Skip to content

Commit

Permalink
Merge pull request robertdavidgraham#740 from ivre/master
Browse files Browse the repository at this point in the history
ivre-masscan integration
This pulls a bunch of changes from https://github.com/ivre/masscan.
  • Loading branch information
robertdavidgraham authored Nov 9, 2023
2 parents 0d0c88f + 882391e commit 7aa740d
Show file tree
Hide file tree
Showing 28 changed files with 910 additions and 149 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
[![Build Status](https://travis-ci.org/robertdavidgraham/masscan.svg?branch=master)](https://travis-ci.org/robertdavidgraham/masscan.svg)
[![Join the chat at Gitter](https://badges.gitter.im/ivre/ivre.svg)](https://gitter.im/ivre/ivre)
[![Follow on Twitter](https://img.shields.io/twitter/follow/IvreRocks.svg?logo=twitter)](https://twitter.com/IvreRocks)
[![Follow on Mastodon](https://img.shields.io/mastodon/follow/109349639355238149?domain=https%3A%2F%2Finfosec.exchange&style=social)](https://infosec.exchange/@ivre)
[![Masscan unittests](https://github.com/ivre/masscan/actions/workflows/unittests.yml/badge.svg?branch=master)](https://github.com/ivre/masscan/actions/workflows/unittests.yml/?branch=master)

# MASSCAN: IVRE's fork

This fork is maintained by the IVRE project. **If you are looking for
the original Masscan, see the
[official repository](https://github.com/robertdavidgraham/masscan)**.

This fork contains a set of patches mostly useful to gather more data
for [IVRE](https://ivre.rocks/). While we will also accepts any useful
contributions unrelated to IVRE, some of the patches in this
repository will not be useful unless you use the results with IVRE.

# MASSCAN: Mass IP port scanner

Expand Down
11 changes: 11 additions & 0 deletions src/main-conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,13 @@ static int SET_nobanners(struct Masscan *masscan, const char *name, const char *
return CONF_OK;
}

static int SET_tcpmss(struct Masscan *masscan, const char *name, const char *value)
{
UNUSEDPARM(name);
masscan->is_tcpmss = parseBoolean(value);
return CONF_OK;
}

static int SET_noreset(struct Masscan *masscan, const char *name, const char *value)
{
UNUSEDPARM(name);
Expand Down Expand Up @@ -2302,6 +2309,7 @@ struct ConfigParameter config_parameters[] = {
{"shard", SET_shard, 0, {"shards",0}},
{"banners", SET_banners, F_BOOL, {"banner",0}},
{"nobanners", SET_nobanners, F_BOOL, {"nobanner",0}},
{"tcpmss", SET_tcpmss, F_BOOL, {"tcpmss",0}},
{"retries", SET_retries, 0, {"retry", "max-retries", "max-retry", 0}},
{"noreset", SET_noreset, F_BOOL, {0}},
{"nmap-payloads", SET_nmap_payloads, 0, {"nmap-payload",0}},
Expand Down Expand Up @@ -3699,6 +3707,9 @@ masscan_echo(struct Masscan *masscan, FILE *fp, unsigned is_echo_all)
}
fprintf(fp, "\n");
}
if (masscan->is_tcpmss) {
fprintf(fp, "tcpmss = true\n");
}
}


Expand Down
51 changes: 34 additions & 17 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@
#include <unistd.h>
#endif

/* number of different protocoles we can try at most
* on the same host:port (one per connection)
*/
#define MAX_ITER 2

/*
* yea I know globals suck
*/
Expand Down Expand Up @@ -229,6 +234,8 @@ transmit_thread(void *v) /*aka. scanning_thread() */
uint64_t *status_syn_count;
uint64_t entropy = masscan->seed;

/* Wait to make sure receive_thread is ready */
pixie_usleep(1000000);
LOG(1, "[+] starting transmit thread #%u\n", parms->nic_index);

/* export a pointer to this variable outside this threads so
Expand Down Expand Up @@ -762,8 +769,9 @@ receive_thread(void *v)
unsigned port_them;
unsigned seqno_me;
unsigned seqno_them;
unsigned cookie;
unsigned cookie[MAX_ITER];
unsigned Q = 0;
unsigned iter = 0;

/*
* RECEIVE
Expand Down Expand Up @@ -815,10 +823,14 @@ receive_thread(void *v)

switch (parsed.ip_protocol) {
case 132: /* SCTP */
cookie = syn_cookie(ip_them, port_them | (Proto_SCTP<<16), ip_me, port_me, entropy) & 0xFFFFFFFF;
/* compute all possible cookies for SCTP*/
for (unsigned int i = 0; i < MAX_ITER; i++)
cookie[i] = syn_cookie(ip_them, port_them | (Proto_SCTP<<16), ip_me, port_me, entropy + i) & 0xFFFFFFFF;
break;
default:
cookie = syn_cookie(ip_them, port_them, ip_me, port_me, entropy) & 0xFFFFFFFF;
/* compute all possible cookies for other protocols */
for (unsigned int i = 0; i < MAX_ITER; i++)
cookie[i] = syn_cookie(ip_them, port_them, ip_me, port_me, entropy + i) & 0xFFFFFFFF;
}

/* verify: my IP address */
Expand Down Expand Up @@ -914,7 +926,7 @@ receive_thread(void *v)
handle_icmp(out, secs, px, length, &parsed, entropy);
continue;
case FOUND_SCTP:
handle_sctp(out, secs, px, length, cookie, &parsed, entropy);
handle_sctp(out, secs, px, length, cookie[0], &parsed, entropy);
break;
case FOUND_OPROTO: /* other IP proto */
handle_oproto(out, secs, px, length, &parsed, entropy);
Expand Down Expand Up @@ -964,23 +976,25 @@ receive_thread(void *v)
port_me, port_them);

if (TCP_IS_SYNACK(px, parsed.transport_offset)) {
if (cookie != seqno_me - 1) {
/* check seqno against all possible cookies */
for (iter = 0; iter < MAX_ITER; iter++) {
if (cookie[iter] == seqno_me-1)
break;
ipaddress_formatted_t fmt = ipaddress_fmt(ip_them);
LOG(2, "%s - bad cookie: ackno=0x%08x expected=0x%08x\n",
fmt.string, seqno_me-1, cookie);
fmt.string, seqno_me-1, cookie[iter]);
}
if (iter == MAX_ITER) {
continue;
}

if (tcb == NULL) {
tcb = tcpcon_create_tcb(tcpcon,
ip_me, ip_them,
port_me, port_them,
seqno_me, seqno_them+1,
parsed.ip_ttl);
parsed.ip_ttl, iter);
(*status_tcb_count)++;

}

Q += stack_incoming_tcp(tcpcon, tcb, TCP_WHAT_SYNACK,
0, 0, secs, usecs, seqno_them+1);

Expand Down Expand Up @@ -1042,20 +1056,22 @@ receive_thread(void *v)

if (TCP_IS_SYNACK(px, parsed.transport_offset)
|| TCP_IS_RST(px, parsed.transport_offset)) {

/* figure out the status */
status = PortStatus_Unknown;
if (TCP_IS_SYNACK(px, parsed.transport_offset))
status = PortStatus_Open;
if (TCP_IS_RST(px, parsed.transport_offset)) {
status = PortStatus_Closed;
}

/* verify: syn-cookies */
if (cookie != seqno_me - 1) {
/* check seqno against all possible cookies */
for (iter = 0; iter < MAX_ITER; iter++) {
if (cookie[iter] == seqno_me-1)
break;
ipaddress_formatted_t fmt = ipaddress_fmt(ip_them);
LOG(5, "%s - bad cookie: ackno=0x%08x expected=0x%08x\n",
fmt.string, seqno_me-1, cookie);
LOG(2, "%s - bad cookie: ackno=0x%08x expected=0x%08x\n",
fmt.string, seqno_me-1, cookie[0]);
}
if (iter == MAX_ITER) {
continue;
}

Expand Down Expand Up @@ -1302,7 +1318,8 @@ main_scan(struct Masscan *masscan)
masscan->payloads.udp,
masscan->payloads.oproto,
stack_if_datalink(masscan->nic[index].adapter),
masscan->seed);
masscan->seed,
masscan->is_tcpmss);

/*
* Set the "source port" of everything we transmit.
Expand Down
6 changes: 6 additions & 0 deletions src/masscan-app.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ masscan_app_to_string(enum ApplicationProtocol proto)
case PROTO_IMAP4: return "imap";
case PROTO_UDP_ZEROACCESS: return "zeroaccess";
case PROTO_X509_CERT: return "X509";
case PROTO_X509_CACERT: return "X509CA";
case PROTO_HTML_TITLE: return "title";
case PROTO_HTML_FULL: return "html";
case PROTO_NTP: return "ntp";
case PROTO_VULN: return "vuln";
case PROTO_HEARTBLEED: return "heartbleed";
case PROTO_TICKETBLEED: return "ticketbleed";
case PROTO_VNC_RFB: return "vnc";
case PROTO_VNC_INFO: return "vnc-info";
case PROTO_SAFE: return "safe";
case PROTO_MEMCACHED: return "memcached";
case PROTO_SCRIPTING: return "scripting";
Expand All @@ -44,6 +46,8 @@ masscan_app_to_string(enum ApplicationProtocol proto)
case PROTO_HTTP_SERVER: return "http.server";
case PROTO_MC: return "minecraft";

case PROTO_ERROR: return "error";

default:
sprintf_s(tmp, sizeof(tmp), "(%u)", proto);
return tmp;
Expand Down Expand Up @@ -73,6 +77,7 @@ masscan_string_to_app(const char *str)
{"pop", PROTO_POP3},
{"imap", PROTO_IMAP4},
{"x509", PROTO_X509_CERT},
{"x509ca", PROTO_X509_CACERT},
{"zeroaccess", PROTO_UDP_ZEROACCESS},
{"title", PROTO_HTML_TITLE},
{"html", PROTO_HTML_FULL},
Expand All @@ -81,6 +86,7 @@ masscan_string_to_app(const char *str)
{"heartbleed", PROTO_HEARTBLEED},
{"ticketbleed", PROTO_TICKETBLEED},
{"vnc", PROTO_VNC_RFB},
{"vnc", PROTO_VNC_INFO},
{"safe", PROTO_SAFE},
{"memcached", PROTO_MEMCACHED},
{"scripting", PROTO_SCRIPTING},
Expand Down
4 changes: 4 additions & 0 deletions src/masscan-app.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ enum ApplicationProtocol {
PROTO_IMAP4,
PROTO_UDP_ZEROACCESS,
PROTO_X509_CERT,
PROTO_X509_CACERT,
PROTO_HTML_TITLE,
PROTO_HTML_FULL,
PROTO_NTP, /* network time protocol, udp/123 */
PROTO_VULN,
PROTO_HEARTBLEED,
PROTO_TICKETBLEED,
PROTO_VNC_RFB,
PROTO_VNC_INFO,
PROTO_SAFE,
PROTO_MEMCACHED,
PROTO_SCRIPTING,
Expand All @@ -39,6 +41,8 @@ enum ApplicationProtocol {
PROTO_HTTP_SERVER, /* HTTP "Server:" field */
PROTO_MC, /* Minecraft server */

PROTO_ERROR,

PROTO_end_of_list /* must be last one */
};

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_tcpmss:1; /* --tcpmss */
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
4 changes: 2 additions & 2 deletions src/out-grepable.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ grepable_out_banner(struct Output *out, FILE *fp, time_t timestamp,
enum ApplicationProtocol proto, unsigned ttl,
const unsigned char *px, unsigned length)
{
char banner_buffer[4096];
char banner_buffer[MAX_BANNER_LENGTH];
ipaddress_formatted_t fmt;

UNUSEDPARM(ttl);
UNUSEDPARM(timestamp);
UNUSEDPARM(out);
Expand Down
2 changes: 1 addition & 1 deletion src/out-text.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ text_out_banner(struct Output *out, FILE *fp, time_t timestamp,
enum ApplicationProtocol proto, unsigned ttl,
const unsigned char *px, unsigned length)
{
char banner_buffer[4096];
char banner_buffer[MAX_BANNER_LENGTH];
ipaddress_formatted_t fmt = ipaddress_fmt(ip);


Expand Down
2 changes: 1 addition & 1 deletion src/out-xml.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ xml_out_banner(struct Output *out, FILE *fp, time_t timestamp,
unsigned ttl,
const unsigned char *px, unsigned length)
{
char banner_buffer[4096];
char banner_buffer[MAX_BANNER_LENGTH];
const char *reason;
ipaddress_formatted_t fmt = ipaddress_fmt(ip);

Expand Down
2 changes: 1 addition & 1 deletion src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,7 @@ output_report_banner(struct Output *out, time_t now,
* line screen */
if (out->is_interactive || out->format == 0 || out->format == Output_Interactive) {
unsigned count;
char banner_buffer[4096];
char banner_buffer[MAX_BANNER_LENGTH];

count = fprintf(stdout, "Banner on port %u/%s on %s: [%s] %s",
port,
Expand Down
2 changes: 2 additions & 0 deletions src/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "unusedparm.h"
#include "masscan-app.h"

#define MAX_BANNER_LENGTH 8192

struct Masscan;
struct Output;
enum ApplicationProtocol;
Expand Down
Loading

0 comments on commit 7aa740d

Please sign in to comment.