/**
 * \brief Search tags for src and dst. Update entries of the tag, remove if necessary
 *
 * \param de_ctx Detect context
 * \param det_ctx Detect thread context
 * \param p packet
 *
 */
void TagHandlePacket(DetectEngineCtx *de_ctx,
        DetectEngineThreadCtx *det_ctx, Packet *p)
{
    /* If there's no tag, get out of here */
    unsigned int current_tags = SC_ATOMIC_GET(num_tags);
    if (current_tags == 0)
        return;

    /* First update and get session tags */
    if (p->flow != NULL) {
        FLOWLOCK_WRLOCK(p->flow);
        TagHandlePacketFlow(p->flow, p);
        FLOWLOCK_UNLOCK(p->flow);
    }

    Host *src = HostLookupHostFromHash(&p->src);
    if (src) {
        if (src->tag != NULL) {
            TagHandlePacketHost(src,p);
        }
        HostRelease(src);
    }
    Host *dst = HostLookupHostFromHash(&p->dst);
    if (dst) {
        if (dst->tag != NULL) {
            TagHandlePacketHost(dst,p);
        }
        HostRelease(dst);
    }
}
/**
 * \brief Make the threshold logic for signatures
 *
 * \param de_ctx Dectection Context
 * \param tsh_ptr Threshold element
 * \param p Packet structure
 * \param s Signature structure
 *
 * \retval 2 silent match (no alert but apply actions)
 * \retval 1 alert on this event
 * \retval 0 do not alert on this event
 */
int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
        const DetectThresholdData *td, Packet *p, const Signature *s, PacketAlert *pa)
{
    SCEnter();

    int ret = 0;
    if (td == NULL) {
        SCReturnInt(0);
    }

    if (td->type == TYPE_SUPPRESS) {
        ret = ThresholdHandlePacketSuppress(p,td,s->id,s->gid);
    } else if (td->track == TRACK_SRC) {
        Host *src = HostGetHostFromHash(&p->src);
        if (src) {
            ret = ThresholdHandlePacketHost(src,p,td,s->id,s->gid,pa);
            HostRelease(src);
        }
    } else if (td->track == TRACK_DST) {
        Host *dst = HostGetHostFromHash(&p->dst);
        if (dst) {
            ret = ThresholdHandlePacketHost(dst,p,td,s->id,s->gid,pa);
            HostRelease(dst);
        }
    } else if (td->track == TRACK_RULE) {
        SCMutexLock(&de_ctx->ths_ctx.threshold_table_lock);
        ret = ThresholdHandlePacketRule(de_ctx,p,td,s,pa);
        SCMutexUnlock(&de_ctx->ths_ctx.threshold_table_lock);
    }

    SCReturnInt(ret);
}
Beispiel #3
0
DWORD WINAPI HashVerifyThread( PTSTR pszPath )
{
	// We will need to free the memory allocated for the data when done
	PBYTE pbRawData;

	// First, activate our manifest and AddRef our host
	ULONG_PTR uActCtxCookie = ActivateManifest(TRUE);
	ULONG_PTR uHostCookie = HostAddRef();

	// Allocate the context data that will persist across this session
	HASHVERIFYCONTEXT hvctx;

	// It's important that we zero the memory since an initial value of zero is
	// assumed for many of the elements
	ZeroMemory(&hvctx, sizeof(hvctx));

	// Prep the path
    HashNormalizeString(pszPath);
	StrTrim(pszPath, TEXT(" "));
	hvctx.pszPath = pszPath;

	// Load the raw data
	pbRawData = HashVerifyLoadData(&hvctx);

	if (hvctx.pszFileData && (hvctx.hList = SLCreateEx(TRUE)))
	{
		HashVerifyParseData(&hvctx);

		DialogBoxParam(
			g_hModThisDll,
			MAKEINTRESOURCE(IDD_HASHVERF),
			NULL,
			HashVerifyDlgProc,
			(LPARAM)&hvctx
		);

		SLRelease(hvctx.hList);
	}
	else if (*pszPath)
	{
		// Technically, we could reach this point by either having a file read
		// error or a memory allocation error, but I really don't feel like
		// doing separate messages for what are supposed to be rare edge cases.
		TCHAR szFormat[MAX_STRINGRES], szMessage[0x100];
		LoadString(g_hModThisDll, IDS_HV_LOADERROR_FMT, szFormat, countof(szFormat));
		wnsprintf(szMessage, countof(szMessage), szFormat, pszPath);
		MessageBox(NULL, szMessage, NULL, MB_OK | MB_ICONERROR);
	}

	free(pbRawData);
	free(pszPath);

	// Clean up the manifest activation and release our host
	DeactivateManifest(uActCtxCookie);
	HostRelease(uHostCookie);

	InterlockedDecrement(&g_cRefThisDll);
	return(0);
}
Beispiel #4
0
DWORD WINAPI HashSaveThread( PHASHSAVECONTEXT phsctx )
{
	// First, activate our manifest and AddRef our host
	ULONG_PTR uActCtxCookie = ActivateManifest(TRUE);
	ULONG_PTR uHostCookie = HostAddRef();

	// Calling HashCalcPrepare with a NULL hList will cause it to calculate
	// and set cchPrefix, but it will not copy the data or walk the directories
	// (we will leave that for the worker thread to do); the reason we do a
	// limited scan now is so that we can show the file dialog (which requires
	// cchPrefix for the automatic name generation) as soon as possible
	phsctx->status = INACTIVE;
	phsctx->hList = NULL;
	HashCalcPrepare(phsctx);

	// Get a file name from the user
	ZeroMemory(&phsctx->ofn, sizeof(phsctx->ofn));
	HashCalcInitSave(phsctx);

	if (phsctx->hFileOut != INVALID_HANDLE_VALUE)
	{
        BOOL bDeletionFailed = TRUE;
		if (phsctx->hList = SLCreateEx(TRUE))
		{
            bDeletionFailed = ! DialogBoxParam(
				g_hModThisDll,
				MAKEINTRESOURCE(IDD_HASHSAVE),
				NULL,
				HashSaveDlgProc,
				(LPARAM)phsctx
			);

			SLRelease(phsctx->hList);
		}

		CloseHandle(phsctx->hFileOut);

        // Should only happen on Windows XP
        if (bDeletionFailed)
            DeleteFile(phsctx->ofn.lpstrFile);
	}

	// This must be the last thing that we free, since this is what supports
	// our context!
	SLRelease(phsctx->hListRaw);

	// Clean up the manifest activation and release our host
	DeactivateManifest(uActCtxCookie);
	HostRelease(uHostCookie);

	InterlockedDecrement(&g_cRefThisDll);
	return(0);
}
Beispiel #5
0
static uint8_t GetHostRepDst(Packet *p, uint8_t cat, uint32_t version) {
    uint8_t val = 0;
    Host *h = NULL;

    if (p->flags & PKT_HOST_DST_LOOKED_UP && p->host_dst == NULL) {
        return 0;
    } else if (p->host_dst != NULL) {
        h = (Host *)p->host_dst;
        HostLock(h);
    } else {
        h = HostLookupHostFromHash(&(p->dst));

        p->flags |= PKT_HOST_DST_LOOKED_UP;

        if (h == NULL) {
            return 0;
        }

        HostReference(&p->host_dst, h);
    }

    if (h->iprep == NULL) {
        HostRelease(h);
        return 0;
    }

    SReputation *r = (SReputation *)h->iprep;

    /* allow higher versions as this happens during
     * rule reload */
    if (r->version >= version)
        val = r->rep[cat];
    else
        SCLogDebug("version mismatch %u != %u", r->version, version);

    HostRelease(h);
    return val;
}
/**
 * \brief Add a tag entry for a host. If it already exist, update it.
 *
 * \param tag_ctx Tag context for hosts
 * \param tde Tag data
 * \param p packet
 *
 * \retval 0 if it was added, 1 if it was updated
 */
int TagHashAddTag(DetectTagDataEntry *tde, Packet *p)
{
    SCEnter();

    uint8_t updated = 0;
    uint16_t num_tags = 0;
    Host *host = NULL;

    /* Lookup host in the hash. If it doesn't exist yet it's
     * created. */
    if (tde->flags & TAG_ENTRY_FLAG_DIR_SRC) {
        host = HostGetHostFromHash(&p->src);
    } else if (tde->flags & TAG_ENTRY_FLAG_DIR_DST) {
        host = HostGetHostFromHash(&p->dst);
    }
    /* no host for us */
    if (host == NULL) {
        return -1;
    }

    if (host->tag == NULL) {
        /* get a new tde as the one we have is on the stack */
        DetectTagDataEntry *new_tde = DetectTagDataCopy(tde);
        if (new_tde != NULL) {
            host->tag = new_tde;
            (void) SC_ATOMIC_ADD(num_tags, 1);
        }
    } else {
        /* Append the tag to the list of this host */

        /* First iterate installed entries searching a duplicated sid/gid */
        DetectTagDataEntry *iter = NULL;

        for (iter = host->tag; iter != NULL; iter = iter->next) {
            num_tags++;
            if (iter->sid == tde->sid && iter->gid == tde->gid) {
                iter->cnt_match++;
                /* If so, update data, unless the maximum MATCH limit is
                 * reached. This prevents possible DOS attacks */
                if (iter->cnt_match < DETECT_TAG_MATCH_LIMIT) {
                    /* Reset time and counters */
                    iter->first_ts = iter->last_ts = tde->first_ts;
                    iter->packets = 0;
                    iter->bytes = 0;
                }
                updated = 1;
                break;
            }
        }

        /* If there was no entry of this rule, append the new tde */
        if (updated == 0 && num_tags < DETECT_TAG_MAX_TAGS) {
            /* get a new tde as the one we have is on the stack */
            DetectTagDataEntry *new_tde = DetectTagDataCopy(tde);
            if (new_tde != NULL) {
                (void) SC_ATOMIC_ADD(num_tags, 1);

                new_tde->next = host->tag;
                host->tag = new_tde;
            }
        } else if (num_tags == DETECT_TAG_MAX_TAGS) {
            SCLogDebug("Max tags for sessions reached (%"PRIu16")", num_tags);
        }
    }

    HostRelease(host);
    SCReturnInt(updated);
}
/**
 * \brief This function is used to match packets via the eDDOS rule
 *
 * \param t pointer to thread vars
 * \param det_ctx pointer to the pattern matcher thread
 * \param p pointer to the current packet
 * \param m pointer to the sigmatch that we will cast into DetectDummyData
 *
 * \retval 0 no match
 * \retval 1 match
 */
int DetecteDDOSMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) {

    int ret = 0;
    DetecteDDOSSig *dsig = (DetecteDDOSSig *) m->ctx;
    DetecteDDOSData *ddata;
    Host *h;
    time_t t1;
    double time_diff_ms;

    if (PKT_IS_PSEUDOPKT(p)
            || !PKT_IS_IPV4(p)
            || p->flags & PKT_HOST_SRC_LOOKED_UP) {
        return 0;
    }

    /* TODO: Inspect the packet contents here.
     * Suricata defines a `Packet` structure in decode.h which already defines 
     * many useful elements -- have a look! */

    h = HostGetHostFromHash(&(p->src)); // Only SRC or can DEST be used too?
    p->flags |= PKT_HOST_SRC_LOOKED_UP;

    if (h == NULL) {
        printf("host not found!\n");
        return 0;
    }

    ddata = (DetecteDDOSData *) h->eddos;
    if (!ddata) {
        /* initialize fresh dummydata */
        ddata = SCMalloc(sizeof (DetecteDDOSData));
        bzero(ddata, sizeof (DetecteDDOSData));
        h->eddos = ddata;
    }
    /**
     * Start counting for evaluation
     */
    (ddata->cnt_packets)++;

    if (PKT_IS_TCP(p)) {
        //counter host
        (ddata->cnt_tcp)++;
        //counter global
        tcp_pkts_gesamt++;
        //printf("\nPakets TCP Flag: %d\n", p->tcph->th_flags);
        if (p->tcph->th_flags == tcp_syn_ack_flag) {
            (ddata->cnt_tcp_syn_ack)++;
            tcp_syn_ack_gesamt++;
            //printf("TCP_SYN_ACK");
        }
        if (p->tcph->th_flags == tcp_fin_ack_flag) {
            (ddata->cnt_tcp_fin_ack)++;
            tcp_fin_ack_gesamt++;
            //printf("TCP_FIN_ACK");
        }
        if (p->tcph->th_flags == TH_SYN) {
            (ddata->cnt_tcp_syn)++;
            tcp_syn_gesamt++;
            //printf("TCP_SYN");

        }
    }

    if (PKT_IS_UDP(p)) {
        (ddata->cnt_udp)++;
        udp_pkt_gesamt++;
    }

    if (PKT_IS_ICMPV4(p) && p->icmpv4h->type == ICMP_ECHO) {
        (ddata->cnt_icmp_echo_req)++;
        icmp_gesamt++;
    }

    /**
     * End Counting
     */
    /**
     * Start evaluation
     */
    if (PKT_IS_UDP(p) || PKT_IS_TCP(p)) {
        t1 = p->ts.tv_sec;
        time_diff_ms = difftime(t1, ddata->PeriodStart);
        if (time_diff_ms > (60)) {
            /*check for alarm here*/
            // abweichung vom 1:2 verhältnis SYN/ACK zu FIN/ACK
            float ver_syn_ack;
            float abw_syn_ack;
            // verhältnis von ICMP echo req paketen zu allen paketen
            float ver_echoreq_norm;
            // verhältnis von udp pakten zu allen paketen
            float ver_udp_norm;
            if (ddata->cnt_tcp_fin_ack != 0) {
                ver_syn_ack = ((float) (ddata->cnt_tcp_syn_ack) / ddata->cnt_tcp_fin_ack);
            } else {
                // we have syn but no syn_acks
                if ((((ddata->cnt_tcp_syn - ddata->cnt_tcp_syn_ack)*2) > dsig->max_abweichung_syn_ack ) && ddata->cnt_tcp_syn > 250) {
                    printf("\nSYN zu SYN/ACK Host\n");
                    printf("\n SYN: %llu SYN/ACK: %llu \n", ddata->cnt_tcp_syn, ddata->cnt_tcp_syn_ack );
                    ver_syn_ack = -1;
                }
                ver_syn_ack = 0;
            }

            abw_syn_ack = (((1 / 2) - ver_syn_ack))*2;
            //printf("\nSYN/ACK zu FIN/ACK Host Value: %f # SYN/ACK: %llu - FIN/ACK: %llu\n", (abw_syn_ack), ddata->cnt_tcp_syn_ack, ddata->cnt_tcp_fin_ack);

            if (abw_syn_ack < 0) {

                // check if abweichung größer als in signatur angegeben
                if (fabs(abw_syn_ack) > dsig->max_abweichung_syn_ack) {
                    ret = 1;
                    printf("\nSYN/ACK zu FIN/ACK Host Value: %f # SYN/ACK: %llu - FIN/ACK: %llu\n", fabs(abw_syn_ack), ddata->cnt_tcp_syn_ack, ddata->cnt_tcp_fin_ack);

                }
            }


            // verhältnis icmp echo request berechnen
            ver_echoreq_norm = ((float) (ddata->cnt_icmp_echo_req) / ddata->cnt_packets)*100;

            // check if ICMP echo request pakete zu viel im verhältnis zu allen
            if (ver_echoreq_norm > (float) (dsig->max_icmp_echo_req_packets)) {
                ret = 1;
                //printf("\nICMP Host\n");
            }
            /**
            // verhältnis udp paketen berechnen
            ver_udp_norm = ((float)(ddata->cnt_udp) / ddata->cnt_packets);
            // check if udp pakete zu viel im verhältnis zu allen
            if ( ver_udp_norm > (float)(dsig->max_udp_packets) ) {
                ret = 1;
            }  
             */
            /**
             * gesamtauswertung 
             */
            time_diff_ms = difftime(t1, start_time);
            if (time_diff_ms > (300)) {
                // auswertung udp pakete
                // verhältnis udp paketen berechnen
                ver_udp_norm = ((float) (udp_pkt_gesamt) / (udp_pkt_gesamt + tcp_pkts_gesamt))*100;
                //printf("UDP Pakete Verhaeltnis: %f", ver_udp_norm);
                // check if udp pakete zu viel im verhältnis zu allen
                if (ver_udp_norm > (float) (dsig->max_verhaeltnis_udp_packets)) {
                    ret = 1;
                    //printf("\nUDP ALL\n");
                }

                // auswertung echo requests
                ver_echoreq_norm = ((float) (icmp_gesamt) / (udp_pkt_gesamt + tcp_pkts_gesamt))*100;
                if (ver_echoreq_norm > (float) (icmp_gesamt)) {
                    ret = 1;
                    printf("\nICMP ALL\n");
                }

                // auswertung syn/ack
                if (tcp_fin_ack_gesamt != 0) {
                    ver_syn_ack = ((float) (tcp_syn_ack_gesamt) / tcp_fin_ack_gesamt);
                } else {
                    // we have syn but no syn_acks
                    if (fabs((float)((tcp_syn_gesamt - tcp_syn_gesamt)*2)) > dsig->max_abweichung_syn_ack) {
                        printf("\nSYN zu SYN/ACK ALL\n");
                        ver_syn_ack = -1;
                    }
                    ver_syn_ack = 0;
                }

                abw_syn_ack = (((1 / 2) - ver_syn_ack))*2;
                if (abw_syn_ack < 0) {
                    // check if abweichung größer als in signatur angegeben
                    if (fabs(abw_syn_ack) > dsig->max_abweichung_syn_ack) {
                        ret = 1;
                        printf("\nSYN/ACK zu FIN/ACK ALL\n");
                    }
                }
                // reset global counter for new interval
                
                tcp_pkts_gesamt = 0;
                udp_pkt_gesamt = 0;
                tcp_fin_ack_gesamt = 0;
                tcp_syn_ack_gesamt = 0;
                icmp_gesamt = 0;
                


            }
            /**printf("host found, packets now %d\n", (int)(ddata->cnt_packets));
            ret = (ddata->cnt_packets > dsig->max_numpackets);
             */

            // reset der parameter, da neuer zeitraum beginnt
            ddata->PeriodStart = p->ts.tv_sec;
            ddata->cnt_icmp_echo_req = 0;
            ddata->cnt_packets = 0;
            ddata->cnt_tcp = 0;
            ddata->cnt_tcp_fin_ack = 0;
            ddata->cnt_tcp_syn_ack = 0;
            ddata->cnt_udp = 0;

        } else {
            ret = 0;
        }
    }
    /**
     * End of evaluation
     */

    //printf("\nHost: %d - %d\n", (int)h, ddata->cnt_packets);
    /**
    printf("#################################\n");
    printf("Host: %d\n",(int)h);
    printf("\n TCP-SYN: %d \n", ddata->cnt_tcp_syn);
    printf("\n TCP-ACK: %d \n", ddata->cnt_tcp_ack);
    printf("\n Packets gesamt: %d \n", ddata->cnt_packets);
    printf("\n Packets TCP gesamt: %d \n", ddata->cnt_tcp);
    printf("\n Packets UDP gesamt: %d \n", ddata->cnt_udp);
    printf("\n ICMP ECHO REQUEST Packets: %d \n", ddata->cnt_icmp_echo_req);
    printf("#################################\n");
    
    printf("\n\nTCP Gesamt: %llu\n",tcp_pkts_gesamt);
    printf("UDP Gesamt: %llu\n",udp_pkt_gesamt);
    printf("SYN: %llu\n",tcp_syn_gesamt);
    printf("ICMP: %llu\n",icmp_gesamt);
    printf("SYN_ACK gesamt %d\n",(int)tcp_syn_ack_gesamt);
    printf("FIN_ACK_gesamt %d\n\n",(int)tcp_fin_ack_gesamt);
    */
    HostRelease(h);
    return ret;
}
Beispiel #8
0
static int DetectThresholdTestSig3(void)
{
    Packet *p = NULL;
    Signature *s = NULL;
    ThreadVars th_v;
    DetectEngineThreadCtx *det_ctx;
    int result = 0;
    int alerts = 0;
    struct timeval ts;
    DetectThresholdEntry *lookup_tsh = NULL;

    HostInitConfig(HOST_QUIET);

    memset (&ts, 0, sizeof(struct timeval));
    TimeGet(&ts);

    memset(&th_v, 0, sizeof(th_v));

    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);

    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
    if (de_ctx == NULL) {
        goto end;
    }

    de_ctx->flags |= DE_QUIET;

    s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold limit\"; threshold: type limit, track by_dst, count 5, seconds 60; sid:10;)");
    if (s == NULL) {
        goto end;
    }

    SigGroupBuild(de_ctx);
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);

    TimeGet(&p->ts);

    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);

    Host *host = HostLookupHostFromHash(&p->dst);
    if (host == NULL) {
        printf("host not found: ");
        goto cleanup;
    }

    if (!(ThresholdHostHasThreshold(host))) {
        HostRelease(host);
        printf("host has no threshold: ");
        goto cleanup;
    }
    HostRelease(host);

    TimeSetIncrementTime(200);
    TimeGet(&p->ts);

    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);

    host = HostLookupHostFromHash(&p->dst);
    if (host == NULL) {
        printf("host not found: ");
        goto cleanup;
    }
    HostRelease(host);

    lookup_tsh = HostGetStorageById(host, ThresholdHostStorageId());
    if (lookup_tsh == NULL) {
        HostRelease(host);
        printf("lookup_tsh is NULL: ");
        goto cleanup;
    }

    alerts = lookup_tsh->current_count;

    if (alerts == 3)
        result = 1;
    else {
        printf("alerts %u != 3: ", alerts);
        goto cleanup;
    }

cleanup:
    SigGroupCleanup(de_ctx);
    SigCleanSignatures(de_ctx);

    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
    DetectEngineCtxFree(de_ctx);
end:
    UTHFreePackets(&p, 1);
    HostShutdown();
    return result;
}