Skip to content

Commit

Permalink
Merge pull request #744 from robertdavidgraham/integration
Browse files Browse the repository at this point in the history
added --rawudp, prints raw UDP regardless of other banners
  • Loading branch information
robertdavidgraham committed Nov 16, 2023
2 parents 87a363d + 122c0ee commit 2a547f7
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 43 deletions.
20 changes: 18 additions & 2 deletions src/main-conf.c
Expand Up @@ -1112,6 +1112,20 @@ static int SET_banners(struct Masscan *masscan, const char *name, const char *va
return CONF_OK;
}

static int SET_banners_rawudp(struct Masscan *masscan, const char *name, const char *value)
{
UNUSEDPARM(name);
if (masscan->echo) {
if (masscan->is_banners_rawudp || masscan->echo_all)
fprintf(masscan->echo, "rawudp = %s\n", masscan->is_banners_rawudp?"true":"false");
return 0;
}
masscan->is_banners_rawudp = parseBoolean(value);
if (masscan->is_banners_rawudp)
masscan->is_banners = true;
return CONF_OK;
}

static int SET_capture(struct Masscan *masscan, const char *name, const char *value)
{
if (masscan->echo) {
Expand Down Expand Up @@ -2343,7 +2357,8 @@ struct ConfigParameter config_parameters[] = {
{"randomize-hosts", SET_randomize_hosts, F_BOOL, {0}},
{"rate", SET_rate, 0, {"max-rate",0}},
{"shard", SET_shard, 0, {"shards",0}},
{"banners", SET_banners, F_BOOL, {"banner",0}},
{"banners", SET_banners, F_BOOL, {"banner",0}}, /* --banners */
{"rawudp", SET_banners_rawudp, F_BOOL, {"rawudp",0}}, /* --rawudp */
{"nobanners", SET_nobanners, F_BOOL, {"nobanner",0}},
{"retries", SET_retries, 0, {"retry", "max-retries", "max-retry", 0}},
{"noreset", SET_noreset, F_BOOL, {0}},
Expand Down Expand Up @@ -3236,7 +3251,8 @@ masscan_command_line(struct Masscan *masscan, int argc, char *argv[])
masscan->op = Operation_ReadScan;

/* Default to reading banners */
masscan->is_banners = 1;
masscan->is_banners = true;
masscan->is_banners_rawudp = true;

/* This option may be followed by many filenames, therefore,
* skip forward in the argument list until the next
Expand Down
2 changes: 2 additions & 0 deletions src/masscan-app.c
Expand Up @@ -46,6 +46,7 @@ masscan_app_to_string(enum ApplicationProtocol proto)
case PROTO_MC: return "minecraft";
case PROTO_VNC_RFB: return "vnc";
case PROTO_VNC_INFO: return "vnc-info";
case PROTO_ISAKMP: return "isakmp";

case PROTO_ERROR: return "error";

Expand Down Expand Up @@ -98,6 +99,7 @@ masscan_string_to_app(const char *str)
{"minecraft", PROTO_MC},
{"vnc", PROTO_VNC_RFB},
{"vnc-info", PROTO_VNC_INFO},
{"isakmp", PROTO_ISAKMP},
{0,0}
};
size_t i;
Expand Down
1 change: 1 addition & 0 deletions src/masscan-app.h
Expand Up @@ -41,6 +41,7 @@ enum ApplicationProtocol {
PROTO_MC, /* 32 - Minecraft server */
PROTO_VNC_RFB,
PROTO_VNC_INFO,
PROTO_ISAKMP, /* 35 - IPsec key exchange */

PROTO_ERROR,

Expand Down
1 change: 1 addition & 0 deletions src/masscan.h
Expand Up @@ -187,6 +187,7 @@ struct Masscan
unsigned is_pfring:1; /* --pfring */
unsigned is_sendq:1; /* --sendq */
unsigned is_banners:1; /* --banners */
unsigned is_banners_rawudp:1; /* --rawudp */
unsigned is_offline:1; /* --offline */
unsigned is_noreset:1; /* --noreset, don't transmit RST */
unsigned is_gmt:1; /* --gmt, all times in GMT */
Expand Down
8 changes: 3 additions & 5 deletions src/output.c
Expand Up @@ -392,7 +392,8 @@ output_create(const struct Masscan *masscan, unsigned thread_index)
out->redis.port = masscan->redis.port;
out->redis.ip = masscan->redis.ip;
out->redis.password = masscan ->redis.password;
out->is_banner = masscan->is_banners;
out->is_banner = masscan->is_banners; /* --banners */
out->is_banner_rawudp = masscan->is_banners_rawudp; /* --rawudp */
out->is_gmt = masscan->is_gmt;
out->is_interactive = masscan->output.is_interactive;
out->is_show_open = masscan->output.is_show_open;
Expand Down Expand Up @@ -779,10 +780,7 @@ output_report_status(struct Output *out, time_t timestamp, int status,
fprintf(stdout, "\n");
fflush(stdout);

}


if (fp == NULL) {
} else if (fp == NULL) {
ERRMSG("no output file, use `--output-filename <filename>` to set one\n");
ERRMSG("for `stdout`, use `--output-filename -`\n");
return;
Expand Down
3 changes: 2 additions & 1 deletion src/output.h
Expand Up @@ -81,7 +81,8 @@ struct Output
char *directory;
} rotate;

unsigned is_banner:1;
unsigned is_banner:1; /* --banners */
unsigned is_banner_rawudp:1; /* --rawudp */
unsigned is_gmt:1; /* --gmt */
unsigned is_interactive:1; /* echo to command line */
unsigned is_show_open:1; /* show open ports (default) */
Expand Down
1 change: 1 addition & 0 deletions src/proto-dns.c
Expand Up @@ -444,6 +444,7 @@ handle_dns(struct Output *out, time_t timestamp,
PROTO_DNS_VERSIONBIND,
parsed->ip_ttl,
px + offset, txtlen);
return 1;
}


Expand Down
108 changes: 90 additions & 18 deletions src/proto-isakmp.c
@@ -1,4 +1,23 @@
/* ISAKMP protocol support */
/* ISAKMP protocol support
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Initiator !
! Cookie !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Responder !
! Cookie !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Message ID !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/

#include "proto-isakmp.h"
#include "proto-banout.h"
Expand All @@ -7,7 +26,44 @@
#include "massip-port.h"
#include "output.h"

static const unsigned char
sample_response[] =
"\x00\x00\x00\x00\xc1\x18\x84\xda\x00\x00\x00\x00\x00\x00\x00\x00"
"\x01\x10\x02\x00\x00\x00\x00\x00\x00\x00\x01`\x00\x00\x01D\x00"
"\x00\x00\x01\x00\x00\x00\x01\x00\x00\x018\x01\x01\x00\x0d\x03\x00"
"\x00\x00\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\x00"
"\x01\x80\x04\x00\x02\x80\x0b\x00\x01\x80\x0c\x00\x01\x03\x00\x00"
"\x00\x01\x00\x00\x80\x01\x00\x01\x80\x02\x00\x01\x80\x03\x00\x01"
"\x80\x04\x00\x02\x80\x0b\x00\x01\x80\x0c\x00\x01\x03\x00\x00"
"\x00\x01\x00\x00\x80\x01\x00\x07\x80\x02\x00\x04\x80\x03\x00\x01"
"\x80\x04\x00\x0e\x80\x0b\x00\x01\x80\x0c\x00\x01\x03\x00\x00\x14"
"\x00\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\x00\x02"
"\x03\x00\x00\x14\x00\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02"
"\x80\x03\x00\x03\x03\x00\x00\x14\x00\x01\x00\x00\x80\x01\x00\x05"
"\x80\x02\x00\x02\x80\x03\x00\x04\x03\x00\x00\x14\x00\x01\x00\x00"
"\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\x00\x08\x03\x00\x00\x14"
"\x00\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\xfa\xdd"
"\x03\x00\x00\x14\x00\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02"
"\x80\x03\xfa\xdf\x03\x00\x00\x14\x00\x01\x00\x00\x80\x01\x00\x05"
"\x80\x02\x00\x02\x80\x03\xfd\xe9\x03\x00\x00\x14\x00\x01\x00\x00"
"\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\xfd\xeb\x03\x00\x00\x14"
"\x00\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02\x80\x03\xfd\xed"
"\x03\x00\x00\x14\x00\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02"
"\x80\x03\xfd\xef\x00\x00\x00\x08\x00\x01\x00\x00";

static unsigned
isakmp_parse_banner(struct Output *out, time_t timestamp,
const unsigned char *px, unsigned length,
struct PreprocessedInfo *parsed,
uint64_t entropy
) {
size_t offset = 0;

/* TODO: parse ISAKMP values */
return 0;
}

unsigned
isakmp_parse(struct Output *out, time_t timestamp,
const unsigned char *px, unsigned length,
struct PreprocessedInfo *parsed,
Expand All @@ -18,33 +74,47 @@ isakmp_parse(struct Output *out, time_t timestamp,
ipaddress ip_me;
unsigned port_them = parsed->port_src;
unsigned port_me = parsed->port_dst;
unsigned cookie;
unsigned resp_cookie;
uint64_t cookie;
uint64_t resp_cookie;
unsigned char i;

/* All memcached responses will be at least 8 bytes */
/* All responses will be at least 8 bytes */
if (length < 16)
return 0;

/* Grab IP addresses */
ip_them = parsed->src_ip;
ip_me = parsed->dst_ip;


/* Calculate the expected SYN-cookie */
cookie = (unsigned)syn_cookie(ip_them, port_them | Templ_UDP, ip_me, port_me, entropy);

/* Extract the SYN-cookie from the response*/
resp_cookie = (uint64_t)px[0] << 56ull;
resp_cookie |= (uint64_t)px[1] << 48ull;
resp_cookie |= (uint64_t)px[2] << 40ull;
resp_cookie |= (uint64_t)px[3] << 32ull;
resp_cookie |= (uint64_t)px[4] << 24ull;
resp_cookie |= (uint64_t)px[5] << 16ull;
resp_cookie |= (uint64_t)px[6] << 8ull;
resp_cookie |= (uint64_t)px[7] << 0ull;

resp_cookie = 0;
for(i = 0; i < 8; i++)
resp_cookie |= px[8 + i] << (56 - 8 * i);

if (resp_cookie != cookie)
output_report_banner(out, timestamp, ip_them, 17, port_them,
if (resp_cookie != cookie) {
/* If they aren't equal, then this is some other protocol.
* TODO: we should use a heuristic on these bytes to
* discover what the protocol probably is */
/*output_report_banner(out, timestamp, ip_them, 17, port_them,
PROTO_ERROR, parsed->ip_ttl,
(unsigned char *) "IP-MISSMATCH", 12);

output_report_banner(out, timestamp, ip_them, 17, port_them, PROTO_NONE,
parsed->ip_ttl, px, length);
(unsigned char *) "IP-MISSMATCH", 12);*/
return 0;
} else {
/* We've found our protocol, so report the banner
* TODO: we should parse this better. */
output_report_banner(out, timestamp, ip_them, 17, port_them, PROTO_ISAKMP,
parsed->ip_ttl, px, length);
return 1;
}

return 0;
}

unsigned
Expand All @@ -65,3 +135,5 @@ isakmp_set_cookie(unsigned char *px, size_t length, uint64_t seqno)

return 0;
}


8 changes: 7 additions & 1 deletion src/proto-isakmp.h
@@ -1,8 +1,14 @@
#ifndef PROTO_ISAKMP_H
#define PROTO_ISAKMP_H

#include <time.h>
#include <stdint.h>
#include <stdlib.h>
struct Output;
struct PreprocessedInfo;

unsigned isakmp_parse(struct Output *out, time_t timestamp,
const unsigned char *px, unsigned length,
struct PreprocessedInfo *parsed, uint64_t entropy);

unsigned isakmp_set_cookie(unsigned char *px, size_t length, uint64_t seqno);

Expand Down
40 changes: 25 additions & 15 deletions src/proto-udp.c
@@ -1,6 +1,7 @@
#include "proto-udp.h"
#include "proto-coap.h"
#include "proto-dns.h"
#include "proto-isakmp.h"
#include "proto-netbios.h"
#include "proto-snmp.h"
#include "proto-memcached.h"
Expand Down Expand Up @@ -59,6 +60,18 @@ handle_udp(struct Output *out, time_t timestamp,
unsigned port_them = parsed->port_src;
unsigned status = 0;

/* Report "open" status regardless */
output_report_status(
out,
timestamp,
PortStatus_Open,
ip_them,
17, /* ip proto = udp */
port_them,
0,
parsed->ip_ttl,
parsed->mac_src);


switch (port_them) {
case 53: /* DNS - Domain Name System (amplifier) */
Expand All @@ -73,8 +86,13 @@ handle_udp(struct Output *out, time_t timestamp,
case 161: /* SNMP - Simple Network Managment Protocol (amplifier) */
status = handle_snmp(out, timestamp, px, length, parsed, entropy);
break;
case 500: /* ISAKMP - IPsec key negotiation */
status = isakmp_parse(out, timestamp,
px + parsed->app_offset, parsed->app_length, parsed, entropy);
break;
case 5683:
status = coap_handle_response(out, timestamp, px + parsed->app_offset, parsed->app_length, parsed, entropy);
status = coap_handle_response(out, timestamp,
px + parsed->app_offset, parsed->app_length, parsed, entropy);
break;
case 11211: /* memcached (amplifier) */
px += parsed->app_offset;
Expand All @@ -94,19 +112,12 @@ handle_udp(struct Output *out, time_t timestamp,
break;
}

if (status == 0) {
if (px != 0 && parsed->app_length == 0) {
output_report_status(
out,
timestamp,
PortStatus_Open,
ip_them,
17, /* ip proto = udp */
port_them,
0,
parsed->ip_ttl,
parsed->mac_src);
} else {

/* Report banner if some parser didn't already do so.
* Also report raw dump if `--rawudp` specified on the
* command-line, even if a protocol above already created a more detailed
* banner. */
if (status == 0 || out->is_banner_rawudp) {
output_report_banner(
out,
timestamp,
Expand All @@ -117,6 +128,5 @@ handle_udp(struct Output *out, time_t timestamp,
parsed->ip_ttl,
px + parsed->app_offset,
parsed->app_length);
}
}
}
2 changes: 1 addition & 1 deletion src/templ-payloads.c
Expand Up @@ -314,7 +314,7 @@ struct PayloadUDP_Default hard_coded_udp_payloads[] = {
/* ISAKMP */
{500, 500, 352, 0, isakmp_set_cookie,
/* ISAKMP */
"\x00\x11\x22\x33\x44\x55\x66\x77"/* init_cookie */
"\x00\x11\x22\x33\x44\x55\x66\x77"/* init_cookie, overwritten on send() */
"\x00\x00\x00\x00\x00\x00\x00\x00" /* resp_cookie*/
"\x01" /* next_payload: SA */
"\x10" /* version */
Expand Down

0 comments on commit 2a547f7

Please sign in to comment.