Skip to content

Commit

Permalink
Merge pull request #7 from ThreatEye/hl-add-dns-cname-dissection
Browse files Browse the repository at this point in the history
add cname dissection to ndpi dns
  • Loading branch information
spendletonliveaction authored Oct 25, 2022
2 parents b4d76b0 + 786610a commit 7ac5837
Showing 1 changed file with 39 additions and 44 deletions.
83 changes: 39 additions & 44 deletions src/lib/protocols/dns.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,59 +297,54 @@ static int search_valid_dns(struct ndpi_detection_module_struct *ndpi_struct,

/* here x points to the response "class" field */
if((x+12) <= packet->payload_packet_len) {
x += 2;
uint32_t ttl = get32(&x,packet->payload);
flow->protos.dns.answer_ttl = ttl;
data_len = get16(&x, packet->payload);
x += 2;
uint32_t ttl = get32(&x,packet->payload);
flow->protos.dns.answer_ttl = ttl;
data_len = get16(&x, packet->payload);

if((x + data_len) <= packet->payload_packet_len) {
// printf("[rsp_type: %u][data_len: %u]\n", rsp_type, data_len);

if(rsp_type == 0x05 /* CNAME */) {
x += data_len;
continue; /* Skip CNAME */
}

if((((rsp_type == 0x1) && (data_len == 4)) /* A */
|| ((rsp_type == 0x1c) && (data_len == 16)) /* AAAA */
)) {
memcpy(&flow->protos.dns.rsp_addr, packet->payload + x, data_len);
}
else if (rsp_type == 0x0c)
{

// reverse dns lookup responses can have an address label as well as additional domain name labels
// since we already have the address from the query we just need the domain name
// we only process the first answer and grab its domain name
int an_index = 0;
// make sure to exit loop if x is a 00 octet or x exceeds the packet payload length or the length octet has first 2 bits set (domain name compressed)
while((packet->payload[x] != '\0') && (x < packet->payload_packet_len) && (packet->payload[x] < 0x40)) // normal length octets can't be greater than 63 chars total 64 chars 1 for the length octet itself leaves 63
{
int label_len = packet->payload[x]; // get 1st label len

// if first char is number this is an address
// number can't be first char in domain name
// we only want to check the first label for an ip address
if (packet->payload[x+1] >= 0x30 && packet->payload[x+1] <= 0x39 && an_index == 0)
{
x += label_len + 1; // skip label len + address field
}
else
{
if (an_index + label_len < (int)(sizeof(flow->protos.dns.answer_domain)-1))
{
strncat(flow->protos.dns.answer_domain, (char *)packet->payload + x + 1, label_len); // copy label section into string field
an_index += label_len; // increment index
flow->protos.dns.answer_domain[an_index] = '.'; // delimeter between label sections
an_index++; // increment index for delimeter
x += label_len + 1; // skip label len + address field
}
else
break;
}
}
flow->protos.dns.answer_domain[an_index - 1] = '\0'; // remove trailing '.' char and replace with null term
}
else if (rsp_type == 0x0c || rsp_type == 0x05) // reverse dns lookup and cname record processing
{

// reverse dns lookup responses can have an address label as well as additional domain name labels
// since we already have the address from the query we just need the domain name
// we only process the first answer and grab its domain name
int an_index = 0;
// make sure to exit loop if x is a 00 octet or x exceeds the packet payload length or the length octet has first 2 bits set (domain name compressed)
while((packet->payload[x] != '\0') && (x < packet->payload_packet_len) && (packet->payload[x] < 0x40)) // normal length octets can't be greater than 63 chars total 64 chars 1 for the length octet itself leaves 63
{
int label_len = packet->payload[x]; // get 1st label len

// if first char is number this is an address
// number can't be first char in domain name
// we only want to check the first label for an ip address
if (packet->payload[x+1] >= 0x30 && packet->payload[x+1] <= 0x39 && an_index == 0 && rsp_type == 0x0c) // only perform this check on PTR records
{
x += label_len + 1; // skip label len + address field
}
else
{
if (an_index + label_len < (int)(sizeof(flow->protos.dns.answer_domain)-1))
{
strncat(flow->protos.dns.answer_domain, (char *)packet->payload + x + 1, label_len); // copy label section into string field
an_index += label_len; // increment index
flow->protos.dns.answer_domain[an_index] = '.'; // delimeter between label sections
an_index++; // increment index for delimeter
x += label_len + 1; // skip label len + address field
}
else
break;
}
}
flow->protos.dns.answer_domain[an_index - 1] = '\0'; // remove trailing '.' char and replace with null term
}
}
}

Expand Down

0 comments on commit 7ac5837

Please sign in to comment.