692 lines
20 KiB
C
692 lines
20 KiB
C
|
/*
|
||
|
Read in the binary file produced by "out-binary.c". This allows you to
|
||
|
translate the "binary" format into any of the other output formats.
|
||
|
*/
|
||
|
#include "massip-addr.h"
|
||
|
#include "in-binary.h"
|
||
|
#include "masscan.h"
|
||
|
#include "masscan-app.h"
|
||
|
#include "masscan-status.h"
|
||
|
#include "main-globals.h"
|
||
|
#include "output.h"
|
||
|
#include "util-safefunc.h"
|
||
|
#include "in-filter.h"
|
||
|
#include "in-report.h"
|
||
|
#include "util-malloc.h"
|
||
|
#include "util-logger.h"
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning(disable:4996)
|
||
|
#endif
|
||
|
|
||
|
static const size_t BUF_MAX = 1024*1024;
|
||
|
|
||
|
struct MasscanRecord {
|
||
|
unsigned timestamp;
|
||
|
ipaddress ip;
|
||
|
unsigned char ip_proto;
|
||
|
unsigned short port;
|
||
|
unsigned char reason;
|
||
|
unsigned char ttl;
|
||
|
unsigned char mac[6];
|
||
|
enum ApplicationProtocol app_proto;
|
||
|
};
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
***************************************************************************/
|
||
|
static void
|
||
|
parse_status(struct Output *out,
|
||
|
enum PortStatus status, /* open/closed */
|
||
|
const unsigned char *buf, size_t buf_length)
|
||
|
{
|
||
|
struct MasscanRecord record;
|
||
|
|
||
|
if (buf_length < 12)
|
||
|
return;
|
||
|
|
||
|
/* parse record */
|
||
|
record.timestamp = buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3];
|
||
|
record.ip.ipv4 = buf[4]<<24 | buf[5]<<16 | buf[6]<<8 | buf[7];
|
||
|
record.ip.version = 4;
|
||
|
record.port = buf[8]<<8 | buf[9];
|
||
|
record.reason = buf[10];
|
||
|
record.ttl = buf[11];
|
||
|
|
||
|
/* if ARP, then there will be a MAC address */
|
||
|
if (record.ip.ipv4 == 0 && buf_length >= 12+6)
|
||
|
memcpy(record.mac, buf+12, 6);
|
||
|
else
|
||
|
memset(record.mac, 0, 6);
|
||
|
|
||
|
if (out->when_scan_started == 0)
|
||
|
out->when_scan_started = record.timestamp;
|
||
|
|
||
|
switch (record.port) {
|
||
|
case 53:
|
||
|
case 123:
|
||
|
case 137:
|
||
|
case 161:
|
||
|
record.ip_proto = 17;
|
||
|
break;
|
||
|
case 36422:
|
||
|
case 36412:
|
||
|
case 2905:
|
||
|
record.ip_proto = 132;
|
||
|
break;
|
||
|
default:
|
||
|
record.ip_proto = 6;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Now report the result
|
||
|
*/
|
||
|
output_report_status(out,
|
||
|
record.timestamp,
|
||
|
status,
|
||
|
record.ip,
|
||
|
record.ip_proto,
|
||
|
record.port,
|
||
|
record.reason,
|
||
|
record.ttl,
|
||
|
record.mac);
|
||
|
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
***************************************************************************/
|
||
|
static void
|
||
|
parse_status2(struct Output *out,
|
||
|
enum PortStatus status, /* open/closed */
|
||
|
const unsigned char *buf, size_t buf_length,
|
||
|
struct MassIP *filter)
|
||
|
{
|
||
|
struct MasscanRecord record;
|
||
|
|
||
|
if (buf_length < 13)
|
||
|
return;
|
||
|
|
||
|
/* parse record */
|
||
|
record.timestamp = buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3];
|
||
|
record.ip.ipv4 = buf[4]<<24 | buf[5]<<16 | buf[6]<<8 | buf[7];
|
||
|
record.ip.version = 4;
|
||
|
record.ip_proto = buf[8];
|
||
|
record.port = buf[9]<<8 | buf[10];
|
||
|
record.reason = buf[11];
|
||
|
record.ttl = buf[12];
|
||
|
|
||
|
/* if ARP, then there will be a MAC address */
|
||
|
if (record.ip.ipv4 == 0 && buf_length >= 13+6)
|
||
|
memcpy(record.mac, buf+13, 6);
|
||
|
else
|
||
|
memset(record.mac, 0, 6);
|
||
|
|
||
|
if (out->when_scan_started == 0)
|
||
|
out->when_scan_started = record.timestamp;
|
||
|
|
||
|
/* Filter for known IP/ports, if specified on command-line */
|
||
|
if (filter && filter->count_ipv4s) {
|
||
|
if (!massip_has_ip(filter, record.ip))
|
||
|
return;
|
||
|
}
|
||
|
if (filter && filter->count_ports) {
|
||
|
if (!massip_has_port(filter, record.port))
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Now report the result
|
||
|
*/
|
||
|
output_report_status(out,
|
||
|
record.timestamp,
|
||
|
status,
|
||
|
record.ip,
|
||
|
record.ip_proto,
|
||
|
record.port,
|
||
|
record.reason,
|
||
|
record.ttl,
|
||
|
record.mac);
|
||
|
|
||
|
}
|
||
|
|
||
|
static unsigned char
|
||
|
_get_byte(const unsigned char *buf, size_t length, size_t *offset)
|
||
|
{
|
||
|
unsigned char result;
|
||
|
if (*offset < length) {
|
||
|
result = buf[*offset];
|
||
|
} else {
|
||
|
result = 0xFF;
|
||
|
}
|
||
|
(*offset)++;
|
||
|
return result;
|
||
|
}
|
||
|
static unsigned
|
||
|
_get_integer(const unsigned char *buf, size_t length, size_t *r_offset)
|
||
|
{
|
||
|
unsigned result;
|
||
|
size_t offset = *r_offset;
|
||
|
(*r_offset) += 4;
|
||
|
|
||
|
if (offset + 4 <= length) {
|
||
|
result = buf[offset+0]<<24
|
||
|
| buf[offset+1]<<16
|
||
|
| buf[offset+2]<<8
|
||
|
| buf[offset+3]<<0;
|
||
|
} else {
|
||
|
result = 0xFFFFFFFF;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
static unsigned short
|
||
|
_get_short(const unsigned char *buf, size_t length, size_t *r_offset)
|
||
|
{
|
||
|
unsigned short result;
|
||
|
size_t offset = *r_offset;
|
||
|
(*r_offset) += 2;
|
||
|
|
||
|
if (offset + 2 <= length) {
|
||
|
result = buf[offset+0]<<8
|
||
|
| buf[offset+1]<<0;
|
||
|
} else {
|
||
|
result = 0xFFFF;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static unsigned long long
|
||
|
_get_long(const unsigned char *buf, size_t length, size_t *r_offset)
|
||
|
{
|
||
|
unsigned long long result;
|
||
|
size_t offset = *r_offset;
|
||
|
(*r_offset) += 8;
|
||
|
|
||
|
if (offset + 8 <= length) {
|
||
|
result =
|
||
|
(unsigned long long)buf[offset+0]<<56ULL
|
||
|
| (unsigned long long)buf[offset+1]<<48ULL
|
||
|
| (unsigned long long)buf[offset+2]<<40ULL
|
||
|
| (unsigned long long)buf[offset+3]<<32ULL
|
||
|
| (unsigned long long)buf[offset+4]<<24ULL
|
||
|
| (unsigned long long)buf[offset+5]<<16ULL
|
||
|
| (unsigned long long)buf[offset+6]<<8ULL
|
||
|
| (unsigned long long)buf[offset+7]<<0ULL;
|
||
|
|
||
|
} else {
|
||
|
result = 0xFFFFFFFFffffffffULL;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
***************************************************************************/
|
||
|
static void
|
||
|
parse_status6(struct Output *out,
|
||
|
enum PortStatus status, /* open/closed */
|
||
|
const unsigned char *buf, size_t length,
|
||
|
struct MassIP *filter)
|
||
|
{
|
||
|
struct MasscanRecord record;
|
||
|
size_t offset = 0;
|
||
|
|
||
|
/* parse record */
|
||
|
record.timestamp = _get_integer(buf, length, &offset);
|
||
|
record.ip_proto = _get_byte(buf, length, &offset);
|
||
|
record.port = _get_short(buf, length, &offset);
|
||
|
record.reason = _get_byte(buf, length, &offset);
|
||
|
record.ttl = _get_byte(buf, length, &offset);
|
||
|
record.ip.version= _get_byte(buf, length, &offset);
|
||
|
if (record.ip.version != 6) {
|
||
|
fprintf(stderr, "[-] corrupt record\n");
|
||
|
return;
|
||
|
}
|
||
|
record.ip.ipv6.hi = _get_long(buf, length, &offset);
|
||
|
record.ip.ipv6.lo = _get_long(buf, length, &offset);
|
||
|
|
||
|
if (out->when_scan_started == 0)
|
||
|
out->when_scan_started = record.timestamp;
|
||
|
|
||
|
/* Filter for known IP/ports, if specified on command-line */
|
||
|
if (filter && filter->count_ipv4s) {
|
||
|
if (!massip_has_ip(filter, record.ip))
|
||
|
return;
|
||
|
}
|
||
|
if (filter && filter->count_ports) {
|
||
|
if (!massip_has_port(filter, record.port))
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Now report the result
|
||
|
*/
|
||
|
output_report_status(out,
|
||
|
record.timestamp,
|
||
|
status,
|
||
|
record.ip,
|
||
|
record.ip_proto,
|
||
|
record.port,
|
||
|
record.reason,
|
||
|
record.ttl,
|
||
|
record.mac);
|
||
|
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
***************************************************************************/
|
||
|
static void
|
||
|
parse_banner6(struct Output *out, unsigned char *buf, size_t length,
|
||
|
const struct MassIP *filter,
|
||
|
const struct RangeList *btypes)
|
||
|
{
|
||
|
struct MasscanRecord record;
|
||
|
size_t offset = 0;
|
||
|
|
||
|
/*
|
||
|
* Parse the parts that are common to most records
|
||
|
*/
|
||
|
record.timestamp = _get_integer(buf, length, &offset);
|
||
|
record.ip_proto = _get_byte(buf, length, &offset);
|
||
|
record.port = _get_short(buf, length, &offset);
|
||
|
record.app_proto = _get_short(buf, length, &offset);
|
||
|
record.ttl = _get_byte(buf, length, &offset);
|
||
|
record.ip.version= _get_byte(buf, length, &offset);
|
||
|
if (record.ip.version != 6) {
|
||
|
fprintf(stderr, "[-] corrupt record\n");
|
||
|
return;
|
||
|
}
|
||
|
record.ip.ipv6.hi = _get_long(buf, length, &offset);
|
||
|
record.ip.ipv6.lo = _get_long(buf, length, &offset);
|
||
|
|
||
|
if (out->when_scan_started == 0)
|
||
|
out->when_scan_started = record.timestamp;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Filter out records if requested
|
||
|
*/
|
||
|
if (!readscan_filter_pass(record.ip, record.port, record.app_proto,
|
||
|
filter, btypes))
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* Now print the output
|
||
|
*/
|
||
|
if (offset > length)
|
||
|
return;
|
||
|
output_report_banner(
|
||
|
out,
|
||
|
record.timestamp,
|
||
|
record.ip,
|
||
|
record.ip_proto, /* TCP=6, UDP=17 */
|
||
|
record.port,
|
||
|
record.app_proto, /* HTTP, SSL, SNMP, etc. */
|
||
|
record.ttl, /* ttl */
|
||
|
buf+offset, (unsigned)(length-offset)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
* [OBSOLETE]
|
||
|
* This parses an old version of the banner record. I've still got files
|
||
|
* hanging around with this version, so I'm keeping it in the code for
|
||
|
* now, but eventually I'll get rid of it.
|
||
|
***************************************************************************/
|
||
|
static void
|
||
|
parse_banner3(struct Output *out, unsigned char *buf, size_t buf_length)
|
||
|
{
|
||
|
struct MasscanRecord record;
|
||
|
|
||
|
/*
|
||
|
* Parse the parts that are common to most records
|
||
|
*/
|
||
|
record.timestamp = buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3];
|
||
|
record.ip.ipv4 = buf[4]<<24 | buf[5]<<16 | buf[6]<<8 | buf[7];
|
||
|
record.ip.version = 4;
|
||
|
record.port = buf[8]<<8 | buf[9];
|
||
|
record.app_proto = buf[10]<<8 | buf[11];
|
||
|
|
||
|
if (out->when_scan_started == 0)
|
||
|
out->when_scan_started = record.timestamp;
|
||
|
|
||
|
/*
|
||
|
* Now print the output
|
||
|
*/
|
||
|
output_report_banner(
|
||
|
out,
|
||
|
record.timestamp,
|
||
|
record.ip,
|
||
|
6, /* this is always TCP */
|
||
|
record.port,
|
||
|
record.app_proto,
|
||
|
0, /* ttl */
|
||
|
buf+12, (unsigned)buf_length-12
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
* Parse the BANNER record, extracting the timestamp, IP address, and port
|
||
|
* number. We also convert the banner string into a safer form.
|
||
|
***************************************************************************/
|
||
|
static void
|
||
|
parse_banner4(struct Output *out, unsigned char *buf, size_t buf_length)
|
||
|
{
|
||
|
struct MasscanRecord record;
|
||
|
|
||
|
if (buf_length < 13)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* Parse the parts that are common to most records
|
||
|
*/
|
||
|
record.timestamp = buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3];
|
||
|
record.ip.ipv4 = buf[4]<<24 | buf[5]<<16 | buf[6]<<8 | buf[7];
|
||
|
record.ip.version = 4;
|
||
|
record.ip_proto = buf[8];
|
||
|
record.port = buf[9]<<8 | buf[10];
|
||
|
record.app_proto = buf[11]<<8 | buf[12];
|
||
|
|
||
|
if (out->when_scan_started == 0)
|
||
|
out->when_scan_started = record.timestamp;
|
||
|
|
||
|
/*
|
||
|
* Now print the output
|
||
|
*/
|
||
|
output_report_banner(
|
||
|
out,
|
||
|
record.timestamp,
|
||
|
record.ip,
|
||
|
record.ip_proto, /* TCP=6, UDP=17 */
|
||
|
record.port,
|
||
|
record.app_proto, /* HTTP, SSL, SNMP, etc. */
|
||
|
0, /* ttl */
|
||
|
buf+13, (unsigned)buf_length-13
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
***************************************************************************/
|
||
|
static void
|
||
|
parse_banner9(struct Output *out, unsigned char *buf, size_t buf_length,
|
||
|
const struct MassIP *filter,
|
||
|
const struct RangeList *btypes)
|
||
|
{
|
||
|
struct MasscanRecord record;
|
||
|
unsigned char *data = buf+14;
|
||
|
size_t data_length = buf_length-14;
|
||
|
|
||
|
if (buf_length < 14)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* Parse the parts that are common to most records
|
||
|
*/
|
||
|
record.timestamp = buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3];
|
||
|
record.ip.ipv4 = buf[4]<<24 | buf[5]<<16 | buf[6]<<8 | buf[7];
|
||
|
record.ip.version = 4;
|
||
|
record.ip_proto = buf[8];
|
||
|
record.port = buf[9]<<8 | buf[10];
|
||
|
record.app_proto = buf[11]<<8 | buf[12];
|
||
|
record.ttl = buf[13];
|
||
|
|
||
|
if (out->when_scan_started == 0)
|
||
|
out->when_scan_started = record.timestamp;
|
||
|
|
||
|
/*
|
||
|
* KLUDGE: when doing SSL stuff, add a IP:name pair to a database
|
||
|
* so we can annotate [VULN] strings with this information
|
||
|
*/
|
||
|
//readscan_report(record.ip, record.app_proto, &data, &data_length);
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Filter out records if requested
|
||
|
*/
|
||
|
if (!readscan_filter_pass(record.ip, record.port, record.app_proto,
|
||
|
filter, btypes))
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* Now print the output
|
||
|
*/
|
||
|
output_report_banner(
|
||
|
out,
|
||
|
record.timestamp,
|
||
|
record.ip,
|
||
|
record.ip_proto, /* TCP=6, UDP=17 */
|
||
|
record.port,
|
||
|
record.app_proto, /* HTTP, SSL, SNMP, etc. */
|
||
|
record.ttl, /* ttl */
|
||
|
data, (unsigned)data_length
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/***************************************************************************
|
||
|
* Read in the file, one record at a time.
|
||
|
***************************************************************************/
|
||
|
static uint64_t
|
||
|
_binaryfile_parse(struct Output *out, const char *filename,
|
||
|
struct MassIP *filter,
|
||
|
const struct RangeList *btypes)
|
||
|
{
|
||
|
FILE *fp = 0;
|
||
|
unsigned char *buf = 0;
|
||
|
size_t bytes_read;
|
||
|
uint64_t total_records = 0;
|
||
|
|
||
|
/* Allocate a buffer of up to one megabyte per record */
|
||
|
buf = MALLOC(BUF_MAX);
|
||
|
|
||
|
/* Open the file */
|
||
|
fp = fopen(filename, "rb");
|
||
|
if (fp == NULL) {
|
||
|
fprintf(stderr, "[-] FAIL: --readscan\n");
|
||
|
fprintf(stderr, "[-] %s: %s\n", filename, strerror(errno));
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
LOG(0, "[+] --readscan %s\n", filename);
|
||
|
|
||
|
if (feof(fp)) {
|
||
|
LOG(0, "[-] %s: file is empty\n", filename);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
/* first record is pseudo-record */
|
||
|
bytes_read = fread(buf, 1, 'a'+2, fp);
|
||
|
if (bytes_read < 'a'+2) {
|
||
|
LOG(0, "[-] %s: %s\n", filename, strerror(errno));
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
/* Make sure it's got the format string */
|
||
|
if (memcmp(buf, "masscan/1.1", 11) != 0) {
|
||
|
LOG(0,
|
||
|
"[-] %s: unknown file format (expected \"masscan/1.1\")\n",
|
||
|
filename);
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Look for start time
|
||
|
*/
|
||
|
if (buf[11] == '.' && strtoul((char*)buf+12,0,0) >= 2) {
|
||
|
unsigned i;
|
||
|
|
||
|
/* move to next field */
|
||
|
for (i=0; i<'a' && buf[i] && buf[i] != '\n'; i++)
|
||
|
;
|
||
|
i++;
|
||
|
|
||
|
if (buf[i] == 's')
|
||
|
i++;
|
||
|
if (buf[i] == ':')
|
||
|
i++;
|
||
|
|
||
|
/* extract timestamp */
|
||
|
if (i < 'a')
|
||
|
out->when_scan_started = strtoul((char*)buf+i,0,0);
|
||
|
}
|
||
|
|
||
|
/* Now read all records */
|
||
|
for (;;) {
|
||
|
unsigned type;
|
||
|
unsigned length;
|
||
|
|
||
|
|
||
|
/* [TYPE]
|
||
|
* This is one or more bytes indicating the type of type of the
|
||
|
* record
|
||
|
*/
|
||
|
bytes_read = fread(buf, 1, 1, fp);
|
||
|
if (bytes_read != 1)
|
||
|
break;
|
||
|
type = buf[0] & 0x7F;
|
||
|
while (buf[0] & 0x80) {
|
||
|
bytes_read = fread(buf, 1, 1, fp);
|
||
|
if (bytes_read != 1)
|
||
|
break;
|
||
|
type = (type << 7) | (buf[0] & 0x7F);
|
||
|
}
|
||
|
|
||
|
/* [LENGTH]
|
||
|
* Is one byte for lengths smaller than 127 bytes, or two
|
||
|
* bytes for lengths up to 16384.
|
||
|
*/
|
||
|
bytes_read = fread(buf, 1, 1, fp);
|
||
|
if (bytes_read != 1)
|
||
|
break;
|
||
|
length = buf[0] & 0x7F;
|
||
|
while (buf[0] & 0x80) {
|
||
|
bytes_read = fread(buf, 1, 1, fp);
|
||
|
if (bytes_read != 1)
|
||
|
break;
|
||
|
length = (length << 7) | (buf[0] & 0x7F);
|
||
|
}
|
||
|
if (length > BUF_MAX) {
|
||
|
LOG(0, "[-] file corrupt\n");
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* get the remainder of the record */
|
||
|
bytes_read = fread(buf, 1, length, fp);
|
||
|
if (bytes_read < length)
|
||
|
break; /* eof */
|
||
|
|
||
|
/* Depending on record type, do something different */
|
||
|
switch (type) {
|
||
|
case 1: /* STATUS: open */
|
||
|
if (!btypes->count)
|
||
|
parse_status(out, PortStatus_Open, buf, bytes_read);
|
||
|
break;
|
||
|
case 2: /* STATUS: closed */
|
||
|
if (!btypes->count)
|
||
|
parse_status(out, PortStatus_Closed, buf, bytes_read);
|
||
|
break;
|
||
|
case 3: /* BANNER */
|
||
|
parse_banner3(out, buf, bytes_read);
|
||
|
break;
|
||
|
case 4:
|
||
|
if (fread(buf+bytes_read,1,1,fp) != 1) {
|
||
|
LOG(0, "[-] read() error\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
bytes_read++;
|
||
|
parse_banner4(out, buf, bytes_read);
|
||
|
break;
|
||
|
case 5:
|
||
|
parse_banner4(out, buf, bytes_read);
|
||
|
break;
|
||
|
case 6: /* STATUS: open */
|
||
|
if (!btypes->count)
|
||
|
parse_status2(out, PortStatus_Open, buf, bytes_read, filter);
|
||
|
break;
|
||
|
case 7: /* STATUS: closed */
|
||
|
if (!btypes->count)
|
||
|
parse_status2(out, PortStatus_Closed, buf, bytes_read, filter);
|
||
|
break;
|
||
|
case 9:
|
||
|
parse_banner9(out, buf, bytes_read, filter, btypes);
|
||
|
break;
|
||
|
case 10: /* Open6 */
|
||
|
if (!btypes->count)
|
||
|
parse_status6(out, PortStatus_Open, buf, bytes_read, filter);
|
||
|
break;
|
||
|
case 11: /* Closed6 */
|
||
|
if (!btypes->count)
|
||
|
parse_status6(out, PortStatus_Closed, buf, bytes_read, filter);
|
||
|
break;
|
||
|
case 13: /* Banner6 */
|
||
|
parse_banner6(out, buf, bytes_read, filter, btypes);
|
||
|
break;
|
||
|
case 'm': /* FILEHEADER */
|
||
|
//goto end;
|
||
|
break;
|
||
|
default:
|
||
|
LOG(0, "[-] file corrupt: unknown type %u\n", type);
|
||
|
goto end;
|
||
|
}
|
||
|
total_records++;
|
||
|
if ((total_records & 0xFFFF) == 0)
|
||
|
LOG(0, "[+] %s: %8" PRIu64 "\r", filename, total_records);
|
||
|
}
|
||
|
|
||
|
end:
|
||
|
if (buf)
|
||
|
free(buf);
|
||
|
if (fp)
|
||
|
fclose(fp);
|
||
|
return total_records;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
* When masscan is called with the "--readscan" parameter, it doesn't
|
||
|
* do a scan of the live network, but instead reads scan results from
|
||
|
* a file. Those scan results can then be written out in any of the
|
||
|
* other formats. This preserves the original timestamps.
|
||
|
*****************************************************************************/
|
||
|
void
|
||
|
readscan_binary_scanfile(struct Masscan *masscan,
|
||
|
int arg_first, int arg_max, char *argv[])
|
||
|
{
|
||
|
struct Output *out;
|
||
|
int i;
|
||
|
|
||
|
/*
|
||
|
* Create the output system, such as XML or JSON output
|
||
|
*/
|
||
|
out = output_create(masscan, 0);
|
||
|
|
||
|
/*
|
||
|
* Set the start time to zero. We'll read it from the first file
|
||
|
* that we parse
|
||
|
*/
|
||
|
out->when_scan_started = 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++) {
|
||
|
_binaryfile_parse(out, argv[i], &masscan->targets, &masscan->banner_types);
|
||
|
}
|
||
|
|
||
|
/* Done! */
|
||
|
output_destroy(out);
|
||
|
}
|
||
|
|
||
|
|