/** * \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); }
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); }
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); }
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; }
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; }