masscan-mark-ii/src/proto-banner1.c

844 lines
28 KiB
C

/*
state machine for receiving banners
*/
#include "smack.h"
#include "rawsock-pcapfile.h"
#include "proto-preprocess.h"
#include "stack-tcp-api.h"
#include "proto-banner1.h"
#include "proto-http.h"
#include "proto-ssl.h"
#include "proto-smb.h"
#include "proto-ssh.h"
#include "proto-ftp.h"
#include "proto-smtp.h"
#include "proto-tcp-telnet.h"
#include "proto-tcp-rdp.h"
#include "proto-imap4.h"
#include "proto-pop3.h"
#include "proto-vnc.h"
#include "proto-memcached.h"
#include "proto-mc.h"
#include "proto-versioning.h"
#include "masscan-app.h"
#include "scripting.h"
#include "util-malloc.h"
#include "util-logger.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
struct Patterns patterns[] = {
{"\x00\x00" "**" "\xff" "SMB", 8, PROTO_SMB, SMACK_ANCHOR_BEGIN | SMACK_WILDCARDS, 0},
{"\x00\x00" "**" "\xfe" "SMB", 8, PROTO_SMB, SMACK_ANCHOR_BEGIN | SMACK_WILDCARDS, 0},
{"\x82\x00\x00\x00", 4, PROTO_SMB, SMACK_ANCHOR_BEGIN, 0}, /* Positive Session Response */
{"\x83\x00\x00\x01\x80", 5, PROTO_SMB, SMACK_ANCHOR_BEGIN, 0}, /* Not listening on called name */
{"\x83\x00\x00\x01\x81", 5, PROTO_SMB, SMACK_ANCHOR_BEGIN, 0}, /* Not listening for calling name */
{"\x83\x00\x00\x01\x82", 5, PROTO_SMB, SMACK_ANCHOR_BEGIN, 0}, /* Called name not present */
{"\x83\x00\x00\x01\x83", 5, PROTO_SMB, SMACK_ANCHOR_BEGIN, 0}, /* Called name present, but insufficient resources */
{"\x83\x00\x00\x01\x8f", 5, PROTO_SMB, SMACK_ANCHOR_BEGIN, 0}, /* Unspecified error */
/* ...the remainder can be in any order */
{"{\x22", 2, PROTO_MC, 0, 0},
{"SSH-1.", 6, PROTO_SSH1, SMACK_ANCHOR_BEGIN, 0},
{"SSH-2.", 6, PROTO_SSH2, SMACK_ANCHOR_BEGIN, 0},
{"HTTP/1.", 7, PROTO_HTTP, SMACK_ANCHOR_BEGIN, 0},
{"220-", 4, PROTO_FTP, SMACK_ANCHOR_BEGIN, 0},
{"220 ", 4, PROTO_FTP, SMACK_ANCHOR_BEGIN, 1},
{"+OK ", 4, PROTO_POP3, SMACK_ANCHOR_BEGIN, 0},
{"* OK ", 5, PROTO_IMAP4, SMACK_ANCHOR_BEGIN, 0},
{"521 ", 4, PROTO_SMTP, SMACK_ANCHOR_BEGIN, 0},
{"\x16\x03\x00",3, PROTO_SSL3, SMACK_ANCHOR_BEGIN, 0},
{"\x16\x03\x01",3, PROTO_SSL3, SMACK_ANCHOR_BEGIN, 0},
{"\x16\x03\x02",3, PROTO_SSL3, SMACK_ANCHOR_BEGIN, 0},
{"\x16\x03\x03",3, PROTO_SSL3, SMACK_ANCHOR_BEGIN, 0},
{"\x15\x03\x00",3, PROTO_SSL3, SMACK_ANCHOR_BEGIN, 0},
{"\x15\x03\x01",3, PROTO_SSL3, SMACK_ANCHOR_BEGIN, 0},
{"\x15\x03\x02",3, PROTO_SSL3, SMACK_ANCHOR_BEGIN, 0},
{"\x15\x03\x03",3, PROTO_SSL3, SMACK_ANCHOR_BEGIN, 0},
{"RFB 000.000\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 1}, /* UltraVNC repeater mode */
{"RFB 003.003\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 3}, /* default version for everything */
{"RFB 003.005\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 3}, /* broken, same as 003.003 */
{"RFB 003.006\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 3}, /* broken, same as 003.003 */
{"RFB 003.007\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 7},
{"RFB 003.008\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 8},
{"RFB 003.889\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 8}, /* Apple's remote desktop, 003.007 */
{"RFB 003.009\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 8},
{"RFB 004.000\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 8}, /* Intel AMT KVM */
{"RFB 004.001\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 8}, /* RealVNC 4.6 */
{"RFB 004.002\n", 12, PROTO_VNC_RFB, SMACK_ANCHOR_BEGIN, 8},
{"STAT pid ", 9, PROTO_MEMCACHED,SMACK_ANCHOR_BEGIN, 0}, /* memcached stat response */
{"\xff\xfb\x01\xff\xf0", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb\x01\xff\xfb", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb\x01\xff\xfc", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb\x01\xff\xfd", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb\x01\xff\xfe", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb\x01\x0a\x0d", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb\x01\x0d\x0a", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb\x01\x0d\x0d", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb\x01\x0a\x0a", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb%\x25xff\xfb", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb\x26\xff\xfd", 5, PROTO_TELNET, 0, 0},
{"\xff\xfd\x18\xff\xfd", 5, PROTO_TELNET, 0, 0},
{"\xff\xfd\x20\xff\xfd", 5, PROTO_TELNET, 0, 0},
{"\xff\xfd\x23\xff\xfd", 5, PROTO_TELNET, 0, 0},
{"\xff\xfd\x27\xff\xfd", 5, PROTO_TELNET, 0, 0},
{"\xff\xfb\x01\x1b[", 5, PROTO_TELNET, SMACK_ANCHOR_BEGIN, 0},
{"\xff\xfb\x01Input", 8, PROTO_TELNET, SMACK_ANCHOR_BEGIN, 0},
{"\xff\xfb\x01 ", 6, PROTO_TELNET, SMACK_ANCHOR_BEGIN, 0},
{"\xff\xfb\x01login", 8, PROTO_TELNET, SMACK_ANCHOR_BEGIN, 0},
{"login:", 6, PROTO_TELNET, SMACK_ANCHOR_BEGIN, 0},
{"password:", 9, PROTO_TELNET, SMACK_ANCHOR_BEGIN, 0},
{"\x03\x00\x00\x13\x0e\xd0\xbe\xef\x12\x34\x00\x02\x0f\x08\x00\x00\x00\x00\x00",
12, PROTO_RDP, SMACK_ANCHOR_BEGIN, 0},
{"\x03\x00\x00\x13\x0e\xd0\x00\x00\x12\x34\x00\x02\x0f\x08\x00\x00\x00\x00\x00",
12, PROTO_RDP, SMACK_ANCHOR_BEGIN, 0},
{0,0,0,0,0}
};
/***************************************************************************
***************************************************************************/
unsigned
banner1_parse(
const struct Banner1 *banner1,
struct StreamState *tcb_state,
const unsigned char *px, size_t length,
struct BannerOutput *banout,
struct stack_handle_t *socket)
{
size_t x;
unsigned offset = 0;
unsigned proto;
switch (tcb_state->app_proto) {
case PROTO_NONE:
case PROTO_HEUR:
x = smack_search_next(
banner1->smack,
&tcb_state->state,
px, &offset, (unsigned)length);
if (x == SMACK_NOT_FOUND)
proto = 0xFFFFFFFF;
else
proto = patterns[x].id;
if (proto != 0xFFFFFFFF
&& !(proto == 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) {
case PROTO_FTP:
if (patterns[x].extra == 1) {
if (tcb_state->port == 25 || tcb_state->port == 587)
proto = PROTO_SMTP;
}
break;
case PROTO_VNC_RFB:
tcb_state->sub.vnc.version = (unsigned char)patterns[x].extra;
break;
}
tcb_state->app_proto = (unsigned short)proto;
/* reset the state back again */
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,
socket);
}
banner1_parse(
banner1,
tcb_state,
px, length,
banout,
socket);
} else {
banout_append(banout, PROTO_HEUR, px, length);
}
break;
case PROTO_FTP:
banner_ftp.parse( banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_SMTP:
banner_smtp.parse( banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_TELNET:
banner_telnet.parse( banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_RDP:
banner_rdp.parse( banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_POP3:
banner_pop3.parse( banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_IMAP4:
banner_imap4.parse(banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_SSH1:
case PROTO_SSH2:
/* generic text-based parser
* TODO: in future, need to split these into separate protocols,
* especially when binary parsing is added to SSH */
banner_ssh.parse( banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_HTTP:
banner_http.parse(
banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_SSL3:
banner_ssl.parse(
banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_SMB:
banner_smb1.parse(
banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_VNC_RFB:
banner_vnc.parse( banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_MEMCACHED:
banner_memcached.parse( banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_SCRIPTING:
banner_scripting.parse( banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_VERSIONING:
banner_versioning.parse( banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
case PROTO_MC:
banner_mc.parse(
banner1,
banner1->http_fields,
tcb_state,
px, length,
banout,
socket);
break;
default:
fprintf(stderr, "banner1: internal error\n");
break;
}
return tcb_state->app_proto;
}
/*
* Simple banners with hello probes from nmap-service-probes
*/
static const char
genericlines_hello[] = "\r\n\r\n";
struct ProtocolParserStream banner_genericlines = {
"banner-GenericLines", 1098, genericlines_hello, sizeof(genericlines_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
x11_hello[] = "\x6C\0\x0B\0\0\0\0\0\0\0\0\0";
struct ProtocolParserStream banner_x11 = {
"banner-X11Probe", 6000, x11_hello, sizeof(x11_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
javarmi_hello[] = "\x4a\x52\x4d\x49\0\x02\x4b";
struct ProtocolParserStream banner_javarmi = {
"banner-JavaRMI", 1098, javarmi_hello, sizeof(javarmi_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
mongodb_hello[] = "\x41\0\0\0\x3a\x30\0\0\xff\xff\xff\xff\xd4\x07\0\0\0\0\0\0test.$cmd\0\0\0\0\0\xff\xff\xff\xff\x1b\0\0\0\x01serverStatus\0\0\0\0\0\0\0\xf0\x3f\0";
struct ProtocolParserStream banner_mongodb = {
"banner-mongodb", 27017, mongodb_hello, sizeof(mongodb_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
kerberos_hello[] = "\0\0\0\x71\x6a\x81\x6e\x30\x81\x6b\xa1\x03\x02\x01\x05\xa2\x03\x02\x01\x0a\xa4\x81\x5e\x30\x5c\xa0\x07\x03\x05\0\x50\x80\0\x10\xa2\x04\x1b\x02NM\xa3\x17\x30\x15\xa0\x03\x02\x01\0\xa1\x0e\x30\x0c\x1b\x06krbtgt\x1b\x02NM\xa5\x11\x18\x0f""19700101000000Z\xa7\x06\x02\x04\x1f\x1e\xb9\xd9\xa8\x17\x30\x15\x02\x01\x12\x02\x01\x11\x02\x01\x10\x02\x01\x17\x02\x01\x01\x02\x01\x03\x02\x01\x02";
struct ProtocolParserStream banner_kerberos = {
"banner-Kerberos", 88, kerberos_hello, sizeof(kerberos_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
dicom_hello[] = "\x01\x00\x00\x00\x00\xcd\x00\x01\x00\x00""ANY-SCP ECHOSCU 0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x15""1.2.840.10008.3.1.1.1 \x00\x00.\x01\x00\x00\x00""0\x00\x00\x11""1.2.840.10008.1.1@\x00\x00\x11""1.2.840.10008.1.2P\x00\x00:Q\x00\x00\x04\x00\x00@\x00R\x00\x00\x1b""1.2.276.0.7230010.3.0.3.6.2U\x00\x00\x0fOFFIS_DCMTK_362";
struct ProtocolParserStream banner_dicom = {
"banner-dicom", 104, dicom_hello, sizeof(dicom_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
ldap_hello[] = "\x30\x84\x00\x00\x00\x2d\x02\x01\x07\x63\x84\x00\x00\x00\x24\x04\x00\x0a\x01\x00\x0a\x01\x00\x02\x01\x00\x02\x01\x64\x01\x01\x00\x87\x0b\x6f\x62\x6a\x65\x63\x74\x43\x6c\x61\x73\x73\x30\x84\x00\x00\x00\x00";
struct ProtocolParserStream banner_ldap = {
"banner-LDAPSearchReq", 389, ldap_hello, sizeof(ldap_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
sip_hello[] = "OPTIONS sip:nm SIP/2.0\r\nVia: SIP/2.0/TCP nm;branch=foo\r\nFrom: <sip:nm@nm>;tag=root\r\nTo: <sip:nm2@nm2>\r\nCall-ID: 50000\r\nCSeq: 42 OPTIONS\r\nMax-Forwards: 70\r\nContent-Length: 0\r\nContact: <sip:nm@nm>\r\nAccept: application/sdp\r\n\r\n";
struct ProtocolParserStream banner_sip = {
"banner-SIPOptions", 5060, sip_hello, sizeof(sip_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
rtsp_hello[] = "OPTIONS / RTSP/1.0\r\n\r\n";
struct ProtocolParserStream banner_rtsp = {
"banner-RTSPRequest", 554, rtsp_hello, sizeof(rtsp_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
rpc_hello[] = "\x80\0\0\x28\x72\xFE\x1D\x13\0\0\0\0\0\0\0\x02\0\x01\x86\xA0\0\x01\x97\x7C\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
struct ProtocolParserStream banner_rpc = {
"banner-RPCCheck", 111, rpc_hello, sizeof(rpc_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
dns_hello[] = "\0\x1E\0\x06\x01\0\0\x01\0\0\0\0\0\0\x07version\x04""bind\0\0\x10\0\x03";
struct ProtocolParserStream banner_dns = {
"banner-DNSVersionBindReqTCP", 53, dns_hello, sizeof(dns_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
docker_hello[] = "GET /version HTTP/1.1\r\n\r\n";
struct ProtocolParserStream banner_docker = {
"banner-docker", 2375, docker_hello, sizeof(docker_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
redis_hello[] = "*1\r\n$4\r\ninfo\r\n";
struct ProtocolParserStream banner_redis = {
"banner-redis-server", 6379, redis_hello, sizeof(redis_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
notes_rpc_hello[] = "\x3A\x00\x00\x00\x2F\x00\x00\x00\x02\x00\x00\x40\x02\x0F\x00\x01\x00\x3D\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x1F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
struct ProtocolParserStream banner_notes_rpc = {
"banner-NotesRPC", 6379, notes_rpc_hello, sizeof(notes_rpc_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
ms_sql_s_hello[] = "\x12\x01\x00\x34\x00\x00\x00\x00\x00\x00\x15\x00\x06\x01\x00\x1b\x00\x01\x02\x00\x1c\x00\x0c\x03\x00\x28\x00\x04\xff\x08\x00\x01\x55\x00\x00\x00\x4d\x53\x53\x51\x4c\x53\x65\x72\x76\x65\x72\x00\x48\x0f\x00\x00";
struct ProtocolParserStream banner_ms_sql_s = {
"banner-ms-sql-s", 6379, ms_sql_s_hello, sizeof(ms_sql_s_hello) - 1, 0,
NULL,
NULL,
NULL,
};
static const char
afp_hello[] = "\x00\x03\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x0f\x00";
struct ProtocolParserStream banner_afp = {
"banner-afp", 548, afp_hello, sizeof(afp_hello) - 1, 0,
NULL,
NULL,
NULL,
};
/***************************************************************************
* Create the --banners systems
***************************************************************************/
struct Banner1 *
banner1_create(void)
{
struct Banner1 *b;
unsigned i;
b = CALLOC(1, sizeof(*b));
/*
* This creates a pattern-matching blob for heuristically determining
* a protocol that runs on wrong ports, such as how FTP servers
* often respond with "220 " or VNC servers respond with "RFB".
*/
b->smack = smack_create("banner1", SMACK_CASE_INSENSITIVE);
for (i=0; patterns[i].pattern; i++)
smack_add_pattern(
b->smack,
patterns[i].pattern,
patterns[i].pattern_length,
i,
patterns[i].is_anchored);
smack_compile(b->smack);
/*
* [TODO] These need to be moved into the 'init' functions
*/
b->payloads.tcp[80] = &banner_http;
b->payloads.tcp[8080] = &banner_http;
b->payloads.tcp[139] = (void*)&banner_smb0;
b->payloads.tcp[445] = (void*)&banner_smb1;
b->payloads.tcp[8530] = (void*)&banner_http; /* WSUS */
b->payloads.tcp[8531] = (void*)&banner_ssl; /* WSUS/s */
/* https://www.nomotion.net/blog/sharknatto/ */
b->payloads.tcp[49955] = (void*)&banner_ssl; /* AT&T box */
b->payloads.tcp[443] = (void*)&banner_ssl; /* HTTP/s */
b->payloads.tcp[465] = (void*)&banner_ssl; /* SMTP/s */
b->payloads.tcp[990] = (void*)&banner_ssl; /* FTP/s */
b->payloads.tcp[991] = (void*)&banner_ssl;
b->payloads.tcp[992] = (void*)&banner_ssl; /* Telnet/s */
b->payloads.tcp[993] = (void*)&banner_ssl; /* IMAP4/s */
b->payloads.tcp[994] = (void*)&banner_ssl;
b->payloads.tcp[995] = (void*)&banner_ssl; /* POP3/s */
b->payloads.tcp[2083] = (void*)&banner_ssl; /* cPanel - SSL */
b->payloads.tcp[2087] = (void*)&banner_ssl; /* WHM - SSL */
b->payloads.tcp[2096] = (void*)&banner_ssl; /* cPanel webmail - SSL */
b->payloads.tcp[8443] = (void*)&banner_ssl; /* Plesk Control Panel - SSL */
b->payloads.tcp[9050] = (void*)&banner_ssl; /* Tor */
b->payloads.tcp[8140] = (void*)&banner_ssl; /* puppet */
b->payloads.tcp[11211] = (void*)&banner_memcached;
b->payloads.tcp[23] = (void*)&banner_telnet;
b->payloads.tcp[3389] = (void*)&banner_rdp;
b->payloads.tcp[1098] = (void*)&banner_javarmi;
b->payloads.tcp[1099] = (void*)&banner_javarmi;
for (i=0; i < 20; i++) {
b->payloads.tcp[6000 + i] = (void*)&banner_x11;
}
b->payloads.tcp[88] = (void*)&banner_kerberos;
b->payloads.tcp[9001] = (void*)&banner_mongodb;
b->payloads.tcp[27017] = (void*)&banner_mongodb;
b->payloads.tcp[49153] = (void*)&banner_mongodb;
b->payloads.tcp[104] = (void*)&banner_dicom;
b->payloads.tcp[2345] = (void*)&banner_dicom;
b->payloads.tcp[2761] = (void*)&banner_dicom;
b->payloads.tcp[2762] = (void*)&banner_dicom;
b->payloads.tcp[4242] = (void*)&banner_dicom;
b->payloads.tcp[11112] = (void*)&banner_dicom;
b->payloads.tcp[256] = (void*)&banner_ldap;
b->payloads.tcp[257] = (void*)&banner_ldap;
b->payloads.tcp[389] = (void*)&banner_ldap;
b->payloads.tcp[390] = (void*)&banner_ldap;
b->payloads.tcp[1702] = (void*)&banner_ldap;
b->payloads.tcp[3268] = (void*)&banner_ldap;
b->payloads.tcp[3892] = (void*)&banner_ldap;
b->payloads.tcp[11711] = (void*)&banner_ldap;
/* LDAP/s */
b->payloads.tcp[636] = (void*)&banner_ssl;
b->payloads.tcp[637] = (void*)&banner_ssl;
b->payloads.tcp[3269] = (void*)&banner_ssl;
b->payloads.tcp[11712] = (void*)&banner_ssl;
b->payloads.tcp[406] = (void*)&banner_sip;
b->payloads.tcp[5060] = (void*)&banner_sip;
b->payloads.tcp[8081] = (void*)&banner_sip;
b->payloads.tcp[31337] = (void*)&banner_sip;
/* SIP/s */
b->payloads.tcp[5061] = (void*)&banner_ssl;
b->payloads.tcp[554] = (void*)&banner_rtsp;
b->payloads.tcp[8554] = (void*)&banner_rtsp;
/* RTSP/s */
b->payloads.tcp[322] = (void*)&banner_ssl;
b->payloads.tcp[111] = (void*)&banner_rpc;
b->payloads.tcp[2049] = (void*)&banner_rpc;
b->payloads.tcp[53] = (void*)&banner_dns;
b->payloads.tcp[135] = (void*)&banner_dns;
b->payloads.tcp[50000] = (void*)&banner_dns;
b->payloads.tcp[50001] = (void*)&banner_dns;
b->payloads.tcp[50002] = (void*)&banner_dns;
b->payloads.tcp[2375] = (void*)&banner_docker;
/* Docker/s */
b->payloads.tcp[2376] = (void*)&banner_ssl;
b->payloads.tcp[2379] = (void*)&banner_docker;
b->payloads.tcp[2380] = (void*)&banner_docker;
b->payloads.tcp[6379] = (void*)&banner_redis;
b->payloads.tcp[130] = (void*)&banner_notes_rpc;
b->payloads.tcp[427] = (void*)&banner_notes_rpc;
b->payloads.tcp[1352] = (void*)&banner_notes_rpc;
b->payloads.tcp[1972] = (void*)&banner_notes_rpc;
b->payloads.tcp[7171] = (void*)&banner_notes_rpc;
b->payloads.tcp[8728] = (void*)&banner_notes_rpc;
b->payloads.tcp[22001] = (void*)&banner_notes_rpc;
b->payloads.tcp[1433] = (void*)&banner_ms_sql_s;
/* AFP */
b->payloads.tcp[548] = (void*)&banner_afp;
/*
* This goes down the list of all the TCP protocol handlers and initializes
* them.
*/
banner_ftp.init(b);
banner_http.init(b);
banner_imap4.init(b);
banner_memcached.init(b);
banner_pop3.init(b);
banner_smtp.init(b);
banner_ssh.init(b);
banner_ssl.init(b);
banner_ssl_12.init(b);
banner_smb0.init(b);
banner_smb1.init(b);
banner_telnet.init(b);
banner_rdp.init(b);
banner_vnc.init(b);
banner_mc.init(b);
/* scripting/versioning come after the rest */
//banner_scripting.init(b);
//banner_versioning.init(b);
return b;
}
/***************************************************************************
***************************************************************************/
void
banner1_destroy(struct Banner1 *b)
{
if (b == NULL)
return;
if (b->smack)
smack_destroy(b->smack);
if (b->http_fields)
smack_destroy(b->http_fields);
free(b);
}
/***************************************************************************
* Test the banner1 detection system by throwing random frames at it
***************************************************************************/
void
banner1_test(const char *filename)
{
struct PcapFile *cap;
unsigned link_type;
cap = pcapfile_openread(filename);
if (cap == NULL) {
fprintf(stderr, "%s: can't open capture file\n", filename);
return;
}
link_type = pcapfile_datalink(cap);
for (;;) {
int packets_read;
unsigned secs;
unsigned usecs;
unsigned origlength;
unsigned length;
unsigned char px[65536];
struct PreprocessedInfo parsed;
unsigned x;
packets_read = pcapfile_readframe(
cap, /* capture dump file */
&secs, &usecs,
&origlength, &length,
px, sizeof(px));
if (packets_read == 0)
break;
x = preprocess_frame(px, length, link_type, &parsed);
if (x == 0)
continue;
}
pcapfile_close(cap);
}
/***************************************************************************
***************************************************************************/
int
banner1_selftest()
{
unsigned i;
struct Banner1 *b;
struct StreamState 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"
"Connection: close\r\n"
"Via: HTTP/1.1 ir14.fp.bf1.yahoo.com (YahooTrafficServer/1.2.0.13 [c s f ])\r\n"
"Server: YTS/1.20.13\r\n"
"Cache-Control: no-store\r\n"
"Content-Type: text/html\r\n"
"Content-Language: en\r\n"
"Location: http://failsafe.fp.yahoo.com/404.html\r\n"
"Content-Length: 227\r\n"
"\r\n<title>hello</title>\n";
px = (const unsigned char *)http_header;
length = (unsigned)strlen(http_header);
LOG(1, "[ ] banners: selftesting\n");
/*
* 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();
banout_init(banout);
memset(tcb_state, 0, sizeof(tcb_state[0]));
for (i=0; i<length; i++) {
struct stack_handle_t more = {0,0};
banner1_parse(
b,
tcb_state,
px+i, 1,
banout,
&more);
}
{
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);
/*
* Test whole buffer
*/
b = banner1_create();
memset(tcb_state, 0, sizeof(tcb_state[0]));
banner1_parse(
b,
tcb_state,
px, length,
banout,
0);
banner1_destroy(b);
/*if (memcmp(banner, "Via:HTTP/1.1", 11) != 0) {
printf("banner1: test failed\n");
return 1;
}*/
{
int x = 0;
x = banner_ssl.selftest();
if (x) {
fprintf(stderr, "SSL banner: selftest failed\n");
return 1;
}
x = banner_ssl_12.selftest();
if (x) {
fprintf(stderr, "SSL banner: selftest failed\n");
return 1;
}
x = banner_smb1.selftest();
if (x) {
fprintf(stderr, "SMB banner: selftest failed\n");
return 1;
}
x = banner_http.selftest();
if (x) {
fprintf(stderr, "HTTP banner: selftest failed\n");
return 1;
}
x = banner_telnet.selftest();
if (x) {
fprintf(stderr, "Telnet banner: selftest failed\n");
return 1;
}
x = banner_rdp.selftest();
if (x) {
fprintf(stderr, "RDP banner: selftest failed\n");
return 1;
}
if (x)
goto failure;
else
goto success;
}
success:
LOG(1, "[+] banners: success\n");
return 0;
failure:
LOG(1, "[-] banners: failure\n");
return 1;
}