Skip to content

Commit

Permalink
multi-banner
Browse files Browse the repository at this point in the history
  • Loading branch information
robertdavidgraham committed Dec 15, 2013
1 parent 1614462 commit ba04285
Show file tree
Hide file tree
Showing 22 changed files with 3,273 additions and 1,869 deletions.
426 changes: 426 additions & 0 deletions doc/algorithm.js

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions src/in-binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,16 @@ convert_binary_files(struct Masscan *masscan,

out = output_create(masscan, 0);

/*
* We don't parse the entire argument list, just a subrange
* containing the list of files. The 'arg_first' parameter
* points to the first filename after the '--readscan'
* parameter, and 'arg_max' is the parameter after
* the last filename. For example, consider an argument list that
* looks like:
* masscan --foo --readscan file1.scan file2.scan --bar
* Then arg_first=3 and arg_max=5.
*/
for (i=arg_first; i<arg_max; i++) {
parse_file(out, argv[i]);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main-conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,7 @@ masscan_set_parameter(struct Masscan *masscan,
masscan->seed = time(0);
else
masscan->seed = parseInt(value);
} else if (EQUALS("sendq", name)) {
} else if (EQUALS("sendq", name) || EQUALS("sendqueue", name)) {
masscan->is_sendq = 1;
} else if (EQUALS("send-eth", name)) {
fprintf(stderr, "nmap(%s): unnecessary, we always do --send-eth\n", name);
Expand Down
6 changes: 6 additions & 0 deletions src/masscan-app.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ const char *
masscan_app_to_string(enum ApplicationProtocol proto)
{
static char tmp[64];

switch (proto) {
case PROTO_NONE: return "unknown";
case PROTO_HEUR: return "unknown";
case PROTO_SSH1: return "ssh";
case PROTO_SSH2: return "ssh";
case PROTO_HTTP: return "http";
Expand All @@ -21,6 +24,9 @@ masscan_app_to_string(enum ApplicationProtocol proto)
case PROTO_POP3: return "pop";
case PROTO_IMAP4: return "imap";
case PROTO_UDP_ZEROACCESS: return "zeroaccess";
case PROTO_X509_CERT: return "X509";
case PROTO_HTML_TITLE: return "title";
case PROTO_HTML_FULL: return "html";

default:
sprintf_s(tmp, sizeof(tmp), "(%u)", proto);
Expand Down
6 changes: 5 additions & 1 deletion src/masscan-app.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
#define MASSCAN_APP_H

enum ApplicationProtocol {
PROTO_UNKNOWN,
PROTO_NONE,
PROTO_HEUR,
PROTO_SSH1,
PROTO_SSH2,
PROTO_HTTP,
Expand All @@ -16,6 +17,9 @@ enum ApplicationProtocol {
PROTO_POP3,
PROTO_IMAP4,
PROTO_UDP_ZEROACCESS,
PROTO_X509_CERT,
PROTO_HTML_TITLE,
PROTO_HTML_FULL,
};

const char *
Expand Down
3 changes: 2 additions & 1 deletion src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -715,12 +715,13 @@ output_report_banner(struct Output *out, time_t now,
unsigned count;
char banner_buffer[4096];

count = fprintf(stdout, "Banner on port %u/tcp on %u.%u.%u.%u: %s",
count = fprintf(stdout, "Banner on port %u/tcp on %u.%u.%u.%u: [%s] %s",
port,
(ip>>24)&0xFF,
(ip>>16)&0xFF,
(ip>> 8)&0xFF,
(ip>> 0)&0xFF,
masscan_app_to_string(proto),
normalize_string(px, length, banner_buffer, sizeof(banner_buffer))
);

Expand Down
184 changes: 91 additions & 93 deletions src/proto-banner1.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>



Expand Down Expand Up @@ -39,63 +40,64 @@ struct Patterns patterns[] = {

/***************************************************************************
***************************************************************************/
void
unsigned
banner1_parse(
struct Banner1 *banner1,
struct Banner1State *pstate,
unsigned *proto,
const struct Banner1 *banner1,
struct ProtocolState *tcb_state,
const unsigned char *px, size_t length,
char *banner, unsigned *banner_offset, size_t banner_max)
struct BannerOutput *banout)
{
size_t x;
unsigned offset = 0;

switch (*proto) {
case PROTO_UNKNOWN:
switch (tcb_state->app_proto) {
case PROTO_NONE:
case PROTO_HEUR:
x = smack_search_next(
banner1->smack,
&pstate->state,
&tcb_state->state,
px, &offset, (unsigned)length);
if (x != SMACK_NOT_FOUND
&& !(x == PROTO_SSL3 && !pstate->is_sent_sslhello)) {
&& !(x == PROTO_SSL3 && !tcb_state->is_sent_sslhello)) {
unsigned i;

/* re-read the stuff that we missed */
for (i=0; patterns[i].id && patterns[i].id != tcb_state->app_proto; i++)
;

/* Kludge: patterns look confusing, so add port info to the
* pattern */
switch (*proto) {
switch (x) {
case PROTO_FTP2:
if (pstate->port == 25 || pstate->port == 587)
*proto = PROTO_SMTP;
if (tcb_state->port == 25 || tcb_state->port == 587)
x = PROTO_SMTP;
break;
}

*proto = (unsigned)x;
tcb_state->app_proto = (unsigned short)x;

/* reset the state back again */
pstate->state = 0;

/* re-read the stuff that we missed */
for (i=0; patterns[i].id != *proto; i++)
;

*banner_offset = 0;

banner1_parse(
banner1,
pstate, proto,
(const unsigned char*)patterns[i].pattern, patterns[i].pattern_length,
banner, banner_offset, banner_max);
tcb_state->state = 0;

/* If there is any data from a previous packet, re-parse that */
{
const unsigned char *s = banout_string(banout, PROTO_HEUR);
unsigned s_len = banout_string_length(banout, PROTO_HEUR);

if (s && s_len)
banner1_parse(
banner1,
tcb_state,
s, s_len,
banout);
}
banner1_parse(
banner1,
pstate, proto,
px+offset, length-offset,
banner, banner_offset, banner_max);
tcb_state,
px, length,
banout);
} else {
size_t len = length;
if (len > banner_max - *banner_offset)
len = banner_max - *banner_offset;
memcpy(banner + *banner_offset, px, len);
(*banner_offset) += (unsigned)len;
banout_append(banout, PROTO_HEUR, px, length);
}
break;
case PROTO_SSH1:
Expand All @@ -110,31 +112,33 @@ banner1_parse(
* especially when binary parsing is added to SSH */
banner_ssh.parse( banner1,
banner1->http_fields,
pstate,
tcb_state,
px, length,
banner, banner_offset, banner_max);
banout);
break;
case PROTO_HTTP:
banner_http.parse(
banner1,
banner1->http_fields,
pstate,
tcb_state,
px, length,
banner, banner_offset, banner_max);
banout);
break;
case PROTO_SSL3:
banner_ssl.parse(
banner1,
banner1->http_fields,
pstate,
tcb_state,
px, length,
banner, banner_offset, banner_max);
banout);
break;
default:
fprintf(stderr, "banner1: internal error\n");
break;

}

return tcb_state->app_proto;
}

/***************************************************************************
Expand Down Expand Up @@ -169,31 +173,6 @@ banner1_create(void)
return b;
}

/***************************************************************************
***************************************************************************/
void
banner_append(const void *vsrc, size_t src_len,
void *vbanner, unsigned *banner_offset, size_t banner_max)
{
const unsigned char *src = (const unsigned char *)vsrc;
unsigned char *banner = (unsigned char *)vbanner;
size_t i;

for (i=0; i<src_len; i++) {
if (*banner_offset < banner_max)
banner[(*banner_offset)++] = src[i];
}
}

void
banner_append_char(int c,
void *vbanner, unsigned *banner_offset, size_t banner_max)
{
unsigned char *banner = (unsigned char *)vbanner;

if (*banner_offset < banner_max)
banner[(*banner_offset)++] = (unsigned char)c;
}

/***************************************************************************
***************************************************************************/
Expand All @@ -210,6 +189,9 @@ banner1_destroy(struct Banner1 *b)
}





/***************************************************************************
* Test the banner1 detection system by throwing random frames at it
***************************************************************************/
Expand Down Expand Up @@ -258,16 +240,15 @@ banner1_test(const char *filename)

/***************************************************************************
***************************************************************************/
int banner1_selftest()
int
banner1_selftest()
{
unsigned i;
struct Banner1 *b;
char banner[128];
unsigned banner_offset;
struct Banner1State pstate[1];
unsigned proto;
struct ProtocolState tcb_state[1];
const unsigned char *px;
unsigned length;
struct BannerOutput banout[1];
static const char *http_header =
"HTTP/1.0 302 Redirect\r\n"
"Date: Tue, 03 Sep 2013 06:50:01 GMT\r\n"
Expand All @@ -279,48 +260,56 @@ int banner1_selftest()
"Content-Language: en\r\n"
"Location: http://failsafe.fp.yahoo.com/404.html\r\n"
"Content-Length: 227\r\n"
"\r\n";
"\r\n<title>hello</title>\n";
px = (const unsigned char *)http_header;
length = (unsigned)strlen(http_header);


/*
* First, test the "banout" subsystem
*/
if (banout_selftest() != 0) {
fprintf(stderr, "banout: failed\n");
return 1;
}


/*
* Test one character at a time
*/
b = banner1_create();
memset(banner, 0xa3, sizeof(banner));
memset(pstate, 0, sizeof(pstate[0]));
proto = 0;
banner_offset = 0;
banout_init(banout);

memset(tcb_state, 0, sizeof(tcb_state[0]));

for (i=0; i<length; i++)
banner1_parse(
b,
pstate,
&proto,
tcb_state,
px+i, 1,
banner, &banner_offset, sizeof(banner)
);
banout);
{
const unsigned char *s = banout_string(banout, PROTO_HTTP);
if (memcmp(s, "HTTP/1.0 302", 11) != 0) {
printf("banner1: test failed\n");
return 1;
}
}
banout_release(banout);
banner1_destroy(b);
/*if (memcmp(banner, "Via:HTTP/1.1", 11) != 0) {
printf("banner1: test failed\n");
return 1;
}*/

/*
* Test whole buffer
*/
b = banner1_create();
memset(banner, 0xa3, sizeof(banner));
memset(pstate, 0, sizeof(pstate[0]));
proto = 0;
banner_offset = 0;

memset(tcb_state, 0, sizeof(tcb_state[0]));

banner1_parse(
b,
pstate,
&proto,
tcb_state,
px, length,
banner, &banner_offset, sizeof(banner)
);
banout);
banner1_destroy(b);
/*if (memcmp(banner, "Via:HTTP/1.1", 11) != 0) {
printf("banner1: test failed\n");
Expand All @@ -331,8 +320,17 @@ int banner1_selftest()
{
int x = 0;

x += banner_ssl.selftest();
x += banner_http.selftest();
x = banner_ssl.selftest();
if (x) {
fprintf(stderr, "SSL banner: selftest failed\n");
return 1;
}

x = banner_http.selftest();
if (x) {
fprintf(stderr, "HTTP banner: selftest failed\n");
return 1;
}

return x;
}
Expand Down
Loading

0 comments on commit ba04285

Please sign in to comment.