📄 spp_dns.c
字号:
/* Fall through */ case DNS_RESP_STATE_Q_CLASS_PART: dnsSessionData->curr_q.dns_class |= (u_int8_t)*data; data++; bytes_unused--; dnsSessionData->curr_rec_state = DNS_RESP_STATE_Q_COMPLETE; if (bytes_unused == 0) { return bytes_unused; } /* Fall through */ default: /* Continue -- we're beyond this question */ break; } return bytes_unused;}u_int16_t ParseDNSAnswer(const unsigned char *data, u_int16_t data_size, u_int16_t bytes_unused, DNSSessionData *dnsSessionData){ u_int16_t bytes_used = 0; u_int16_t new_bytes_unused = 0; if (bytes_unused == 0) { return bytes_unused; } if (dnsSessionData->curr_rec_state < DNS_RESP_STATE_RR_NAME_COMPLETE) { new_bytes_unused = ParseDNSName(data, bytes_unused, dnsSessionData); bytes_used = bytes_unused - new_bytes_unused; if (dnsSessionData->curr_txt.name_state == DNS_RESP_STATE_NAME_COMPLETE) { dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_TYPE; bzero(&dnsSessionData->curr_txt, sizeof(DNSNameState)); data = data + bytes_used; } bytes_unused = new_bytes_unused; if (bytes_unused == 0) { /* ran out of data */ return bytes_unused; } } switch (dnsSessionData->curr_rec_state) { case DNS_RESP_STATE_RR_TYPE: dnsSessionData->curr_rr.type = (u_int8_t)*data << 8; data++; bytes_unused--; dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_TYPE_PART; if (bytes_unused == 0) { return bytes_unused; } /* Fall through */ case DNS_RESP_STATE_RR_TYPE_PART: dnsSessionData->curr_rr.type |= (u_int8_t)*data; data++; bytes_unused--; dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_CLASS; if (bytes_unused == 0) { return bytes_unused; } /* Fall through */ case DNS_RESP_STATE_RR_CLASS: dnsSessionData->curr_rr.dns_class = (u_int8_t)*data << 8; data++; bytes_unused--; dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_CLASS_PART; if (bytes_unused == 0) { return bytes_unused; } /* Fall through */ case DNS_RESP_STATE_RR_CLASS_PART: dnsSessionData->curr_rr.dns_class |= (u_int8_t)*data; data++; bytes_unused--; dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_TTL; if (bytes_unused == 0) { return bytes_unused; } /* Fall through */ case DNS_RESP_STATE_RR_TTL: dnsSessionData->curr_rr.ttl = (u_int8_t)*data << 24; data++; bytes_unused--; dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_TTL_PART; dnsSessionData->bytes_seen_curr_rec = 1; if (bytes_unused == 0) { return bytes_unused; } /* Fall through */ case DNS_RESP_STATE_RR_TTL_PART: while (dnsSessionData->bytes_seen_curr_rec < 4) { dnsSessionData->bytes_seen_curr_rec++; dnsSessionData->curr_rr.ttl |= (u_int8_t)*data << (4-dnsSessionData->bytes_seen_curr_rec)*8; data++; bytes_unused--; if (bytes_unused == 0) { return bytes_unused; } } dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_RDLENGTH; if (bytes_unused == 0) { return bytes_unused; } case DNS_RESP_STATE_RR_RDLENGTH: dnsSessionData->curr_rr.length = (u_int8_t)*data << 8; data++; bytes_unused--; dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_RDLENGTH_PART; if (bytes_unused == 0) { return bytes_unused; } /* Fall through */ case DNS_RESP_STATE_RR_RDLENGTH_PART: dnsSessionData->curr_rr.length |= (u_int8_t)*data; data++; bytes_unused--; dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_RDATA_START; if (bytes_unused == 0) { return bytes_unused; } /* Fall through */ default: /* Continue -- we're beyond this answer */ break; } return bytes_unused;}/* The following check is to look for an attempt to exploit * a vulnerability in the DNS client, per MS 06-041. * * For details, see: * http://www.microsoft.com/technet/security/bulletin/ms06-007.mspx * http://cve.mitre.org/cgi-bin/cvename.cgi?name=2006-3441 * * Vulnerability Research by Lurene Grenier, Judy Novak, * and Brian Caswell. */u_int16_t CheckRRTypeTXTVuln(const unsigned char *data, u_int16_t bytes_unused, DNSSessionData *dnsSessionData){ u_int16_t bytes_required = dnsSessionData->curr_txt.txt_len - dnsSessionData->curr_txt.txt_bytes_seen; while (dnsSessionData->curr_txt.name_state != DNS_RESP_STATE_RR_NAME_COMPLETE) { if (dnsSessionData->bytes_seen_curr_rec == dnsSessionData->curr_rr.length) { /* Done with the name */ dnsSessionData->curr_txt.name_state = DNS_RESP_STATE_RR_NAME_COMPLETE; /* Got to the end of the rdata in this packet! */ dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_COMPLETE; return bytes_unused; } if (bytes_unused == 0) { return bytes_unused; } switch (dnsSessionData->curr_txt.name_state) { case DNS_RESP_STATE_RR_NAME_SIZE: dnsSessionData->curr_txt.txt_len = (u_int8_t)*data; dnsSessionData->curr_txt.txt_count++; dnsSessionData->curr_txt.total_txt_len += dnsSessionData->curr_txt.txt_len + 1; /* include the NULL */ if (!dnsSessionData->curr_txt.alerted) { u_int32_t overflow_check = (dnsSessionData->curr_txt.txt_count * 4) + (dnsSessionData->curr_txt.total_txt_len * 2) + 4; /* if txt_count * 4 + total_txt_len * 2 + 4 > FFFF, vulnerability! */ if (overflow_check > 0xFFFF) { if (dns_config.enabled_alerts & DNS_ALERT_RDATA_OVERFLOW) { /* Alert on obsolete DNS RR types */ DNS_ALERT(DNS_EVENT_RDATA_OVERFLOW, DNS_EVENT_RDATA_OVERFLOW_STR); } dnsSessionData->curr_txt.alerted = 1; } } data++; bytes_unused--; dnsSessionData->bytes_seen_curr_rec++; if (dnsSessionData->curr_txt.txt_len > 0) { dnsSessionData->curr_txt.name_state = DNS_RESP_STATE_RR_NAME; dnsSessionData->curr_txt.txt_bytes_seen = 0; bytes_required = dnsSessionData->curr_txt.txt_len; } else { continue; } if (bytes_unused == 0) { return bytes_unused; } /* Fall through */ case DNS_RESP_STATE_RR_NAME: if (bytes_required <= bytes_unused) { bytes_unused -= bytes_required; dnsSessionData->bytes_seen_curr_rec += bytes_required; data += bytes_required; dnsSessionData->curr_txt.txt_bytes_seen += bytes_required; if (bytes_unused == 0) { return bytes_unused; } } else { dnsSessionData->curr_txt.txt_bytes_seen += bytes_unused; dnsSessionData->bytes_seen_curr_rec += bytes_unused; return 0; } break; } /* Go to the next portion of the name */ dnsSessionData->curr_txt.name_state = DNS_RESP_STATE_RR_NAME_SIZE; } return bytes_unused;}u_int16_t SkipDNSRData(const unsigned char *data, u_int16_t bytes_unused, DNSSessionData *dnsSessionData){ u_int16_t bytes_required = dnsSessionData->curr_rr.length - dnsSessionData->bytes_seen_curr_rec; if (bytes_required <= bytes_unused) { bytes_unused -= bytes_required; data += bytes_required; dnsSessionData->bytes_seen_curr_rec += bytes_required; } else { dnsSessionData->bytes_seen_curr_rec += bytes_unused; return 0; } /* Got to the end of the rdata in this packet! */ dnsSessionData->curr_rec_state = DNS_RESP_STATE_RR_COMPLETE; return bytes_unused;}u_int16_t ParseDNSRData(SFSnortPacket *p, const unsigned char *data, u_int16_t bytes_unused, DNSSessionData *dnsSessionData){ if (bytes_unused == 0) { return bytes_unused; } switch (dnsSessionData->curr_rr.type) { case DNS_RR_TYPE_TXT: /* Check for RData Overflow */ bytes_unused = CheckRRTypeTXTVuln(data, bytes_unused, dnsSessionData); break; case DNS_RR_TYPE_MD: case DNS_RR_TYPE_MF: if (dns_config.enabled_alerts & DNS_ALERT_OBSOLETE_TYPES) { /* Alert on obsolete DNS RR types */ DNS_ALERT(DNS_EVENT_OBSOLETE_TYPES, DNS_EVENT_OBSOLETE_TYPES_STR); } bytes_unused = SkipDNSRData(data, bytes_unused, dnsSessionData); break; case DNS_RR_TYPE_MB: case DNS_RR_TYPE_MG: case DNS_RR_TYPE_MR: case DNS_RR_TYPE_NULL: case DNS_RR_TYPE_MINFO: if (dns_config.enabled_alerts & DNS_ALERT_EXPERIMENTAL_TYPES) { /* Alert on experimental DNS RR types */ DNS_ALERT(DNS_EVENT_EXPERIMENTAL_TYPES, DNS_EVENT_EXPERIMENTAL_TYPES_STR); } bytes_unused = SkipDNSRData(data, bytes_unused, dnsSessionData); break; case DNS_RR_TYPE_A: case DNS_RR_TYPE_NS: case DNS_RR_TYPE_CNAME: case DNS_RR_TYPE_SOA: case DNS_RR_TYPE_WKS: case DNS_RR_TYPE_PTR: case DNS_RR_TYPE_HINFO: case DNS_RR_TYPE_MX: bytes_unused = SkipDNSRData(data, bytes_unused, dnsSessionData); break; default: /* Not one of the known types. Stop looking at this session * as DNS. */ dnsSessionData->flags |= DNS_FLAG_NOT_DNS; break; } return bytes_unused;}void ParseDNSResponseMessage(SFSnortPacket *p, DNSSessionData *dnsSessionData){ u_int16_t bytes_unused = p->payload_size; int i; const unsigned char *data = p->payload; while (bytes_unused) { /* Parse through the DNS Header */ if (dnsSessionData->state < DNS_RESP_STATE_QUESTION) { /* Length only applies on a TCP packet, skip to header ID * if at beginning of a UDP Response. */ if ((dnsSessionData->state == DNS_RESP_STATE_LENGTH) && (p->udp_header)) { dnsSessionData->state = DNS_RESP_STATE_HDR_ID; } bytes_unused = ParseDNSHeader(data, bytes_unused, dnsSessionData); if (bytes_unused > 0) { data = p->payload + (p->payload_size - bytes_unused); } else { /* No more data */ return; } dnsSessionData->curr_rec_state = DNS_RESP_STATE_Q_NAME; dnsSessionData->curr_rec = 0; } /* Print out the header (but only once -- when we're ready to parse the Questions */#ifdef DEBUG if ((dnsSessionData->curr_rec_state == DNS_RESP_STATE_Q_NAME) && (dnsSessionData->curr_rec == 0)) { DebugMessage(DEBUG_DNS, "DNS Header: length %d, id 0x%x, flags 0x%x, " "questions %d, answers %d, authorities %d, additionals %d\n", dnsSessionData->length, dnsSessionData->hdr.id,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -