Loading src/proto-banner1.h +1 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ enum { PROTO_FTP2, PROTO_DNS_VERSIONBIND, PROTO_SNMP, PROTO_NBTSTAT, }; struct Banner1 Loading src/proto-dns-parse.h 0 → 100644 +51 −0 Original line number Diff line number Diff line #ifndef PROTO_DNS_PARSE_H #define PROTO_DNS_PARSE_H struct DomainPointer { const unsigned char *name; unsigned length; }; struct DNS_Incoming { unsigned id; /* transaction id */ unsigned is_valid:1; unsigned is_formerr:1; unsigned is_edns0:1;/* edns0 features found */ unsigned qr:1; /* 'query' or 'response' */ unsigned aa:1; /* 'authoritative answer' */ unsigned tc:1; /* 'truncation' */ unsigned rd:1; /* 'recursion desired' */ unsigned ra:1; /* 'recursion available' */ unsigned z:3; /* reserved */ unsigned opcode; unsigned rcode; /* response error code */ unsigned qdcount; /* query count */ unsigned ancount; /* answer count */ unsigned nscount; /* name-server/authority count */ unsigned arcount; /* additional record count */ struct { unsigned payload_size; unsigned version; unsigned z; } edns0; const unsigned char *req; unsigned req_length; /* the query name */ struct DomainPointer query_name; unsigned query_type; unsigned char query_name_buffer[256]; unsigned rr_count; unsigned short rr_offset[1024]; unsigned edns0_offset; }; void proto_dns_parse(struct DNS_Incoming *dns, const unsigned char px[], unsigned offset, unsigned max); unsigned dns_name_skip(const unsigned char px[], unsigned offset, unsigned max); #endif src/proto-dns.c +2 −44 Original line number Diff line number Diff line #include "proto-udp.h" #include "proto-dns.h" #include "proto-dns-parse.h" #include "proto-preprocess.h" #include "syn-cookie.h" #include "logger.h" Loading @@ -10,47 +11,6 @@ struct DomainPointer { const unsigned char *name; unsigned length; }; struct DNS_Incoming { unsigned id; /* transaction id */ unsigned is_valid:1; unsigned is_formerr:1; unsigned is_edns0:1;/* edns0 features found */ unsigned qr:1; /* 'query' or 'response' */ unsigned aa:1; /* 'authoritative answer' */ unsigned tc:1; /* 'truncation' */ unsigned rd:1; /* 'recursion desired' */ unsigned ra:1; /* 'recursion available' */ unsigned z:3; /* reserved */ unsigned opcode; unsigned rcode; /* response error code */ unsigned qdcount; /* query count */ unsigned ancount; /* answer count */ unsigned nscount; /* name-server/authority count */ unsigned arcount; /* additional record count */ struct { unsigned payload_size; unsigned version; unsigned z; } edns0; const unsigned char *req; unsigned req_length; /* the query name */ struct DomainPointer query_name; unsigned query_type; unsigned char query_name_buffer[256]; unsigned rr_count; unsigned short rr_offset[1024]; unsigned edns0_offset; }; #define VERIFY_REMAINING(n) if (offset+(n) > length) return; Loading Loading @@ -98,7 +58,7 @@ dns_name_skip_validate(const unsigned char *px, unsigned offset, unsigned length /**************************************************************************** ****************************************************************************/ static unsigned unsigned dns_name_skip(const unsigned char px[], unsigned offset, unsigned max) { unsigned name_length = 0; Loading Loading @@ -237,8 +197,6 @@ proto_dns_parse(struct DNS_Incoming *dns, const unsigned char px[], unsigned off | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ if (dns->qdcount == 0) return; for (i=0; i<dns->qdcount; i++) { unsigned xclass; unsigned xtype; Loading src/proto-netbios.c 0 → 100644 +149 −0 Original line number Diff line number Diff line #include "proto-udp.h" #include "proto-dns-parse.h" #include "proto-preprocess.h" #include "syn-cookie.h" #include "logger.h" #include "output.h" #include "proto-banner1.h" #include "masscan.h" #include "unusedparm.h" #include <ctype.h> static void append_char(unsigned char *banner, size_t banner_max, unsigned *banner_length, char c) { if (*banner_length < banner_max) banner[(*banner_length)++] = c; } static void append_name(unsigned char *banner, size_t banner_max, unsigned *banner_length, const unsigned char *name) { unsigned i; unsigned char c; for (i=0; i<15; i++) { c = name[i]; if (c == 0x20 || c == '\0') append_char(banner, banner_max, banner_length, ' '); else if (isalnum(c) || ispunct(c)) append_char(banner, banner_max, banner_length, c); else { append_char(banner, banner_max, banner_length, '<'); append_char(banner, banner_max, banner_length, "0123456789ABCDEF"[c>>4]); append_char(banner, banner_max, banner_length, "0123456789ABCDEF"[c&0xF]); append_char(banner, banner_max, banner_length, '>'); } } c = name[i]; append_char(banner, banner_max, banner_length, '<'); append_char(banner, banner_max, banner_length, "0123456789ABCDEF"[c>>4]); append_char(banner, banner_max, banner_length, "0123456789ABCDEF"[c&0xF]); append_char(banner, banner_max, banner_length, '>'); append_char(banner, banner_max, banner_length, '\n'); } unsigned handle_nbtstat_rr(struct Output *out, const unsigned char *px, unsigned length, unsigned ip_them, unsigned port_them) { unsigned char banner[65536]; unsigned banner_length = 0; unsigned offset = 0; unsigned name_count; if (offset >= length) return 0; name_count = px[offset++]; while (offset + 18 <= length && name_count) { append_name(banner, sizeof(banner), &banner_length, &px[offset]); offset += 18; name_count--; } { unsigned i; for (i=0; i<6; i++) { if (offset + i < length) { unsigned char c = px[offset]; append_char(banner, sizeof(banner), &banner_length, "0123456789ABCDEF"[c>>4]); append_char(banner, sizeof(banner), &banner_length, "0123456789ABCDEF"[c&0xF]); if (i < 5) append_char(banner, sizeof(banner), &banner_length, '-'); } } } output_report_banner( out, ip_them, port_them, PROTO_NBTSTAT, banner, banner_length); return 0; } unsigned handle_nbtstat(struct Output *out, const unsigned char *px, unsigned length, struct PreprocessedInfo *parsed) { unsigned ip_them; unsigned port_them = parsed->port_src; struct DNS_Incoming dns[1]; unsigned offset; unsigned seqno; ip_them = parsed->ip_src[0]<<24 | parsed->ip_src[1]<<16 | parsed->ip_src[2]<< 8 | parsed->ip_src[3]<<0; seqno = syn_hash(ip_them, port_them | 0x10000); proto_dns_parse(dns, px, parsed->app_offset, parsed->app_offset + parsed->app_length); if ((seqno & 0xFFFF) != dns->id) return 1; if (dns->qr != 1) return 0; if (dns->rcode != 0) return 0; if (dns->qdcount > 1) return 0; if (dns->ancount < 1) return 0; if (dns->rr_count < 1) return 0; offset = dns->rr_offset[dns->qdcount]; offset = dns_name_skip(px, offset, length); if (offset + 10 >= length) return 0; { unsigned type = px[offset+0]<<8 | px[offset+1]; unsigned xclass = px[offset+2]<<8 | px[offset+3]; unsigned rrlen = px[offset+8]<<8 | px[offset+9]; unsigned txtlen = px[offset+10]; if (rrlen == 0 || txtlen > rrlen-1) return 0; if (type != 0x21 || xclass != 1) return 0; offset += 10; return handle_nbtstat_rr(out, px + offset, length - offset, ip_them, port_them); } } src/proto-netbios.h 0 → 100644 +9 −0 Original line number Diff line number Diff line #ifndef PROTO_NETBIOS_H #define PROTO_NETBIOS_H struct PreprocessedInfo; struct Output; unsigned handle_nbtstat(struct Output *out, const unsigned char *px, unsigned length, struct PreprocessedInfo *parsed); #endif Loading
src/proto-banner1.h +1 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ enum { PROTO_FTP2, PROTO_DNS_VERSIONBIND, PROTO_SNMP, PROTO_NBTSTAT, }; struct Banner1 Loading
src/proto-dns-parse.h 0 → 100644 +51 −0 Original line number Diff line number Diff line #ifndef PROTO_DNS_PARSE_H #define PROTO_DNS_PARSE_H struct DomainPointer { const unsigned char *name; unsigned length; }; struct DNS_Incoming { unsigned id; /* transaction id */ unsigned is_valid:1; unsigned is_formerr:1; unsigned is_edns0:1;/* edns0 features found */ unsigned qr:1; /* 'query' or 'response' */ unsigned aa:1; /* 'authoritative answer' */ unsigned tc:1; /* 'truncation' */ unsigned rd:1; /* 'recursion desired' */ unsigned ra:1; /* 'recursion available' */ unsigned z:3; /* reserved */ unsigned opcode; unsigned rcode; /* response error code */ unsigned qdcount; /* query count */ unsigned ancount; /* answer count */ unsigned nscount; /* name-server/authority count */ unsigned arcount; /* additional record count */ struct { unsigned payload_size; unsigned version; unsigned z; } edns0; const unsigned char *req; unsigned req_length; /* the query name */ struct DomainPointer query_name; unsigned query_type; unsigned char query_name_buffer[256]; unsigned rr_count; unsigned short rr_offset[1024]; unsigned edns0_offset; }; void proto_dns_parse(struct DNS_Incoming *dns, const unsigned char px[], unsigned offset, unsigned max); unsigned dns_name_skip(const unsigned char px[], unsigned offset, unsigned max); #endif
src/proto-dns.c +2 −44 Original line number Diff line number Diff line #include "proto-udp.h" #include "proto-dns.h" #include "proto-dns-parse.h" #include "proto-preprocess.h" #include "syn-cookie.h" #include "logger.h" Loading @@ -10,47 +11,6 @@ struct DomainPointer { const unsigned char *name; unsigned length; }; struct DNS_Incoming { unsigned id; /* transaction id */ unsigned is_valid:1; unsigned is_formerr:1; unsigned is_edns0:1;/* edns0 features found */ unsigned qr:1; /* 'query' or 'response' */ unsigned aa:1; /* 'authoritative answer' */ unsigned tc:1; /* 'truncation' */ unsigned rd:1; /* 'recursion desired' */ unsigned ra:1; /* 'recursion available' */ unsigned z:3; /* reserved */ unsigned opcode; unsigned rcode; /* response error code */ unsigned qdcount; /* query count */ unsigned ancount; /* answer count */ unsigned nscount; /* name-server/authority count */ unsigned arcount; /* additional record count */ struct { unsigned payload_size; unsigned version; unsigned z; } edns0; const unsigned char *req; unsigned req_length; /* the query name */ struct DomainPointer query_name; unsigned query_type; unsigned char query_name_buffer[256]; unsigned rr_count; unsigned short rr_offset[1024]; unsigned edns0_offset; }; #define VERIFY_REMAINING(n) if (offset+(n) > length) return; Loading Loading @@ -98,7 +58,7 @@ dns_name_skip_validate(const unsigned char *px, unsigned offset, unsigned length /**************************************************************************** ****************************************************************************/ static unsigned unsigned dns_name_skip(const unsigned char px[], unsigned offset, unsigned max) { unsigned name_length = 0; Loading Loading @@ -237,8 +197,6 @@ proto_dns_parse(struct DNS_Incoming *dns, const unsigned char px[], unsigned off | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ if (dns->qdcount == 0) return; for (i=0; i<dns->qdcount; i++) { unsigned xclass; unsigned xtype; Loading
src/proto-netbios.c 0 → 100644 +149 −0 Original line number Diff line number Diff line #include "proto-udp.h" #include "proto-dns-parse.h" #include "proto-preprocess.h" #include "syn-cookie.h" #include "logger.h" #include "output.h" #include "proto-banner1.h" #include "masscan.h" #include "unusedparm.h" #include <ctype.h> static void append_char(unsigned char *banner, size_t banner_max, unsigned *banner_length, char c) { if (*banner_length < banner_max) banner[(*banner_length)++] = c; } static void append_name(unsigned char *banner, size_t banner_max, unsigned *banner_length, const unsigned char *name) { unsigned i; unsigned char c; for (i=0; i<15; i++) { c = name[i]; if (c == 0x20 || c == '\0') append_char(banner, banner_max, banner_length, ' '); else if (isalnum(c) || ispunct(c)) append_char(banner, banner_max, banner_length, c); else { append_char(banner, banner_max, banner_length, '<'); append_char(banner, banner_max, banner_length, "0123456789ABCDEF"[c>>4]); append_char(banner, banner_max, banner_length, "0123456789ABCDEF"[c&0xF]); append_char(banner, banner_max, banner_length, '>'); } } c = name[i]; append_char(banner, banner_max, banner_length, '<'); append_char(banner, banner_max, banner_length, "0123456789ABCDEF"[c>>4]); append_char(banner, banner_max, banner_length, "0123456789ABCDEF"[c&0xF]); append_char(banner, banner_max, banner_length, '>'); append_char(banner, banner_max, banner_length, '\n'); } unsigned handle_nbtstat_rr(struct Output *out, const unsigned char *px, unsigned length, unsigned ip_them, unsigned port_them) { unsigned char banner[65536]; unsigned banner_length = 0; unsigned offset = 0; unsigned name_count; if (offset >= length) return 0; name_count = px[offset++]; while (offset + 18 <= length && name_count) { append_name(banner, sizeof(banner), &banner_length, &px[offset]); offset += 18; name_count--; } { unsigned i; for (i=0; i<6; i++) { if (offset + i < length) { unsigned char c = px[offset]; append_char(banner, sizeof(banner), &banner_length, "0123456789ABCDEF"[c>>4]); append_char(banner, sizeof(banner), &banner_length, "0123456789ABCDEF"[c&0xF]); if (i < 5) append_char(banner, sizeof(banner), &banner_length, '-'); } } } output_report_banner( out, ip_them, port_them, PROTO_NBTSTAT, banner, banner_length); return 0; } unsigned handle_nbtstat(struct Output *out, const unsigned char *px, unsigned length, struct PreprocessedInfo *parsed) { unsigned ip_them; unsigned port_them = parsed->port_src; struct DNS_Incoming dns[1]; unsigned offset; unsigned seqno; ip_them = parsed->ip_src[0]<<24 | parsed->ip_src[1]<<16 | parsed->ip_src[2]<< 8 | parsed->ip_src[3]<<0; seqno = syn_hash(ip_them, port_them | 0x10000); proto_dns_parse(dns, px, parsed->app_offset, parsed->app_offset + parsed->app_length); if ((seqno & 0xFFFF) != dns->id) return 1; if (dns->qr != 1) return 0; if (dns->rcode != 0) return 0; if (dns->qdcount > 1) return 0; if (dns->ancount < 1) return 0; if (dns->rr_count < 1) return 0; offset = dns->rr_offset[dns->qdcount]; offset = dns_name_skip(px, offset, length); if (offset + 10 >= length) return 0; { unsigned type = px[offset+0]<<8 | px[offset+1]; unsigned xclass = px[offset+2]<<8 | px[offset+3]; unsigned rrlen = px[offset+8]<<8 | px[offset+9]; unsigned txtlen = px[offset+10]; if (rrlen == 0 || txtlen > rrlen-1) return 0; if (type != 0x21 || xclass != 1) return 0; offset += 10; return handle_nbtstat_rr(out, px + offset, length - offset, ip_them, port_them); } }
src/proto-netbios.h 0 → 100644 +9 −0 Original line number Diff line number Diff line #ifndef PROTO_NETBIOS_H #define PROTO_NETBIOS_H struct PreprocessedInfo; struct Output; unsigned handle_nbtstat(struct Output *out, const unsigned char *px, unsigned length, struct PreprocessedInfo *parsed); #endif