From b77d3e3ab6d216cda9a092794a5fb8b1eac86fe6 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Sun, 15 Sep 2024 20:21:32 +0200 Subject: [PATCH] Enhanced DHCP fingerprint Exported it with -E --- example/reader_util.c | 15 +++++++++++++-- src/include/ndpi_typedefs.h | 1 + src/lib/protocols/dhcp.c | 27 +++++++++++++++++---------- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/example/reader_util.c b/example/reader_util.c index d2b60859d2d..51e8c3da05f 100644 --- a/example/reader_util.c +++ b/example/reader_util.c @@ -1057,8 +1057,19 @@ static void dump_raw_fingerprint(struct ndpi_workflow * workflow, /* ****************************************************** */ static void dump_flow_fingerprint(struct ndpi_workflow * workflow, struct ndpi_flow_info *flow) { - if(flow->ndpi_flow->protos.tls_quic.ja4_client_raw != NULL) - dump_raw_fingerprint(workflow, flow, "JA4r", flow->ndpi_flow->protos.tls_quic.ja4_client_raw); + if(is_ndpi_proto(flow, NDPI_PROTOCOL_TLS) || is_ndpi_proto(flow, NDPI_PROTOCOL_QUIC)) { + if(flow->ndpi_flow->protos.tls_quic.ja4_client_raw != NULL) + dump_raw_fingerprint(workflow, flow, "JA4r", flow->ndpi_flow->protos.tls_quic.ja4_client_raw); + } else if(is_ndpi_proto(flow, NDPI_PROTOCOL_DHCP) + && (flow->ndpi_flow->protos.dhcp.fingerprint[0] != '\0')) { + char buf[256]; + + snprintf(buf, sizeof(buf), "%s_%s", + flow->ndpi_flow->protos.dhcp.options, + flow->ndpi_flow->protos.dhcp.fingerprint); + + dump_raw_fingerprint(workflow, flow, "DHCP_r", buf); + } } /* ****************************************************** */ diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index e7fdb95417b..9086e456ee5 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1434,6 +1434,7 @@ struct ndpi_flow_struct { } bittorrent; struct { + char options[48]; char fingerprint[48]; char class_ident[48]; } dhcp; diff --git a/src/lib/protocols/dhcp.c b/src/lib/protocols/dhcp.c index 092d5ce617e..564e5e24334 100644 --- a/src/lib/protocols/dhcp.c +++ b/src/lib/protocols/dhcp.c @@ -88,7 +88,7 @@ static void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struc && (packet->udp->source == htons(67) || packet->udp->source == htons(68)) && (packet->udp->dest == htons(67) || packet->udp->dest == htons(68)) && is_dhcp_magic(dhcp->magic)) { - u_int i = 0, foundValidMsgType = 0; + u_int i = 0, foundValidMsgType = 0, opt_offset = 0; u_int dhcp_options_size = ndpi_min(DHCP_VEND_LEN /* maximum size of options in struct dhcp_packet */, packet->payload_packet_len - 240); @@ -96,10 +96,10 @@ static void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struc /* Parse options in two steps (since we need first the message type and it seems there is no specific order in the options list) */ - + /* First iteration: search for the message type */ while(i + 1 /* for the len */ < dhcp_options_size) { - u_int8_t id = dhcp->options[i]; + u_int8_t id = dhcp->options[i]; if(id == 0xFF) break; @@ -142,6 +142,7 @@ static void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struc if(id == 0xFF) break; else { + int rc; /* Prevent malformed packets to cause out-of-bounds accesses */ u_int8_t len = ndpi_min(dhcp->options[i+1] /* len as found in the packet */, dhcp_options_size - (i+2) /* 1 for the type and 1 for the value */); @@ -149,20 +150,26 @@ static void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struc if(len == 0) break; + rc = ndpi_snprintf((char*)&flow->protos.dhcp.options[opt_offset], + sizeof(flow->protos.dhcp.options) - opt_offset, + "%s%u", (i > 0) ? "," : "", id); + + if(rc > 0) opt_offset += rc; + #ifdef DHCP_DEBUG NDPI_LOG_DBG2(ndpi_struct, "[DHCP] Id=%d [len=%d]\n", id, len); #endif if(id == 55 /* Parameter Request List / Fingerprint */) { - u_int idx, offset = 0; + u_int idx, fing_offset = 0; - for(idx = 0; idx < len && offset < sizeof(flow->protos.dhcp.fingerprint) - 2; idx++) { - int rc = ndpi_snprintf((char*)&flow->protos.dhcp.fingerprint[offset], - sizeof(flow->protos.dhcp.fingerprint) - offset, - "%s%u", (idx > 0) ? "," : "", - (unsigned int)dhcp->options[i+2+idx] & 0xFF); + for(idx = 0; idx < len && fing_offset < sizeof(flow->protos.dhcp.fingerprint) - 2; idx++) { + rc = ndpi_snprintf((char*)&flow->protos.dhcp.fingerprint[fing_offset], + sizeof(flow->protos.dhcp.fingerprint) - fing_offset, + "%s%u", (idx > 0) ? "," : "", + (unsigned int)dhcp->options[i+2+idx] & 0xFF); - if(rc < 0) break; else offset += rc; + if(rc < 0) break; else fing_offset += rc; } flow->protos.dhcp.fingerprint[sizeof(flow->protos.dhcp.fingerprint) - 1] = '\0';