Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue #764: support multiple payloads per UDP port #772

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,15 +249,15 @@ transmit_thread(void *v) /*aka. scanning_thread() */
throttler_start(throttler, masscan->max_rate/masscan->nic_count);

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(&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
Expand Down Expand Up @@ -340,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(&masscan->targets.ports, xXx / count_ipv6);
port_them = rangelist_pick(&masscan->targets.ports_payloads, xXx / count_ipv6);

ip_me = src.ipv6;
port_me = src.port;
Expand Down Expand Up @@ -369,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(&masscan->targets.ports, xXx / count_ipv4);
port_them = rangelist_pick(&masscan->targets.ports_payloads, xXx / count_ipv4);

/*
* SYN-COOKIE LOGIC
Expand Down Expand Up @@ -1215,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
Expand Down Expand Up @@ -1246,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();
Expand Down
2 changes: 1 addition & 1 deletion src/massip-port.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions src/massip.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
99 changes: 66 additions & 33 deletions src/templ-payloads.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "util-malloc.h"
#include "massip.h"
#include "templ-nmap-payloads.h"
#include "massip-rangesv4.h"

#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -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; i<payloads->count; 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;
}


Expand Down Expand Up @@ -623,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;
Expand All @@ -650,26 +640,20 @@ payloads_datagram_add(struct PayloadsUDP *payloads,
unsigned j;

for (j=0; j<payloads->count; j++) {
if (p->port <= payloads->list[j]->port)
if (p->port < payloads->list[j]->port)
break;
}

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
Expand Down Expand Up @@ -903,3 +887,52 @@ 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, no_payloads;

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);
}

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)
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);
}

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);
}
19 changes: 7 additions & 12 deletions src/templ-payloads.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,18 @@ 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);


/**
* Called to set up targets->ports_payloads from targets->ports with UDP
* payloads where available instead of UDP ports.
*/
void
payloads_udp_ports_payloads(struct MassIP *targets, const struct PayloadsUDP *payloads);

#endif
29 changes: 21 additions & 8 deletions src/templ-pkt.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,20 +614,21 @@ 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;
SET_COOKIE set_cookie = 0;

UNUSEDPARM(seqno);

payloads_udp_lookup(tmpl->payloads,
port,
port = payloads_udp_lookup(tmpl->payloads,
payload_index,
&px2,
&length2,
&source_port2,
Expand Down Expand Up @@ -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
Expand All @@ -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;

Expand All @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -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 */
Expand Down