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

added --rawudp, prints raw UDP regardless of other banners #744

Merged
merged 1 commit into from
Nov 16, 2023
Merged
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
20 changes: 18 additions & 2 deletions src/main-conf.c
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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