// #if 0 // Don't compile the detection functions if they're not used int rule23039eval(void *p) { const u_int8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:to_server; if(checkFlow(p, rule23039options[0]->option_u.flowFlags) <= 0 ) return RULE_NOMATCH; // content:"|00 01 00 00 00 00|", offset 4, depth 8, fast_pattern; if(contentMatch( p, rule23039options[1]->option_u.content, &cursor_normal ) <= 0) return RULE_NOMATCH; // The last |00| in the match above drops the cursor at the beginning of the first query, // 12 bytes from the beginning of the payload. If the first 2 bits are set on this byte, // it means we're looking at a pointer. In that event, we'll go ahead and flag it, because // we've already verified that there is only one query. return detectDNSloop(sp, cursor_normal ); }
int rule37676eval(void *p) { const uint8_t *cursor_normal = 0, *end_of_buffer; SFSnortPacket *sp = (SFSnortPacket *) p; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:to_server if(checkFlow(p, rule37676options[0]->option_u.flowFlags) <= 0) return RULE_NOMATCH; // content:"|84|", fast_pattern:only; // if(contentMatch(p, rule37676options[1]->option_u.content, &cursor_normal) <= 0) // return RULE_NOMATCH; // content:"|20|", offset 17, depth 1; if(contentMatch(p, rule37676options[2]->option_u.content, &cursor_normal) <= 0) return RULE_NOMATCH; if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_buffer) <= 0) return RULE_NOMATCH; return DetectCiscoIkeBof(sp, cursor_normal, end_of_buffer); }
// #if 0 // Don't compile the detection functions if they're not used int rule18063eval(void *p) { const uint8_t *cursor_normal = 0, *OfficeArtSPContainer = 0, *OfficeArtSpgrContainer = 0, *OfficeArtFSP = 0, *OfficeArtFSPGR = 0; const uint8_t *beg_of_payload = 0, *end_of_payload = 0, *tmp_payload = 0; uint32_t OfficeArtSpgrContainer_size = 0, OfficeArtSPContainer_size = 0; SFSnortPacket *sp = (SFSnortPacket *) p; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_client; if (checkFlow(p, rule18063options[0]->option_u.flowFlags) <= 0 ) { return RULE_NOMATCH; } // flowbits:isset "file.doc"; if (processFlowbits(p, rule18063options[1]->option_u.flowBit) <= 0) { return RULE_NOMATCH; } if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) { return RULE_NOMATCH; } // Start by finding inner container // content:"|0F 00 04 F0|", depth 0, fast_pattern; if (contentMatch(p, rule18063options[3]->option_u.content, &OfficeArtSPContainer) <= 0) { return RULE_NOMATCH; } DEBUG_SO(fprintf(stderr, "OfficeArtSPContainer found: %p\n", OfficeArtSPContainer);) // Find the outer container - This may or may not exist // content:"|0F 00 03 F0|", depth 0; if(contentMatch(p, rule18063options[2]->option_u.content, &OfficeArtSpgrContainer) <= 0) {
int rule35943eval(void *p) { const uint8_t *cursor_normal = 0, *end_of_buffer; SFSnortPacket *sp = (SFSnortPacket *) p; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if(checkFlow(p, rule35943options[0]->option_u.flowFlags) <= 0) return RULE_NOMATCH; // content:"|00 01|", offset 6, depth 2; if(contentMatch(p, rule35943options[2]->option_u.content, &cursor_normal) <= 0) return RULE_NOMATCH; // content:"|00 00 00|", offset 2, depth 3, relative; if(contentMatch(p, rule35943options[3]->option_u.content, &cursor_normal) <= 0) return RULE_NOMATCH; if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_buffer) <= 0) return RULE_NOMATCH; // move cursor to flags // in the TCP case, flags are at offset 4 cursor_normal += 4; return DetectBindTkeyDos(cursor_normal, end_of_buffer); }
// #if 0 // Don't compile the detection functions if they're not used int rule18101eval(void *p) { const uint8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; const uint8_t *end_of_payload; BER_ELEMENT ber_element; if(sp == NULL) return RULE_NOMATCH; // flow:established, to_server; if(checkFlow(p, rule18101options[0]->option_u.flowFlags) <= 0 ) return RULE_NOMATCH; if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_payload) <= 0) return RULE_NOMATCH; BER_DATA(0x30); BER_SKIP(0x02); if(ber_get_element(sp, cursor_normal, &ber_element) < 0) return RULE_NOMATCH; // Exploit condition is SearchRequest (0x63) or ModifyDNRequest (0x6c) with // large size. We're going with 1000 as a max size, apparently. if(ber_element.data_len > 1000 && (ber_element.type == 0x63 || ber_element.type == 0x6c)) return RULE_MATCH; return RULE_NOMATCH; }
void NetwalkWindow::mapViewTileClicked( Widget& o, int x, int y, MouseButtons mb ) { if ( mb.left ) { rotate( x, y, true ); pCliConn = 0; checkFlow(); scoreLabel.setText( Utils::toWString(++pTurns) ); o.updated(); } else if ( mb.right ) { rotate( x, y, false ); pCliConn = 0; checkFlow(); scoreLabel.setText( Utils::toWString(++pTurns) ); o.updated(); } }
void eMP3Decoder::outputReady(int what) { (void)what; singleLock s(lock); // must protect access on all eIOBuffer, position, outputbr if (type != codecMPG) { if ( ( pcmsettings.reconfigure || (pcmsettings.samplerate != audiodecoder->pcmsettings.samplerate) || (pcmsettings.channels != audiodecoder->pcmsettings.channels))) { pcmsettings=audiodecoder->pcmsettings; outputbr=pcmsettings.samplerate*pcmsettings.channels*16; if (::ioctl(dspfd[0], SNDCTL_DSP_SPEED, &pcmsettings.samplerate) < 0) eDebug("SNDCTL_DSP_SPEED failed (%m)"); if (::ioctl(dspfd[0], SNDCTL_DSP_CHANNELS, &pcmsettings.channels) < 0) eDebug("SNDCTL_DSP_CHANNELS failed (%m)"); if (::ioctl(dspfd[0], SNDCTL_DSP_SETFMT, &pcmsettings.format) < 0) eDebug("SNDCTL_DSP_SETFMT failed (%m)"); // eDebug("reconfigured audio interface..."); } } seekbusy-=output.tofile(dspfd[0], 65536); if (seekbusy < 0) seekbusy=0; checkFlow(0); }
void eMP3Decoder::outputReady2(int what) { (void)what; singleLock s(lock); // must protect access on all eIOBuffer, position, outputbr output2.tofile(dspfd[1], 65536); checkFlow(0); }
/* detection functions */ int rule15968eval(void *p) { const uint8_t *cursor_normal = 0, *beg_of_payload, *end_of_payload; SFSnortPacket *sp = (SFSnortPacket *) p; uint32_t MsgLen, stringOffset; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if (checkFlow(p, rule15968options[0]->option_u.flowFlags) > 0 ) { // content:"heal", offset 14, depth 4, fast_pattern; if (contentMatch(p, rule15968options[1]->option_u.content, &cursor_normal) > 0) { // content:"sdfx", depth 4; if (contentMatch(p, rule15968options[2]->option_u.content, &cursor_normal) > 0) { // This protocol is goofy. stringOffset, in the payload, is little endian. // MsgLen, in the header, is big endian. // Vulnerable condition is if stringOffset is less than 0x24 or greater // than MsgLen. if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; if(end_of_payload - beg_of_payload < 38) return RULE_NOMATCH; cursor_normal = beg_of_payload + 34; stringOffset = *cursor_normal++; stringOffset |= *cursor_normal++ << 8; stringOffset |= *cursor_normal++ << 16; stringOffset |= *cursor_normal << 24; //printf("stringOffset = %d (0x%08x)\n", stringOffset, stringOffset); if(stringOffset < 0x24) return RULE_MATCH; cursor_normal = beg_of_payload + 4; MsgLen = *cursor_normal++ << 24; MsgLen |= *cursor_normal++ << 16; MsgLen |= *cursor_normal++ << 8; MsgLen |= *cursor_normal; //printf("MsgLen = %d (0x%08x)\n", MsgLen, MsgLen); if(stringOffset > MsgLen) return RULE_MATCH; // Note there is also a two-byte big endian value PayloadLen at offset 12 // and a four-byte little endian dataLen at offset 18. // We ignore them, because they do not seem relevant to detection. } } } return RULE_NOMATCH; }
/* detection functions */ int rule13308eval(void *p) { const u_int8_t *cursor_normal = 0; const u_int8_t *beg_of_buffer, *end_of_buffer; SFSnortPacket *sp = (SFSnortPacket *) p; // Base64 stuff u_int8_t base64buf[256], decodedbuf[256]; u_int32_t inputchars, base64bytes, decodedbytes; int i; if(sp == NULL) return RULE_NOMATCH; // flow:established, to_server; if (checkFlow(p, rule13308options[0]->option_u.flowFlags) <= 0) return RULE_NOMATCH; // Doing this content match is pretty useless because it's duplicated in our PCRE. // But we want to keep the structure for the pattern matcher. // // content:"Authorization|3A|", depth 0, nocase, fast_pattern; // if (contentMatch(p, rule13308options[1]->option_u.content, &cursor_normal) <= 0) // return RULE_NOMATCH; // pcre:"^Authorization\x3A\s*Basic[ \t]+", dotall, multiline, nocase; if (pcreMatch(p, rule13308options[2]->option_u.pcre, &cursor_normal) <= 0) return RULE_NOMATCH; if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_buffer, &end_of_buffer) != CURSOR_IN_BOUNDS) return RULE_NOMATCH; // At this point, cursor should point to the start of the auth data inputchars = (end_of_buffer > cursor_normal + sizeof(base64buf)) ? sizeof(base64buf) : end_of_buffer - cursor_normal; DEBUG_SO(printf("%d input chars: %*s\n", inputchars, inputchars, cursor_normal)); if(unfold_header(cursor_normal, inputchars, base64buf, sizeof(base64buf), &base64bytes) != 0) return RULE_NOMATCH; DEBUG_SO(printf("Successfully unfolded header (%s)(%d)\n", base64buf, base64bytes)); if(base64decode(base64buf, base64bytes, decodedbuf, sizeof(decodedbuf), &decodedbytes) < 0) return RULE_NOMATCH; DEBUG_SO(printf("Successfully base64 decoded (%s)(%d)\n", decodedbuf, decodedbytes)); for(i=0; i<decodedbytes; i++) { DEBUG_SO(printf("checking byte: %c\n", decodedbuf[i])); if(decodedbuf[i] == '%') { return RULE_MATCH; } else if(decodedbuf[i] == ':') { // Separator between username:password return RULE_NOMATCH; } } return RULE_NOMATCH; }
/* detection functions */ int rule17741eval(void *p) { const uint8_t *cursor_normal = 0, *end_of_payload; SFSnortPacket *sp = (SFSnortPacket *) p; BER_ELEMENT ber_element; BER_ELEMENT req_body; BER_ELEMENT req_body_SEQUENCE; int ret; DEBUG_SO(printf("rule17741eval enter\n")); if(sp == NULL) return RULE_NOMATCH; // flow:to_server; if(checkFlow(p, rule17741options[0]->option_u.flowFlags) <= 0 ) return RULE_NOMATCH; if (getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_payload) <= 0) return RULE_NOMATCH; ret = ber_get_element(sp, cursor_normal, &ber_element); DEBUG_SO(printf("First element type 0x%02x\n", ber_element.type)); if(ret < 0 || ((ber_element.type != 0x6a) && (ber_element.type != 0x6c))) return RULE_NOMATCH; // We want to delve into this element cursor_normal = ber_element.data.data_ptr; BER_DATA(0x30); // SEQUENCE BER_SKIP(0xA1); // pvno [1] INTEGER (5) BER_SKIP(0xA2); // msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --) // if optional PA-DATA exists, skip it // 10 1 00011 (context-specific, structured, tag number 3) if (cursor_normal < end_of_payload && *cursor_normal == 0xA3) BER_SKIP(0xA3); // padata [3] SEQUENCE OF PA-DATA OPTIONAL // req-body [4] KDC-REQ-BODY // req-body is defined as SEQUENCE and if req-body's data size is not equal to // the total size of SEQUENCE, it is malicious ret = ber_get_element(sp, cursor_normal, &req_body); if (ret < 0) return RULE_NOMATCH; BER_DATA(0xA4); ret = ber_get_element(sp, cursor_normal, &req_body_SEQUENCE); if (ret < 0) return RULE_NOMATCH; DEBUG_SO(printf("req_body.data_len = 0x%08x, req_body_SEQUENCE.specified_total_len = 0x%08x\n", req_body.data_len, req_body_SEQUENCE.specified_total_len);) if (req_body.data_len != req_body_SEQUENCE.specified_total_len)
/* detection functions */ int rule16396eval(void *p) { const uint8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; const uint8_t *beg_of_payload, *end_of_payload; uint32_t length = 0; uint16_t WCT; uint16_t BCC; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if (checkFlow(p, rule16396options[0]->option_u.flowFlags) > 0 ) { // content:"|FF|SMBr", offset 4, depth 5, fast_pattern; if (contentMatch(p, rule16396options[1]->option_u.content, &cursor_normal) > 0) { if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; // isdataat:offset 30, relative; if (cursor_normal + 30 <= end_of_payload) { //Extract length from Netbios session header //Previous content match assures us no buffer underread length = *(cursor_normal-8) << 16; length |= *(cursor_normal-7) << 8; length |= *(cursor_normal-6); //Extract WCT Word Count //Word Count should be usually be zero in negotiate requests //But we need to be able to handle the case where there is //some value in there. cursor_normal += 27; WCT = 2 * *cursor_normal++; cursor_normal += WCT; //Make sure there is enough room to extract BCC if (cursor_normal + 2 > end_of_payload) return RULE_NOMATCH; //Extract BCC Byte Count BCC = read_little_16_inc(cursor_normal); //Alert if your netbios session size is bigger than //Byte count + number of words * 2 + 32-byte SMB header //+ 3 bytes (1 for the WCT field, and 2 for the BCC field) if (length > (BCC + WCT + 35)) return RULE_MATCH; } } } return RULE_NOMATCH; }
/* detection functions */ int rule16180eval(void *p) { const u_int8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; const u_int8_t *beg_of_payload, *end_of_payload; const u_int8_t *end_of_CommonName; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_client; if (checkFlow(p, rule16180options[0]->option_u.flowFlags) > 0 ) { // content:"|16 03|", depth 0; if (contentMatch(p, rule16180options[1]->option_u.content, &cursor_normal) > 0) { // content:"U|04 03|", depth 0, relative, fast_pattern; if (contentMatch(p, rule16180options[2]->option_u.content, &cursor_normal) > 0) { if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; // Skip single byte type value, we're not checking it cursor_normal++; if(cursor_normal + 1 > end_of_payload) return RULE_NOMATCH; // Extract one-byte length value and use it to set end_of_CommonName end_of_CommonName = cursor_normal + *cursor_normal + 1; // Skip length value cursor_normal++; // Ensure we don't go past the end of the payload if (end_of_payload < end_of_CommonName) { end_of_CommonName = end_of_payload; } // Zip through the field, stop at end or NULL while ((cursor_normal < end_of_CommonName) && (*cursor_normal++)) { // empty loop } // If we stop before the end, there was a NULL so alert if (cursor_normal < end_of_CommonName) { return RULE_MATCH; } } } } return RULE_NOMATCH; }
/* detection functions */ int rule19187eval(void *p) { const u_int8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; u_int16_t flags, num_of_answers, data_len; const u_int8_t *beg_of_payload, *end_of_payload; const u_int8_t *start_hostent, *end_hostent; int i; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:to_client; if (checkFlow(p, rule19187options[0]->option_u.flowFlags) > 0 ) { if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; // Ensure we have enough data // txid, flags, num records * 4, query response (unk), at least 256 bytes of hostent // So, at least 300 bytes, I guess. DEBUG_SO(printf("Payload size = %d\n", (int)(end_of_payload - beg_of_payload));) if(end_of_payload - beg_of_payload < 300) return RULE_NOMATCH; // Forcing to be only one response entry // content:"|00 01|", offset 4, depth 2, fast_pattern; if (contentMatch(p, rule19187options[1]->option_u.content, &cursor_normal) <= 0) { return RULE_NOMATCH; } // Now, let's make sure this is actually a standard query response. // Our content match above ensures we have requisite data. flags = *(cursor_normal - 4) << 8; flags |= *(cursor_normal - 3); if((flags & 0xFA0F) != 0x8000) { // 1 bit - response (1 = response) // 4 bits - opcode (0000 = standard query) // 1 bit - authoritative (don't care) // 1 bit - truncated (0 = not truncated) // 5 bits - recursion and other don't cares // 4 bits - reply code (0000 = no error) return RULE_NOMATCH; } // Get number of answers num_of_answers = *cursor_normal++ << 8; num_of_answers |= *cursor_normal; DEBUG_SO(printf("We have %d answers\n", num_of_answers);)
int ruleMYSQL_COM_TABLE_DUMPeval(void *p) { const uint8_t *cursor_normal = 0, *beg_of_payload = 0, *end_of_payload = 0; uint32_t packet_length; uint8_t db_name_length, table_name_length; SFSnortPacket *sp = (SFSnortPacket *) p; // flow:established, to_server; if(checkFlow(p, ruleMYSQL_COM_TABLE_DUMPoptions[0]->option_u.flowFlags) > 0 ) { /* Make sure the packet is long enough */ if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; if((end_of_payload - beg_of_payload) < 6) return RULE_NOMATCH; // content:"|13|", depth 1; offset 4; if(contentMatch(p, ruleMYSQL_COM_TABLE_DUMPoptions[1]->option_u.content, &cursor_normal) > 0) { // Grab the size of the "packet" -- this is the size (in bytes) of // data after the message number byte, including the command byte // Packet size is 3 bytes, little endian packet_length = beg_of_payload[0]; packet_length += beg_of_payload[1] << 8; packet_length += beg_of_payload[2] << 16; // Grab the length of the DB Name db_name_length = beg_of_payload[5]; // if db name length > packet length (+2 for length and command // bytes), flag if((db_name_length + 2) > packet_length) { return RULE_MATCH; } else { // else grab table name length // table_name_length is at offset of db_name + db_name_length // + size byte if((end_of_payload - beg_of_payload) < 5 + db_name_length + 2) return RULE_NOMATCH; table_name_length = beg_of_payload[5 + db_name_length + 1]; // if table name length + db name length + size bytes // + command byte > packet length, flag if((db_name_length + table_name_length + 3) > packet_length) return RULE_MATCH; } } } return RULE_NOMATCH; }
/* detection functions */ int rule13897eval(void *p) { const u_int8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; const u_int8_t *beg_of_payload, *end_of_payload; u_int32_t atom_size; u_int16_t region_size; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_client; if(checkFlow(p, rule13897options[0]->option_u.flowFlags) > 0 ) { // flowbits:isset "file.quicktime"; if(processFlowbits(p, rule13897options[1]->option_u.flowBit) > 0) { // content:"crgn"; if(contentMatch(p, rule13897options[2]->option_u.content, &cursor_normal) > 0) { if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; if(cursor_normal + 2 >= end_of_payload) return RULE_NOMATCH; region_size = (*cursor_normal++) << 8; region_size |= *cursor_normal++; DEBUG_WRAP(printf("REGION SIZE: %d\n", region_size)); cursor_normal = cursor_normal - 10; if(cursor_normal < beg_of_payload) return RULE_NOMATCH; atom_size = (*cursor_normal++) << 24; atom_size |= (*cursor_normal++) << 16; atom_size |= (*cursor_normal++) << 8; atom_size |= *cursor_normal++; DEBUG_WRAP(printf("ATOM SIZE: %d\n", atom_size)); // Changed from region_size > (atom_size - 8) to avoid // integer underflow from (atom_size - 8) if(((u_int32_t)region_size + 8) > atom_size) return RULE_MATCH; } } } return RULE_NOMATCH; }
/* detection functions */ int ruleCITRIX_METAFRAME_BOeval(void *p) { const uint8_t *cursor_normal = 0, *beg_of_payload, *end_of_payload; const uint8_t *cursor_extract = 0; uint32_t event_data_length, description_length, encr_data_length; SFSnortPacket *sp = (SFSnortPacket *) p; // flow:established, to_server; if (checkFlow(p, ruleCITRIX_METAFRAME_BOoptions[0]->option_u.flowFlags) > 0 ) { // content:"A|80 00 00 02|", offset 28, depth 5; if (contentMatch(p, ruleCITRIX_METAFRAME_BOoptions[1]->option_u.content, &cursor_normal) > 0) { // byte_test:size 4, value 16, operator <, offset 4, endian little; if (byteTest(p, ruleCITRIX_METAFRAME_BOoptions[2]->option_u.byte, cursor_normal) > 0) { if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; if((end_of_payload - beg_of_payload) < 0x28) return RULE_NOMATCH; // Extract Event Data Length ( 4 bytes little endian ) cursor_extract = &(beg_of_payload[0x0008]); event_data_length = (*cursor_extract++) & 0xFF; event_data_length |= ((*cursor_extract++) & 0xFF) << 8; event_data_length |= ((*cursor_extract++) & 0xFF) << 16; event_data_length |= ((*cursor_extract++) & 0xFF) << 24; // Extract Description Length ( 2 bytes little endian ) cursor_extract = &(beg_of_payload[0x0022]); description_length = (*cursor_extract++) & 0xFF; description_length |= ((*cursor_extract++) & 0xFF) << 8; // extract Encrypted Data Length ( 4 bytes little endian ) cursor_extract = &(beg_of_payload[0x00024]); encr_data_length = (*cursor_extract++) & 0xFF; encr_data_length |= ((*cursor_extract++) & 0xFF) << 8; encr_data_length |= ((*cursor_extract++) & 0xFF) << 16; encr_data_length |= ((*cursor_extract++) & 0xFF) << 24; if(description_length + encr_data_length > event_data_length) return RULE_MATCH; } } } return RULE_NOMATCH; }
/* detection functions */ int rule14646eval(void *p) { const uint8_t *cursor_normal = 0, *end_of_payload; SFSnortPacket *sp = (SFSnortPacket *) p; int retval; BER_ELEMENT element; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if(checkFlow(p, rule14646options[0]->option_u.flowFlags) <= 0 ) return RULE_NOMATCH; if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_payload) <= 0) return RULE_NOMATCH; // Universal Sequence if(ber_point_to_data(sp, &cursor_normal, 0x30) < 0) return RULE_NOMATCH; // message ID if(ber_skip_element(sp, &cursor_normal, 0x02) < 0) return RULE_NOMATCH; // search request if(ber_point_to_data(sp, &cursor_normal, 0x63) < 0) return RULE_NOMATCH; // Here's the meat retval = ber_get_element(sp, cursor_normal, &element); if(retval == -1) return RULE_NOMATCH; //DEBUG_WRAP(printf("found baseObject string. checking values type=0x%02x size=%d\n", element.type, element.data_len)); /* vuln is 0x43 + len(baseObject first part) + 3 * len(baseObject dc) > 0xFFA We simplify to data_len > 1200 since that's more than reasonable and shortest possible length to exploit is len(baseObject) == len(d) == 1363 */ if(element.type == 0x04 && ((element.data_len > 1200) || (retval == -2))) return RULE_MATCH; return RULE_NOMATCH; }
/* detection functions */ int rule15149eval(void *p) { const uint8_t *cursor_normal = 0, *end_of_payload; SFSnortPacket *sp = (SFSnortPacket *) p; int retval; BER_ELEMENT element; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if (checkFlow(p, rule15149options[0]->option_u.flowFlags) <= 0 ) { return RULE_NOMATCH; } if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_payload) <= 0) return RULE_NOMATCH; // Universal Sequence if(ber_point_to_data(sp, &cursor_normal, 0x30) < 0) return RULE_NOMATCH; // message ID if(ber_skip_element(sp, &cursor_normal, 0x02) < 0) return RULE_NOMATCH; // find the bind request if(ber_point_to_data(sp, &cursor_normal, 0x60) < 0) return RULE_NOMATCH; /* bind requests are defined as: int version LDAPDN name auth authenticationChoice bug here is if the version element is specified as a cursor (0x30) vs. an int (0x02) */ retval = ber_get_element(sp, cursor_normal, &element); if(retval == -1) return RULE_NOMATCH; if(element.type == 0x30) return RULE_MATCH; return RULE_NOMATCH; }
/* detection functions */ int rule23847eval(void *p) { const u_int8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; const u_int8_t *end_of_payload = 0; const u_int8_t *beg_of_payload = 0; const u_int8_t *beg_of_servers = 0; const u_int8_t *start_of_smb = 0; int16_t converter = 0; int16_t server_comment = 0; int16_t server_comment_position = 0; u_int32_t entries = 0; u_int32_t netbios_message_length = 0; int i; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_client; if (checkFlow(p, rule23847options[0]->option_u.flowFlags) <= 0 ) return RULE_NOMATCH; // Verify we are looking at an SMB Trans (0x25) response. // Verify the SMB Request was STATUS_SUCCESS (0x00000000) // content:"|FF|SMB|25 00 00 00 00|", depth 0, fast_pattern; if (contentMatch(p, rule23847options[1]->option_u.content, &cursor_normal) <= 0) return RULE_NOMATCH; // Verify LANMAN protocol is reporting additional data available. // content:"|EA 00|", offset 47, depth 2, relative; if(contentMatch(p, rule23847options[2]->option_u.content, &cursor_normal) <= 0) return RULE_NOMATCH; // Get the beginning of payload and end of payload positions. if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; start_of_smb = beg_of_payload + 4; // Beginning of 9-byte content match netbios_message_length = READ_BIG_16(beg_of_payload + 2); // 2 byte size field DEBUG_SO(fprintf(stderr,"\nnetbios_message_length: %d\n", netbios_message_length);)
/* detection functions */ int rule15329eval(void *p) { const u_int8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; u_int8_t countOne = 0; u_int8_t countTwo = 0; const u_int8_t *beg_of_payload, *end_of_payload; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if (checkFlow(p, rule15329options[0]->option_u.flowFlags) > 0 ) { // content:"MODPROPS"; nocase; if (contentMatch(p, rule15329options[1]->option_u.content, &cursor_normal) > 0) { if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; while ((cursor_normal < end_of_payload) && (*cursor_normal != '\r') && (*cursor_normal != '\n')) { if (*cursor_normal == ',') { countOne++; } cursor_normal++; } if (contentMatch(p, rule15329options[2]->option_u.content, &cursor_normal) > 0) { while ((cursor_normal < end_of_payload) && (*cursor_normal != '\r') && (*cursor_normal != '\n')) { if (*cursor_normal == ',') { countTwo++; } cursor_normal++; } } // Yes, technically these are both off-by-one on the count...but why waste the CPU // necessary to increment them both when leaving them as-is yields the same result? if (countTwo > countOne) { return RULE_MATCH; } } } return RULE_NOMATCH; }
int rule23040eval(void *p) { const u_int8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if(checkFlow(p, rule23040options[0]->option_u.flowFlags) <= 0 ) return RULE_NOMATCH; // content:"|00 01 00 00 00 00 00 00|", offset 6, depth 8, fast_pattern; if(contentMatch(p, rule23040options[1]->option_u.content, &cursor_normal) <= 0) return RULE_NOMATCH; return detectDNSloop( sp, cursor_normal ); }
/* detection functions */ int rule13469eval(void *p) { const uint8_t *cursor_normal = 0; const uint8_t *beg_of_payload, *end_of_payload; uint32_t length; SFSnortPacket *sp = (SFSnortPacket *) p; // flow:established, to_client; if (checkFlow(p, rule13469options[0]->option_u.flowFlags) > 0 ) { // flowbits:isset "file.doc"; if (processFlowbits(p, rule13469options[1]->option_u.flowBit) > 0) { // content:"bjbj"; if (contentMatch(p, rule13469options[2]->option_u.content, &cursor_normal) > 0) { // content:"|00 00 00 00|", offset 62, depth 4, relative; if (!(contentMatch(p, rule13469options[3]->option_u.content, &cursor_normal) > 0)) { if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; // At this point, cursor_normal is still right after bjbj because negative // content matches do not move the pointer // Start custom detection here if((cursor_normal + 572) > end_of_payload) return RULE_NOMATCH; cursor_normal += 568; length = *cursor_normal++; length |= *cursor_normal++ << 8; length |= *cursor_normal++ << 16; length |= *cursor_normal++ << 24; if((length - 4) % 0x1a) return RULE_MATCH; } } } } return RULE_NOMATCH; }
/* detection functions */ int rule15148eval(void *p) { const u_int8_t *cursor_normal = 0, *beg_of_payload, *end_of_payload; SFSnortPacket *sp = (SFSnortPacket *) p; u_int16_t data_len; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if (checkFlow(p, rule15148options[0]->option_u.flowFlags) > 0 ) { // content:"RCH0", depth 4, nocase; if (contentMatch(p, rule15148options[1]->option_u.content, &cursor_normal) > 0) { // content:"RCHE", offset 4, depth 4, nocase, relative; if (contentMatch(p, rule15148options[2]->option_u.content, &cursor_normal) > 0) { cursor_normal = cursor_normal - 8; data_len = *cursor_normal++; data_len |= (*cursor_normal++) << 8; if(data_len >= 130) return RULE_MATCH; if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; // Normally, we'd be nervous about this check with TCP, but given the // packet sizes involved, we'll take the false positives from segmentation // on such a small packet. if(cursor_normal + 6 + data_len != end_of_payload) return RULE_MATCH; } } } return RULE_NOMATCH; }
/* detection functions */ int rule17697eval(void *p) { const uint8_t *cursor_normal = 0; const uint8_t *beg_of_buffer, *end_of_buffer; uint8_t decodedbuf[MAX_BASE64_BUFFER_SIZE], *decodedbuf_ptr; uint32_t inputchars, decodedbytes; SFSnortPacket *sp = (SFSnortPacket *) p; uint32_t tmpval = 0; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if (checkFlow(p, rule17697options[0]->option_u.flowFlags) > 0 ) { // content:"-----BEGIN PGP MESSAGE-----", depth 0, nocase, fast_pattern; if (contentMatch(p, rule17697options[1]->option_u.content, &cursor_normal) > 0) { DEBUG_SO(printf("Matched the PGP header\n")); // content:"Version|3A|", offset 2, depth 8, nocase, relative; if (contentMatch(p, rule17697options[2]->option_u.content, &cursor_normal) > 0) { DEBUG_SO(printf("Matched the version\n")); // content:"|0D 0A 0D 0A|", depth 0, relative; if (contentMatch(p, rule17697options[3]->option_u.content, &cursor_normal) > 0) { DEBUG_SO(printf("Matched the newline\n")); if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_buffer, &end_of_buffer) != CURSOR_IN_BOUNDS) return RULE_NOMATCH; // We should now be at the beginning of the PGP data // Four base64 input chars become three output chars inputchars = (end_of_buffer > cursor_normal + (sizeof(decodedbuf) * 4 / 3)) ? (sizeof(decodedbuf) * 4 / 3) : end_of_buffer - cursor_normal; DEBUG_SO(printf("Decoding %d bytes\n", inputchars)); // Only need 6 output bytes, plus 1 byte for the NULL added by base64decode() if(base64decode(cursor_normal, inputchars, decodedbuf, 7, &decodedbytes) < 0) { DEBUG_SO(printf("Failed to decode any data to work with\n")); return RULE_NOMATCH; } DEBUG_SO(printf("Decoded %d bytes\n", decodedbytes)); // Make sure we have enough data to work with if(decodedbytes >= 6) { decodedbuf_ptr = decodedbuf; // New format with content tag of 16 or 61 (both in the first byte) DEBUG_SO(printf("Packet format: %01x\n", decodedbuf[0])); // The top two bits are set, the lower six we want to be either 16 or 61. // 0xC0 + 16 = 0xD0, 0xC0 + 61 = 0xFD if((decodedbuf[0] == (uint8_t)0xD0) || (decodedbuf[0] == (uint8_t)0xFD)) { if(decodedbuf[1] == 0xFF) { decodedbuf_ptr = decodedbuf + 2; tmpval = *decodedbuf_ptr++; tmpval |= *decodedbuf_ptr++ << 8; tmpval |= *decodedbuf_ptr++ << 16; tmpval |= *decodedbuf_ptr++ << 24; DEBUG_SO(printf("Packet Size: 0x%08x\n", tmpval)); if((tmpval >= 0xF9FFFFFF) && (tmpval <= 0xFEFFFFFF)) { return RULE_MATCH; } } } } } } } } return RULE_NOMATCH; }
/* detection functions */ int rule13666eval(void *p) { const uint8_t *cursor_normal = 0, *cursor_offBmi; SFSnortPacket *sp = (SFSnortPacket *) p; const uint8_t *record_size_ptr, *beg_of_payload, *end_of_payload; uint32_t recordType, offBmi, bcSize; uint16_t bcWidth,bcHeight,bcPlanes,bcBitCount; uint64_t Value; // For storing exploit calculations if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_client; if (checkFlow(p, rule13666options[0]->option_u.flowFlags) <= 0 ) return RULE_NOMATCH; // flowbits:isset "file.emf"; if (processFlowbits(p, rule13666options[1]->option_u.flowBit) <= 0) return RULE_NOMATCH; // content:" EMF|00 00 01 00|"; if (contentMatch(p, rule13666options[2]->option_u.content, &cursor_normal) > 0) { // content:"|01 00 00 00|", offset -48, depth 4, relative; if (contentMatch(p, rule13666options[3]->option_u.content, &cursor_normal) > 0) { // byte_jump:size 4, relative, endian little; if (byteJump(p, rule13666options[4]->option_u.byte, &cursor_normal) > 0) { if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; // Now we're at the start of records. Find the interesting ones. while(cursor_normal < end_of_payload) { // We point to record size so we're at the right state for the relative jump // if it turns out the record doesn't have a BITMAPCOREHEADER. record_size_ptr = cursor_normal - 4; // content:"|5E 00 00 00|", offset -8, depth 4, relative; XXX /* EMR_CREATEDIBPATTERNBRUSHPT */ if (contentMatch(p, rule13666options[5]->option_u.content, &cursor_normal) > 0 // content:"|51 00 00 00|", offset -8, depth 4, relative; XXX /* EMR_STRETCHDIBITS */ || (contentMatch(p, rule13666options[6]->option_u.content, &cursor_normal) > 0)) { recordType = *(cursor_normal - 4); switch(recordType) { case EMR_CREATEDIBPATTERNBRUSHPT: DEBUG_SO(printf("matched EMR_CREATEDIBPATTERNBRUSHPT\n");) if (cursor_normal + 28 > end_of_payload) // Make sure there's enough room return RULE_NOMATCH; // extract offset to BITMAPCOREHEADER. can't use byte_jump because it could put us // past end of packet since the "jump" actually starts from an earlier offset cursor_offBmi = cursor_normal + 12; offBmi = read_little_32(cursor_offBmi); break; case EMR_STRETCHDIBITS: DEBUG_SO(printf("matched EMR_STRETCHDIBITS\n");) if (cursor_normal + 60 > end_of_payload) return RULE_NOMATCH; // read offBmiSrc field cursor_offBmi = cursor_normal + 44; offBmi = read_little_32(cursor_offBmi); break; default: DEBUG_SO(printf("This case must not happen\n");) return RULE_NOMATCH; } if (offBmi + cursor_normal - 4 < cursor_normal) // check integer overflow return RULE_NOMATCH; // move cursor to the beginning of a device independent bitmap (DIB) DEBUG_SO(printf("offBmi=0x%08x\n", offBmi);) cursor_normal += offBmi - 4; if(cursor_normal + 12 > end_of_payload) return RULE_NOMATCH; // match size of BITMAPCOREHEADER to determine if it's the proper structure bcSize = read_little_32(cursor_normal); cursor_normal += 4; DEBUG_SO(printf("bcSize=0x%08x\n", bcSize);) if (bcSize == 12) // checks BITMAPCOREHEADER
/* detection functions */ int rule16394eval(void *p) { const uint8_t *cursor_normal = 0; SFSnortPacket *sp = (SFSnortPacket *) p; const uint8_t *cursor_padata; BER_ELEMENT ber_element; int retval; uint32_t renew_realm_len; const uint8_t *renew_realm_str; uint32_t ticket_realm_len; const uint8_t *ticket_realm_str; DEBUG_SO(int i); DEBUG_SO(printf("rule16394eval enter\n")); if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if(checkFlow(p, rule16394options[0]->option_u.flowFlags) <= 0) return RULE_NOMATCH; // For speed and for ease of programming, we take advantage of some content matches // here in some places at the expense of false negatives. // But they do also to give us a nice content match. // This content match skips over a few items then matches on Kerberos protocol // version (pvno) 5 and mesg type TGS-REQ (12) // content:"|A1 03 02 01 05 A2 03 02 01 0C|", payload raw, depth 22, fast_pattern; if(contentMatch(p, rule16394options[1]->option_u.content, &cursor_normal) <= 0) return RULE_NOMATCH; // Save the pointer so we can come back here, and we're going to jump ahead to make // sure this is a renew packet as well as store the pointer to and size of the // renewal realm cursor_padata = cursor_normal; BER_SKIP(0xa3); // This is a wrapper to ber_skip_element() that NOMATCH's on failure // We should now be at the start of the KDC_REQ_BODY BER_DATA(0xa4); // This is a wrapper to ber_point_to_data() that NOMATCH's on failure BER_DATA(0x30); // We're going to cheat again here and do a quick content match. // Plus, this is our fast pattern match. // content:"|A0 07 03 05 00 00 00 00 02|", payload raw, depth 9, relative, fast_pattern; if(contentMatch(p, rule16394options[2]->option_u.content, &cursor_normal) <= 0) return RULE_NOMATCH; BER_DATA(0xa2); // Grab the piece of data we've been looking for retval = ber_get_element(sp, cursor_normal, &ber_element); // Type 0x1b is essentially a string. Don't know why it's not type 0x04. // Negative return value means error. 0 means 0 data bytes and therefore useless. // Also make sure there is the full amount of data present. if((retval <= 0) || (ber_element.type != 0x1b) || (retval < ber_element.data_len)) return RULE_NOMATCH; renew_realm_len = ber_element.data_len; renew_realm_str = ber_element.data.data_ptr; DEBUG_SO(for(i=0; i<renew_realm_len; i++) printf("%c", renew_realm_str[i]); printf("\n")); // Now that we have our renew_realm info and we've verified the data is complete, // Let's go back to the beginning and get our ticket_realm information cursor_normal = cursor_padata; // This is a very long list. Glad we made sure we were in a renewal packet and // had all of the data we need before we bother with this. :) BER_DATA(0xa3); BER_DATA(0x30); BER_DATA(0x30); BER_SKIP(0xa1); BER_DATA(0xa2); BER_DATA(0x04); BER_DATA(0x6e); BER_DATA(0x30); BER_SKIP(0xa0); BER_SKIP(0xa1); BER_SKIP(0xa2); BER_DATA(0xa3); BER_DATA(0x61); BER_DATA(0x30); BER_SKIP(0xa0); BER_DATA(0xa1); // Same code and checks as above for our ticket/home realm retval = ber_get_element(sp, cursor_normal, &ber_element); if((retval <= 0) || (ber_element.type != 0x1b) || (retval < ber_element.data_len)) return RULE_NOMATCH; ticket_realm_len = ber_element.data_len; ticket_realm_str = ber_element.data.data_ptr; DEBUG_SO(for(i=0; i<ticket_realm_len; i++) printf("%c", ticket_realm_str[i]); printf("\n")); // Match if the realm names are different (either lens are diff or value is diff) if(ticket_realm_len != renew_realm_len || memcmp(ticket_realm_str, renew_realm_str, ticket_realm_len)) return RULE_MATCH; return RULE_NOMATCH; }
/* detection functions */ int rule16375eval(void *p) { const u_int8_t *cursor_normal = 0, *beg_of_payload, *end_of_payload; SFSnortPacket *sp = (SFSnortPacket *) p; BER_ELEMENT ber_element; const u_int8_t *end_of_string; u_int32_t namelen = 0; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; // flow:established, to_server; if(checkFlow(p, rule16375options[0]->option_u.flowFlags) <= 0) return RULE_NOMATCH; // Initialize our pointer if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; // Universal Sequence if(ber_point_to_data(sp, &cursor_normal, 0x30) < 0) return RULE_NOMATCH; // Message ID if(ber_skip_element(sp, &cursor_normal, 0x02) < 0) return RULE_NOMATCH; // Search Request if(ber_point_to_data(sp, &cursor_normal, 0x66) < 0) return RULE_NOMATCH; // Object if(ber_get_element(sp, cursor_normal, &ber_element) < 0) return RULE_NOMATCH; // Make sure it's a string if(ber_element.type != 0x04) return RULE_NOMATCH; // Move the cursor to the start of the string data cursor_normal = ber_element.data.data_ptr; end_of_string = cursor_normal + ber_element.data_len; // Check for end of buffer if(end_of_string > end_of_payload) end_of_string = end_of_payload; // Now we have cursor_normal pointing to the start of the // string and end_of_string set appropriately. Now, // let's see how long the parameter names are. while(cursor_normal < end_of_string) { if(*cursor_normal != '=') namelen++; else { DEBUG_SO(printf("rule16375: namelen=%d\n", namelen)); if(namelen > 100) return RULE_MATCH; // Length is fine. Set back to zero. namelen = 0; // Now jump over the value while((cursor_normal < end_of_string) && (*cursor_normal != ',')) cursor_normal++; } cursor_normal++; } // If we were in the middle of an overly long parameter name // when we ran out of data, match. if(namelen > 100) return RULE_MATCH; return RULE_NOMATCH; }
int ruleIMAIL_LDAPeval(void *p) { u_int32_t current_byte = 0; u_int32_t width, value, lengthwidth; int retval; u_int32_t payload_len; const u_int8_t *cursor_normal, *beg_of_payload, *end_of_payload; SFSnortPacket *sp = (SFSnortPacket *) p; if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; /* call flow match */ if (checkFlow(sp, ruleIMAIL_LDAPoptions[0]->option_u.flowFlags) <= 0 ) return RULE_NOMATCH; /* call content match */ if (contentMatch(sp, ruleIMAIL_LDAPoptions[1]->option_u.content, &cursor_normal) <= 0) { return RULE_NOMATCH; } if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; payload_len = end_of_payload - beg_of_payload; if(payload_len < 10) /* Minimum bind request length */ return RULE_NOMATCH; /* our contentMatch already assures us the first byte is \x30, so just jump over it */ current_byte++; /* Begin packet structure processing */ /* Packet length (only care about width of the specifier) */ if(beg_of_payload[current_byte] & 0x80) { current_byte += beg_of_payload[current_byte] & 0x0F; /* Does imail do this properly? */ } current_byte++; /* Message number (only care about width of the specifier) */ if(payload_len < current_byte + 8) return RULE_NOMATCH; if(beg_of_payload[current_byte] != 0x02) /* Int data type */ return RULE_NOMATCH; current_byte++; /* int width specifier */ if(beg_of_payload[current_byte] & 0x80) { width = beg_of_payload[current_byte] & 0x0F; current_byte++; if(payload_len < current_byte + width) return RULE_NOMATCH; retval = process_val(&(beg_of_payload[current_byte]), width, &value); if(retval < 0) return RULE_NOMATCH; /* width is either 0 or > 4 */ current_byte += width; /* width of data width specifier */ current_byte += value; /* width of data itself */ } else { current_byte += beg_of_payload[current_byte] + 1; } /* Bind request */ if(payload_len < current_byte + 5) return RULE_NOMATCH; if(beg_of_payload[current_byte] != 0x60) return RULE_NOMATCH; current_byte++; /* Message length (only care about width of the specifier) */ if(beg_of_payload[current_byte] & 0x80) { current_byte += beg_of_payload[current_byte] & 0x0F; } current_byte++; /* ldap version */ if(payload_len < current_byte + 3) return RULE_NOMATCH; /* ldap version */ if(beg_of_payload[current_byte] != 0x02) /* Int data type */ return RULE_NOMATCH; current_byte++; /* Now check for funkiness with the version field */ /* Get width of version number */ if(beg_of_payload[current_byte] & 0x80) { /* Excess bits in the high nibble */ if(beg_of_payload[current_byte] & 0x70) return RULE_MATCH; lengthwidth = beg_of_payload[current_byte] & 0x0F; current_byte++; if(payload_len < current_byte + lengthwidth) return RULE_NOMATCH; retval = process_val(&(beg_of_payload[current_byte]), lengthwidth, &value); if(retval < 0) return RULE_MATCH; /* Something screwy's going on around here */ width = value; current_byte += lengthwidth; } else { width = beg_of_payload[current_byte]; current_byte++; } if(payload_len < current_byte + width) return RULE_NOMATCH; /* In this case, if the version value is this fubar, trigger */ retval = process_val(&(beg_of_payload[current_byte]), width, &value); if(retval < 0) return RULE_MATCH; /* LDAP version > 9 (currently, should be 1-3) */ if(value > 9) return RULE_MATCH; return RULE_NOMATCH; }
static int rule13921eval(void *p) { SFSnortPacket *sp = (SFSnortPacket *)p; const u_int8_t *cursor, *beg_of_payload, *end_of_payload; int16_t lm_x; int n; /* cruft */ /* Data for holding our base64 data */ u_int8_t decoded_data[16]; u_int32_t num_bytes_extracted; /* General sanity checking */ if(sp == NULL) return RULE_NOMATCH; if(sp->payload == NULL) return RULE_NOMATCH; if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) return RULE_NOMATCH; if((end_of_payload - beg_of_payload) < 32) return RULE_NOMATCH; /* call flow match */ if (checkFlow(sp, rule13921options[0]->option_u.flowFlags) <= 0 ) return RULE_NOMATCH; /* call first content match */ if (contentMatch(sp, rule13921options[1]->option_u.content, &cursor) <= 0) { return RULE_NOMATCH; } /* call second content match */ if (contentMatch(sp, rule13921options[2]->option_u.content, &cursor) <= 0) { return RULE_NOMATCH; } /* Decode the part containing "/P.\x03/" to ensure the proper header and message type */ n = base64decode(&(beg_of_payload[8]), 4, decoded_data, sizeof(decoded_data), &num_bytes_extracted); if((n < 0) || (num_bytes_extracted < 3)) return RULE_NOMATCH; /* verify contents */ if((decoded_data[0] != 'P') || (decoded_data[2] != 0x03)) return RULE_NOMATCH; /* Now decode the part containing LM_X */ n = base64decode(&(beg_of_payload[24]), 8, decoded_data, sizeof(decoded_data), &num_bytes_extracted); if((n < 0) || (num_bytes_extracted < 6)) return RULE_NOMATCH; /* Extract LM_X, a signed 16-bit entity in little-endian format */ lm_x = decoded_data[2]; lm_x += decoded_data[3] << 8; if((lm_x < 0) || (lm_x > 56)) return RULE_MATCH; return RULE_NOMATCH; }