From 126184cab8bfdb4007f943d304f023fde95b3283 Mon Sep 17 00:00:00 2001 From: Gerhard Bogner Date: Thu, 14 Mar 2024 14:39:21 +0100 Subject: [PATCH 1/4] support multiple payloads per udp port --- src/main.c | 33 ++++++++++++++++++----- src/massip-port.h | 2 +- src/templ-payloads.c | 62 +++++++++++++++++++++++++++++--------------- src/templ-payloads.h | 15 +++-------- src/templ-pkt.c | 29 +++++++++++++++------ 5 files changed, 94 insertions(+), 47 deletions(-) diff --git a/src/main.c b/src/main.c index f6b6ee12..45dbf0d5 100644 --- a/src/main.c +++ b/src/main.c @@ -226,6 +226,7 @@ transmit_thread(void *v) /*aka. scanning_thread() */ uint64_t repeats = 0; /* --infinite repeats */ uint64_t *status_syn_count; uint64_t entropy = masscan->seed; + struct RangeList targets = {0}; /* Wait to make sure receive_thread is ready */ pixie_usleep(1000000); @@ -248,16 +249,33 @@ transmit_thread(void *v) /*aka. scanning_thread() */ * --max-rate parameter */ throttler_start(throttler, masscan->max_rate/masscan->nic_count); + /* Create a target list with multiple payloads per UDP port. */ + memset(&targets, 0, sizeof(targets)); + + for (i = 0; i < masscan->targets.ports.count; ++i) { + if (masscan->targets.ports.list[i].begin > Templ_UDP_last + || masscan->targets.ports.list[i].end < Templ_UDP) + rangelist_add_range( + &targets, masscan->targets.ports.list[i].begin, + masscan->targets.ports.list[i].end); + else + payloads_add_targets( + &targets, + masscan->payloads.udp, + masscan->targets.ports.list[i].begin - Templ_UDP, + masscan->targets.ports.list[i].end - Templ_UDP); + } + infinite: - + /* Create the shuffler/randomizer. This creates the 'range' variable, * which is simply the number of IP addresses times the number of * ports. * IPv6: low index will pick addresses from the IPv6 ranges, and high * indexes will pick addresses from the IPv4 ranges. */ - range = count_ipv4 * rangelist_count(&masscan->targets.ports) - + count_ipv6 * rangelist_count(&masscan->targets.ports); - range_ipv6 = count_ipv6 * rangelist_count(&masscan->targets.ports); + range = count_ipv4 * rangelist_count(&targets) + + count_ipv6 * rangelist_count(&targets); + range_ipv6 = count_ipv6 * rangelist_count(&targets); blackrock_init(&blackrock, range, seed, masscan->blackrock_rounds); /* Calculate the 'start' and 'end' of a scan. One reason to do this is @@ -340,7 +358,7 @@ transmit_thread(void *v) /*aka. scanning_thread() */ unsigned port_me; ip_them = range6list_pick(&masscan->targets.ipv6, xXx % count_ipv6); - port_them = rangelist_pick(&masscan->targets.ports, xXx / count_ipv6); + port_them = rangelist_pick(&targets, xXx / count_ipv6); ip_me = src.ipv6; port_me = src.port; @@ -369,7 +387,7 @@ transmit_thread(void *v) /*aka. scanning_thread() */ xXx -= range_ipv6; ip_them = rangelist_pick(&masscan->targets.ipv4, xXx % count_ipv4); - port_them = rangelist_pick(&masscan->targets.ports, xXx / count_ipv4); + port_them = rangelist_pick(&targets, xXx / count_ipv4); /* * SYN-COOKIE LOGIC @@ -456,6 +474,9 @@ transmit_thread(void *v) /*aka. scanning_thread() */ */ rawsock_flush(adapter); + /* free the list of target ports (including different payloads) */ + rangelist_remove_all(&targets); + /* * Wait until the receive thread realizes the scan is over */ diff --git a/src/massip-port.h b/src/massip-port.h index b2807f69..3abff57e 100644 --- a/src/massip-port.h +++ b/src/massip-port.h @@ -21,7 +21,7 @@ enum { Templ_Oproto_first = 65536*3 + 256, Templ_Oproto_last = 65536*3 + 256 + 255, Templ_VulnCheck = 65536*4, - + Templ_UDP_payloads = 65536*5 }; #endif diff --git a/src/templ-payloads.c b/src/templ-payloads.c index 6d446e3d..09c55b21 100644 --- a/src/templ-payloads.c +++ b/src/templ-payloads.c @@ -24,6 +24,7 @@ #include "util-malloc.h" #include "massip.h" #include "templ-nmap-payloads.h" +#include "massip-rangesv4.h" #include #include @@ -501,32 +502,22 @@ partial_checksum(const unsigned char *px, size_t icmp_length) int payloads_udp_lookup( const struct PayloadsUDP *payloads, - unsigned port, + unsigned payload_index, const unsigned char **px, unsigned *length, unsigned *source_port, uint64_t *xsum, SET_COOKIE *set_cookie) { - unsigned i; - if (payloads == 0) - return 0; - - port &= 0xFFFF; - - /* This is just a linear search, done once at startup, to search - * through all the payloads for the best match. */ - for (i=0; icount; i++) { - if (payloads->list[i]->port == port) { - *px = payloads->list[i]->buf; - *length = payloads->list[i]->length; - *source_port = payloads->list[i]->source_port; - *xsum = payloads->list[i]->xsum; - *set_cookie = payloads->list[i]->set_cookie; - return 1; - } - } - return 0; + if (payloads == 0 || payload_index >= payloads->count) + return -1; + + *px = payloads->list[payload_index]->buf; + *length = payloads->list[payload_index]->length; + *source_port = payloads->list[payload_index]->source_port; + *xsum = payloads->list[payload_index]->xsum; + *set_cookie = payloads->list[payload_index]->set_cookie; + return payloads->list[payload_index]->port; } @@ -650,7 +641,7 @@ payloads_datagram_add(struct PayloadsUDP *payloads, unsigned j; for (j=0; jcount; j++) { - if (p->port <= payloads->list[j]->port) + if (p->port < payloads->list[j]->port) break; } @@ -903,3 +894,32 @@ int templ_payloads_selftest(void) { return templ_nmap_selftest(); } + + +/*************************************************************************** + * add UDP payloads for the given port range to the targets list + ***************************************************************************/ +void +payloads_add_targets(struct RangeList *targets, const struct PayloadsUDP *payloads, unsigned begin, unsigned end) { + unsigned i, j, k; + + for (i = 0; i < payloads->count; ++i) + if (payloads->list[i]->port >= begin) + break; + for (j = i; j < payloads->count; ++j) + if (payloads->list[j]->port > end) + break; + + if (i < j) { + rangelist_add_range(targets, i + Templ_UDP_payloads, j + Templ_UDP_payloads - 1); + LOG(3, "[+] UDP port range %d - %d ==> UDP payloads %d - %d\n", begin, end, i, j - 1); + } + + for (k = begin; k <= end; ++k) { + for(; i < j && payloads->list[i]->port < k; ++i); + if (i == j || payloads->list[i]->port != k) { + LOG(3, "[-] no payload for UDP port %d\n", k); + rangelist_add_range_udp(targets, k, k); + } + } +} diff --git a/src/templ-payloads.h b/src/templ-payloads.h index a4613f8e..ce3223e4 100644 --- a/src/templ-payloads.h +++ b/src/templ-payloads.h @@ -3,6 +3,7 @@ #include #include struct MassIP; +struct RangeList; /** * Regression test this module. @@ -92,23 +93,15 @@ typedef unsigned (*SET_COOKIE)(unsigned char *px, size_t length, int payloads_udp_lookup( const struct PayloadsUDP *payloads, - unsigned port, + unsigned payload_index, const unsigned char **px, unsigned *length, unsigned *source_port, uint64_t *xsum, SET_COOKIE *set_cookie); -int -payloads_oproto_lookup( - const struct PayloadsUDP *payloads, - unsigned port, - const unsigned char **px, - unsigned *length, - unsigned *source_port, - uint64_t *xsum, - SET_COOKIE *set_cookie); - +void +payloads_add_targets(struct RangeList *targets, const struct PayloadsUDP *payloads, unsigned begin, unsigned end); #endif diff --git a/src/templ-pkt.c b/src/templ-pkt.c index db65724e..dbbded23 100644 --- a/src/templ-pkt.c +++ b/src/templ-pkt.c @@ -614,11 +614,12 @@ tcp_create_packet( /*************************************************************************** ***************************************************************************/ -static void -udp_payload_fixup(struct TemplatePacket *tmpl, unsigned port, unsigned seqno) +static int +udp_payload_fixup(struct TemplatePacket *tmpl, unsigned payload_index, unsigned seqno) { const unsigned char *px2 = 0; unsigned length2 = 0; + int port; unsigned source_port2 = 0x1000; uint64_t xsum2 = 0; //unsigned char *px = tmpl->packet; @@ -626,8 +627,8 @@ udp_payload_fixup(struct TemplatePacket *tmpl, unsigned port, unsigned seqno) UNUSEDPARM(seqno); - payloads_udp_lookup(tmpl->payloads, - port, + port = payloads_udp_lookup(tmpl->payloads, + payload_index, &px2, &length2, &source_port2, @@ -656,6 +657,8 @@ udp_payload_fixup(struct TemplatePacket *tmpl, unsigned port, unsigned seqno) tmpl->ipv4.length = tmpl->ipv4.offset_app + length2; tmpl->ipv6.length = tmpl->ipv6.offset_app + length2; + + return port; } void @@ -673,6 +676,7 @@ template_set_target_ipv6( struct TemplatePacket *tmpl = NULL; uint64_t entropy = tmplset->entropy; unsigned payload_length; + int maybe_port_them; *r_length = sizeof_px; @@ -687,7 +691,7 @@ template_set_target_ipv6( else if (port_them < Templ_UDP + 65536) { tmpl = &tmplset->pkts[Proto_UDP]; port_them &= 0xFFFF; - udp_payload_fixup(tmpl, port_them, seqno); + udp_payload_fixup(tmpl, UINT32_MAX, seqno); } else if (port_them < Templ_SCTP + 65536) { tmpl = &tmplset->pkts[Proto_SCTP]; port_them &= 0xFFFF; @@ -705,7 +709,11 @@ template_set_target_ipv6( tmpl = &tmplset->pkts[Proto_VulnCheck]; port_them &= 0xFFFF; } else { - return; + tmpl = &tmplset->pkts[Proto_UDP]; + maybe_port_them = udp_payload_fixup(tmpl, port_them - Templ_UDP_payloads, seqno); + if (maybe_port_them < 0) + return; + port_them = (unsigned)maybe_port_them; } /* Create some shorter local variables to work with */ @@ -889,6 +897,7 @@ template_set_target_ipv4( struct TemplatePacket *tmpl = NULL; unsigned xsum2; uint64_t entropy = tmplset->entropy; + int maybe_port_them; *r_length = sizeof_px; @@ -903,7 +912,7 @@ template_set_target_ipv4( else if (port_them < Templ_UDP + 65536) { tmpl = &tmplset->pkts[Proto_UDP]; port_them &= 0xFFFF; - udp_payload_fixup(tmpl, port_them, seqno); + udp_payload_fixup(tmpl, UINT32_MAX, seqno); } else if (port_them < Templ_SCTP + 65536) { tmpl = &tmplset->pkts[Proto_SCTP]; port_them &= 0xFFFF; @@ -930,7 +939,11 @@ template_set_target_ipv4( tmpl = &tmplset->pkts[Proto_VulnCheck]; port_them &= 0xFFFF; } else { - return; + tmpl = &tmplset->pkts[Proto_UDP]; + maybe_port_them = udp_payload_fixup(tmpl, port_them - Templ_UDP_payloads, seqno); + if (maybe_port_them < 0) + return; + port_them = (unsigned)maybe_port_them; } /* Create some shorter local variables to work with */ From 0512f26f8d7097f732294c1f003ed299cb92160d Mon Sep 17 00:00:00 2001 From: Gerhard Bogner Date: Thu, 14 Mar 2024 15:43:45 +0100 Subject: [PATCH 2/4] clean up payloads_datagram_add --- src/templ-payloads.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/templ-payloads.c b/src/templ-payloads.c index 09c55b21..67683f07 100644 --- a/src/templ-payloads.c +++ b/src/templ-payloads.c @@ -614,7 +614,6 @@ payloads_datagram_add(struct PayloadsUDP *payloads, struct RangeList *ports, unsigned source_port, SET_COOKIE set_cookie) { - unsigned count = 1; struct PayloadUDP_Item *p; uint64_t port_count = rangelist_count(ports); uint64_t i; @@ -646,21 +645,15 @@ payloads_datagram_add(struct PayloadsUDP *payloads, } if (j < payloads->count) { - if (p->port == payloads->list[j]->port) { - free(payloads->list[j]); - count = 0; /* don't increment count */ - } else - memmove(payloads->list + j + 1, - payloads->list + j, - (payloads->count-j) * sizeof(payloads->list[0])); + memmove(payloads->list + j + 1, + payloads->list + j, + (payloads->count-j) * sizeof(payloads->list[0])); } payloads->list[j] = p; - - payloads->count += count; - count = 1; + payloads->count += 1; } } - return count; /* zero or one */ + return port_count < UINT32_MAX ? (unsigned)port_count : UINT32_MAX; } static unsigned From 1e56072be785dbccbf058e3ab5c046041fb39dc7 Mon Sep 17 00:00:00 2001 From: Gerhard Bogner Date: Thu, 14 Mar 2024 16:21:16 +0100 Subject: [PATCH 3/4] report combined missing udp payloads --- src/templ-payloads.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/templ-payloads.c b/src/templ-payloads.c index 67683f07..12975c4b 100644 --- a/src/templ-payloads.c +++ b/src/templ-payloads.c @@ -894,7 +894,7 @@ templ_payloads_selftest(void) { ***************************************************************************/ void payloads_add_targets(struct RangeList *targets, const struct PayloadsUDP *payloads, unsigned begin, unsigned end) { - unsigned i, j, k; + unsigned i, j, k, no_payloads; for (i = 0; i < payloads->count; ++i) if (payloads->list[i]->port >= begin) @@ -905,14 +905,16 @@ payloads_add_targets(struct RangeList *targets, const struct PayloadsUDP *payloa if (i < j) { rangelist_add_range(targets, i + Templ_UDP_payloads, j + Templ_UDP_payloads - 1); - LOG(3, "[+] UDP port range %d - %d ==> UDP payloads %d - %d\n", begin, end, i, j - 1); + LOG(3, "[+] UDP port range %d - %d --> UDP payloads %d - %d\n", begin, end, i, j - 1); } + no_payloads = targets->count; for (k = begin; k <= end; ++k) { for(; i < j && payloads->list[i]->port < k; ++i); - if (i == j || payloads->list[i]->port != k) { - LOG(3, "[-] no payload for UDP port %d\n", k); + if (i == j || payloads->list[i]->port != k) rangelist_add_range_udp(targets, k, k); - } } + for (k = no_payloads; k < targets->count; ++k) + LOG(4, "[-] no payload for UDP ports %d - %d\n", + targets->list[k].begin - Templ_UDP, targets->list[k].end - Templ_UDP); } From 4c33150ad879f8c7a6c1e19d69cbfff7c0450e5c Mon Sep 17 00:00:00 2001 From: Gerhard Bogner Date: Fri, 15 Mar 2024 07:32:34 +0100 Subject: [PATCH 4/4] fix progress not finishing at 100% --- src/main.c | 42 ++++++++++++++---------------------------- src/massip.h | 1 + src/templ-payloads.c | 18 ++++++++++++++++++ src/templ-payloads.h | 8 +++++--- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/main.c b/src/main.c index 45dbf0d5..a95593fe 100644 --- a/src/main.c +++ b/src/main.c @@ -226,7 +226,6 @@ transmit_thread(void *v) /*aka. scanning_thread() */ uint64_t repeats = 0; /* --infinite repeats */ uint64_t *status_syn_count; uint64_t entropy = masscan->seed; - struct RangeList targets = {0}; /* Wait to make sure receive_thread is ready */ pixie_usleep(1000000); @@ -249,23 +248,6 @@ transmit_thread(void *v) /*aka. scanning_thread() */ * --max-rate parameter */ throttler_start(throttler, masscan->max_rate/masscan->nic_count); - /* Create a target list with multiple payloads per UDP port. */ - memset(&targets, 0, sizeof(targets)); - - for (i = 0; i < masscan->targets.ports.count; ++i) { - if (masscan->targets.ports.list[i].begin > Templ_UDP_last - || masscan->targets.ports.list[i].end < Templ_UDP) - rangelist_add_range( - &targets, masscan->targets.ports.list[i].begin, - masscan->targets.ports.list[i].end); - else - payloads_add_targets( - &targets, - masscan->payloads.udp, - masscan->targets.ports.list[i].begin - Templ_UDP, - masscan->targets.ports.list[i].end - Templ_UDP); - } - infinite: /* Create the shuffler/randomizer. This creates the 'range' variable, @@ -273,9 +255,9 @@ transmit_thread(void *v) /*aka. scanning_thread() */ * ports. * IPv6: low index will pick addresses from the IPv6 ranges, and high * indexes will pick addresses from the IPv4 ranges. */ - range = count_ipv4 * rangelist_count(&targets) - + count_ipv6 * rangelist_count(&targets); - range_ipv6 = count_ipv6 * rangelist_count(&targets); + range = count_ipv4 * rangelist_count(&masscan->targets.ports_payloads) + + count_ipv6 * rangelist_count(&masscan->targets.ports_payloads); + range_ipv6 = count_ipv6 * rangelist_count(&masscan->targets.ports_payloads); blackrock_init(&blackrock, range, seed, masscan->blackrock_rounds); /* Calculate the 'start' and 'end' of a scan. One reason to do this is @@ -358,7 +340,7 @@ transmit_thread(void *v) /*aka. scanning_thread() */ unsigned port_me; ip_them = range6list_pick(&masscan->targets.ipv6, xXx % count_ipv6); - port_them = rangelist_pick(&targets, xXx / count_ipv6); + port_them = rangelist_pick(&masscan->targets.ports_payloads, xXx / count_ipv6); ip_me = src.ipv6; port_me = src.port; @@ -387,7 +369,7 @@ transmit_thread(void *v) /*aka. scanning_thread() */ xXx -= range_ipv6; ip_them = rangelist_pick(&masscan->targets.ipv4, xXx % count_ipv4); - port_them = rangelist_pick(&targets, xXx / count_ipv4); + port_them = rangelist_pick(&masscan->targets.ports_payloads, xXx / count_ipv4); /* * SYN-COOKIE LOGIC @@ -474,9 +456,6 @@ transmit_thread(void *v) /*aka. scanning_thread() */ */ rawsock_flush(adapter); - /* free the list of target ports (including different payloads) */ - rangelist_remove_all(&targets); - /* * Wait until the receive thread realizes the scan is over */ @@ -1236,8 +1215,6 @@ main_scan(struct Masscan *masscan) LOG(0, " [hint] try something like \"--ports 0-65535\"\n"); return 1; } - range = count_ips * count_ports; - range += (uint64_t)(masscan->retries * range); /* * If doing an ARP scan, then don't allow port scanning @@ -1267,6 +1244,15 @@ main_scan(struct Masscan *masscan) payloads_udp_trim(masscan->payloads.udp, &masscan->targets); payloads_oproto_trim(masscan->payloads.oproto, &masscan->targets); + /* + * Convert all UDP port targets with one or more payloads into UDP payload + * targets. This allows multiple payloads to be sent for per port. + */ + payloads_udp_ports_payloads(&masscan->targets, masscan->payloads.udp); + + count_ports = rangelist_count(&masscan->targets.ports_payloads); + range = count_ips * count_ports; + range += (uint64_t)(masscan->retries * range); #ifdef __AFL_HAVE_MANUAL_CONTROL __AFL_INIT(); diff --git a/src/massip.h b/src/massip.h index 5b4293a4..eadab5ba 100644 --- a/src/massip.h +++ b/src/massip.h @@ -16,6 +16,7 @@ struct MassIP { * range 64k-128k, thus, allowing us to scan both at the same time. */ struct RangeList ports; + struct RangeList ports_payloads; /** * Used internally to differentiate between indexes selecting an diff --git a/src/templ-payloads.c b/src/templ-payloads.c index 12975c4b..ca1de26e 100644 --- a/src/templ-payloads.c +++ b/src/templ-payloads.c @@ -918,3 +918,21 @@ payloads_add_targets(struct RangeList *targets, const struct PayloadsUDP *payloa LOG(4, "[-] no payload for UDP ports %d - %d\n", targets->list[k].begin - Templ_UDP, targets->list[k].end - Templ_UDP); } + +void +payloads_udp_ports_payloads(struct MassIP *targets, const struct PayloadsUDP *payloads) { + unsigned i; + + /* Create a target list with multiple payloads per UDP port. */ + memset(&targets->ports_payloads, 0, sizeof(targets->ports_payloads)); + + for (i = 0; i < targets->ports.count; ++i) { + if (targets->ports.list[i].begin > Templ_UDP_last || targets->ports.list[i].end < Templ_UDP) + rangelist_add_range(&targets->ports_payloads, targets->ports.list[i].begin, targets->ports.list[i].end); + else + payloads_add_targets(&targets->ports_payloads, payloads, + targets->ports.list[i].begin - Templ_UDP, targets->ports.list[i].end - Templ_UDP); + } + + rangelist_optimize(&targets->ports_payloads); +} diff --git a/src/templ-payloads.h b/src/templ-payloads.h index ce3223e4..6743c09c 100644 --- a/src/templ-payloads.h +++ b/src/templ-payloads.h @@ -3,7 +3,6 @@ #include #include struct MassIP; -struct RangeList; /** * Regression test this module. @@ -100,8 +99,11 @@ payloads_udp_lookup( uint64_t *xsum, SET_COOKIE *set_cookie); +/** + * Called to set up targets->ports_payloads from targets->ports with UDP + * payloads where available instead of UDP ports. + */ void -payloads_add_targets(struct RangeList *targets, const struct PayloadsUDP *payloads, unsigned begin, unsigned end); - +payloads_udp_ports_payloads(struct MassIP *targets, const struct PayloadsUDP *payloads); #endif