555 lines
16 KiB
C
555 lines
16 KiB
C
|
#ifndef MASSCAN_H
|
||
|
#define MASSCAN_H
|
||
|
#include "massip-addr.h"
|
||
|
#include "util-safefunc.h"
|
||
|
#include "stack-src.h"
|
||
|
#include "massip.h"
|
||
|
#include "util-bool.h"
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdint.h>
|
||
|
#include <time.h>
|
||
|
|
||
|
#include "massip.h"
|
||
|
#include "stack-queue.h"
|
||
|
|
||
|
struct Adapter;
|
||
|
struct TemplateSet;
|
||
|
struct Banner1;
|
||
|
struct TemplateOptions;
|
||
|
|
||
|
/**
|
||
|
* This is the "operation" to be performed by masscan, which is almost always
|
||
|
* to "scan" the network. However, there are some lesser operations to do
|
||
|
* instead, like run a "regression self test", or "debug", or something else
|
||
|
* instead of scanning. We parse the command-line in order to figure out the
|
||
|
* proper operation
|
||
|
*/
|
||
|
enum Operation {
|
||
|
Operation_Default = 0, /* nothing specified, so print usage */
|
||
|
Operation_List_Adapters = 1, /* --listif */
|
||
|
Operation_Selftest = 2, /* --selftest or --regress */
|
||
|
Operation_Scan = 3, /* this is what you expect */
|
||
|
Operation_DebugIF = 4, /* --debug if */
|
||
|
Operation_ListScan = 5, /* -sL */
|
||
|
Operation_ReadScan = 6, /* --readscan <binary-output> */
|
||
|
Operation_ReadRange = 7, /* --readrange */
|
||
|
Operation_Benchmark = 8, /* --benchmark */
|
||
|
Operation_Echo = 9, /* --echo */
|
||
|
Operation_EchoAll = 10, /* --echo-all */
|
||
|
Operation_EchoCidr = 11, /* --echo-cidr */
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The format of the output. If nothing is specified, then the default will
|
||
|
* be "--interactive", meaning that we'll print to the command-line live as
|
||
|
* results come in. Only one output format can be specified, except that
|
||
|
* "--interactive" can be specified alongside any of the other ones.
|
||
|
*/
|
||
|
enum OutputFormat {
|
||
|
Output_Default = 0x0000,
|
||
|
Output_Interactive = 0x0001, /* --interactive, print to cmdline */
|
||
|
Output_List = 0x0002,
|
||
|
Output_Binary = 0x0004, /* -oB, "binary", the primary format */
|
||
|
Output_XML = 0x0008, /* -oX, "xml" */
|
||
|
Output_JSON = 0x0010, /* -oJ, "json" */
|
||
|
Output_NDJSON = 0x0011, /* -oD, "ndjson" */
|
||
|
Output_Nmap = 0x0020,
|
||
|
Output_ScriptKiddie = 0x0040,
|
||
|
Output_Grepable = 0x0080, /* -oG, "grepable" */
|
||
|
Output_Redis = 0x0100,
|
||
|
Output_Unicornscan = 0x0200, /* -oU, "unicornscan" */
|
||
|
Output_None = 0x0400,
|
||
|
Output_Certs = 0x0800,
|
||
|
Output_Hostonly = 0x1000, /* -oH, "hostonly" */
|
||
|
Output_All = 0xFFBF, /* not supported */
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Holds the list of TCP "hello" payloads, specified with the "--hello-file"
|
||
|
* or "--hello-string" options
|
||
|
*/
|
||
|
struct TcpCfgPayloads
|
||
|
{
|
||
|
/** The "hello" data in base64 format. This is either the base64 string
|
||
|
* specified in the cmdline/cfgfile with "--hello-string", or the
|
||
|
* contents of a file specified with "--hello-file" that we've converted
|
||
|
* into base64 */
|
||
|
char *payload_base64;
|
||
|
|
||
|
/** The TCP port that this hello belongs to */
|
||
|
unsigned port;
|
||
|
|
||
|
/** These configuration options are stored as a linked-list */
|
||
|
struct TcpCfgPayloads *next;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* This is the master MASSCAN configuration structure. It is created on startup
|
||
|
* by reading the command-line and parsing configuration files.
|
||
|
*
|
||
|
* Once read in at the start, this structure doesn't change. The transmit
|
||
|
* and receive threads have only a "const" pointer to this structure.
|
||
|
*/
|
||
|
struct Masscan
|
||
|
{
|
||
|
/**
|
||
|
* What this program is doing, which is normally "Operation_Scan", but
|
||
|
* which can be other things, like "Operation_SelfTest"
|
||
|
*/
|
||
|
enum Operation op;
|
||
|
|
||
|
struct {
|
||
|
unsigned tcp:1;
|
||
|
unsigned udp:1; /* -sU */
|
||
|
unsigned sctp:1;
|
||
|
unsigned ping:1; /* --ping, ICMP echo */
|
||
|
unsigned arp:1; /* --arp, local ARP scan */
|
||
|
unsigned oproto:1; /* -sO */
|
||
|
} scan_type;
|
||
|
|
||
|
/**
|
||
|
* After scan type has been configured, add these ports. In other words,
|
||
|
* the user may specify `-sU` or `-sT` after the `--top-ports` parameter,
|
||
|
* so we have to wait until after parsing arguments to fill in the ports.
|
||
|
*/
|
||
|
unsigned top_ports;
|
||
|
|
||
|
/**
|
||
|
* Temporary file to echo parameters to, used for saving configuration
|
||
|
* to a file
|
||
|
*/
|
||
|
FILE *echo;
|
||
|
unsigned echo_all;
|
||
|
|
||
|
/**
|
||
|
* One or more network adapters that we'll use for scanning. Each adapter
|
||
|
* should have a separate set of IP source addresses, except in the case
|
||
|
* of PF_RING dnaX:Y adapters.
|
||
|
*/
|
||
|
struct {
|
||
|
char ifname[256];
|
||
|
struct Adapter *adapter;
|
||
|
struct stack_src_t src;
|
||
|
macaddress_t source_mac;
|
||
|
macaddress_t router_mac_ipv4;
|
||
|
macaddress_t router_mac_ipv6;
|
||
|
ipv4address_t router_ip;
|
||
|
int link_type; /* libpcap definitions */
|
||
|
unsigned char my_mac_count; /*is there a MAC address? */
|
||
|
unsigned vlan_id;
|
||
|
unsigned is_vlan:1;
|
||
|
unsigned is_usable:1;
|
||
|
} nic[8];
|
||
|
unsigned nic_count;
|
||
|
|
||
|
/**
|
||
|
* The target ranges of IPv4 addresses that are included in the scan.
|
||
|
* The user can specify anything here, and we'll resolve all overlaps
|
||
|
* and such, and sort the target ranges.
|
||
|
*/
|
||
|
struct MassIP targets;
|
||
|
|
||
|
/**
|
||
|
* IPv4 addresses/ranges that are to be excluded from the scan. This takes
|
||
|
* precedence over any 'include' statement. What happens is this: after
|
||
|
* all the configuration has been read, we then apply the exclude/blacklist
|
||
|
* on top of the target/whitelist, leaving only a target/whitelist left.
|
||
|
* Thus, during the scan, we only choose from the target/whitelist and
|
||
|
* don't consult the exclude/blacklist.
|
||
|
*/
|
||
|
struct MassIP exclude;
|
||
|
|
||
|
/**
|
||
|
* Only output these types of banners
|
||
|
*/
|
||
|
struct RangeList banner_types;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Maximum rate, in packets-per-second (--rate parameter). This can be
|
||
|
* a fraction of a packet-per-second, or be as high as 30000000.0 (or
|
||
|
* more actually, but I've only tested to 30megapps).
|
||
|
*/
|
||
|
double max_rate;
|
||
|
|
||
|
/**
|
||
|
* Number of retries (--retries or --max-retries parameter). Retries
|
||
|
* happen a few seconds apart.
|
||
|
*/
|
||
|
unsigned retries;
|
||
|
|
||
|
|
||
|
unsigned is_pfring:1; /* --pfring */
|
||
|
unsigned is_sendq:1; /* --sendq */
|
||
|
unsigned is_banners:1; /* --banners */
|
||
|
unsigned is_banners_rawudp:1; /* --rawudp */
|
||
|
unsigned is_offline:1; /* --offline */
|
||
|
unsigned is_noreset:1; /* --noreset, don't transmit RST */
|
||
|
unsigned is_gmt:1; /* --gmt, all times in GMT */
|
||
|
unsigned is_capture_cert:1; /* --capture cert */
|
||
|
unsigned is_capture_html:1; /* --capture html */
|
||
|
unsigned is_capture_heartbleed:1; /* --capture heartbleed */
|
||
|
unsigned is_capture_ticketbleed:1; /* --capture ticket */
|
||
|
unsigned is_test_csv:1; /* (temporary testing feature) */
|
||
|
unsigned is_infinite:1; /* -infinite */
|
||
|
unsigned is_readscan:1; /* --readscan, Operation_Readscan */
|
||
|
unsigned is_heartbleed:1; /* --heartbleed, scan for this vuln */
|
||
|
unsigned is_ticketbleed:1; /* --ticketbleed, scan for this vuln */
|
||
|
unsigned is_poodle_sslv3:1; /* --vuln poodle, scan for this vuln */
|
||
|
unsigned is_hello_ssl:1; /* --ssl, use SSL HELLO on all ports */
|
||
|
unsigned is_hello_smbv1:1; /* --smbv1, use SMBv1 hello, instead of v1/v2 hello */
|
||
|
unsigned is_hello_http:1; /* --hello=http, use HTTP on all ports */
|
||
|
unsigned is_scripting:1; /* whether scripting is needed */
|
||
|
unsigned is_capture_servername:1; /* --capture servername */
|
||
|
|
||
|
/** Packet template options, such as whether we should add a TCP MSS
|
||
|
* value, or remove it from the packet */
|
||
|
struct TemplateOptions *templ_opts; /* e.g. --tcpmss */
|
||
|
|
||
|
/**
|
||
|
* Wait forever for responses, instead of the default 10 seconds
|
||
|
*/
|
||
|
unsigned wait;
|
||
|
|
||
|
/**
|
||
|
* --resume
|
||
|
* This structure contains options for pausing the scan (by exiting the
|
||
|
* program) and restarting it later.
|
||
|
*/
|
||
|
struct {
|
||
|
/** --resume-index */
|
||
|
uint64_t index;
|
||
|
|
||
|
/** --resume-count */
|
||
|
uint64_t count;
|
||
|
|
||
|
/** Derives the --resume-index from the target ip:port */
|
||
|
struct {
|
||
|
unsigned ip;
|
||
|
unsigned port;
|
||
|
} target;
|
||
|
} resume;
|
||
|
|
||
|
/**
|
||
|
* --shard n/m
|
||
|
* This is used for distributing a scan across multiple "shards". Every
|
||
|
* shard in the scan must know the total number of shards, and must also
|
||
|
* know which of those shards is it's identity. Thus, shard 1/5 scans
|
||
|
* a different range than 2/5. These numbers start at 1, so it's
|
||
|
* 1/3 (#1 out of three), 2/3, and 3/3 (but not 0/3).
|
||
|
*/
|
||
|
struct {
|
||
|
unsigned one;
|
||
|
unsigned of;
|
||
|
} shard;
|
||
|
|
||
|
/**
|
||
|
* The packet template set we are current using. We store a binary template
|
||
|
* for TCP, UDP, SCTP, ICMP, and so on. All the scans using that protocol
|
||
|
* are then scanned using that basic template. IP and TCP options can be
|
||
|
* added to the basic template without affecting any other component
|
||
|
* of the system.
|
||
|
*/
|
||
|
struct TemplateSet *pkt_template;
|
||
|
|
||
|
/**
|
||
|
* A random seed for randomization if zero, otherwise we'll use
|
||
|
* the configured seed for repeatable tests.
|
||
|
*/
|
||
|
uint64_t seed;
|
||
|
|
||
|
/**
|
||
|
* This block configures what we do for the output files
|
||
|
*/
|
||
|
struct OutputStuff {
|
||
|
|
||
|
/**
|
||
|
* --output-format
|
||
|
* Examples are "xml", "binary", "json", "ndjson", "grepable", and so on.
|
||
|
*/
|
||
|
enum OutputFormat format;
|
||
|
|
||
|
/**
|
||
|
* --output-filename
|
||
|
* The name of the file where we are storing scan results.
|
||
|
* Note: the filename "-" means that we should send the file to
|
||
|
* <stdout> rather than to a file.
|
||
|
*/
|
||
|
char filename[256];
|
||
|
|
||
|
/**
|
||
|
* A feature of the XML output where we can insert an optional
|
||
|
* stylesheet into the file for better rendering on web browsers
|
||
|
*/
|
||
|
char stylesheet[256];
|
||
|
|
||
|
/**
|
||
|
* --append
|
||
|
* We should append to the output file rather than overwriting it.
|
||
|
*/
|
||
|
unsigned is_append:1;
|
||
|
|
||
|
/**
|
||
|
* --json-status
|
||
|
* Print each status update line to stderr as JSON ending with a newline
|
||
|
*
|
||
|
* This only applies to the three types of status lines that are printed
|
||
|
* in status_print(); it does *not* apply to things like startup messages,
|
||
|
* error messages or discovery of individual ports
|
||
|
*
|
||
|
*/
|
||
|
bool is_status_ndjson;
|
||
|
|
||
|
/**
|
||
|
* --open
|
||
|
* --open-only
|
||
|
* --show open
|
||
|
* Whether to show open ports
|
||
|
*/
|
||
|
unsigned is_show_open:1;
|
||
|
|
||
|
/**
|
||
|
* --show closed
|
||
|
* Whether to show closed ports (i.e. RSTs)
|
||
|
*/
|
||
|
unsigned is_show_closed:1;
|
||
|
|
||
|
/**
|
||
|
* --show host
|
||
|
* Whether to show host messages other than closed ports
|
||
|
*/
|
||
|
unsigned is_show_host:1;
|
||
|
|
||
|
/**
|
||
|
* print reason port is open, which is redundant for us
|
||
|
*/
|
||
|
unsigned is_reason:1;
|
||
|
|
||
|
/**
|
||
|
* --interactive
|
||
|
* Print to command-line while also writing to output file. This isn't
|
||
|
* needed if the output format is already 'interactive' (the default),
|
||
|
* but only if the default output format is anything else, and the
|
||
|
* user also wants interactivity.
|
||
|
*/
|
||
|
unsigned is_interactive:1;
|
||
|
|
||
|
/**
|
||
|
* Print state updates
|
||
|
*/
|
||
|
unsigned is_status_updates:1;
|
||
|
|
||
|
struct {
|
||
|
/**
|
||
|
* When we should rotate output into the target directory
|
||
|
*/
|
||
|
unsigned timeout;
|
||
|
|
||
|
/**
|
||
|
* When doing "--rotate daily", the rotation is done at GMT. In
|
||
|
* order to fix this, add an offset.
|
||
|
*/
|
||
|
unsigned offset;
|
||
|
|
||
|
/**
|
||
|
* Instead of rotating by timeout, we can rotate by filesize
|
||
|
*/
|
||
|
uint64_t filesize;
|
||
|
|
||
|
/**
|
||
|
* The directory to which we store rotated files
|
||
|
*/
|
||
|
char directory[256];
|
||
|
} rotate;
|
||
|
} output;
|
||
|
|
||
|
struct {
|
||
|
unsigned data_length; /* number of bytes to randomly append */
|
||
|
unsigned ttl; /* starting IP TTL field */
|
||
|
unsigned badsum; /* bad TCP/UDP/SCTP checksum */
|
||
|
|
||
|
unsigned packet_trace:1; /* print transmit messages */
|
||
|
|
||
|
char datadir[256];
|
||
|
} nmap;
|
||
|
|
||
|
char pcap_filename[256];
|
||
|
|
||
|
struct {
|
||
|
unsigned timeout;
|
||
|
} tcb;
|
||
|
|
||
|
struct {
|
||
|
char *pcap_payloads_filename;
|
||
|
char *nmap_payloads_filename;
|
||
|
char *nmap_service_probes_filename;
|
||
|
|
||
|
struct PayloadsUDP *udp;
|
||
|
struct PayloadsUDP *oproto;
|
||
|
struct TcpCfgPayloads *tcp;
|
||
|
struct NmapServiceProbeList *probes;
|
||
|
} payloads;
|
||
|
|
||
|
/** Reconfigure the HTTP header */
|
||
|
struct {
|
||
|
/* Method */
|
||
|
unsigned char *method;
|
||
|
size_t method_length;
|
||
|
|
||
|
/* URL */
|
||
|
unsigned char *url;
|
||
|
size_t url_length;
|
||
|
|
||
|
/* Version */
|
||
|
unsigned char *version;
|
||
|
size_t version_length;
|
||
|
|
||
|
/* Host */
|
||
|
unsigned char *host;
|
||
|
size_t host_length;
|
||
|
|
||
|
/* User-Agent */
|
||
|
unsigned char *user_agent;
|
||
|
size_t user_agent_length;
|
||
|
|
||
|
/* Payload after the header*/
|
||
|
unsigned char *payload;
|
||
|
size_t payload_length;
|
||
|
|
||
|
/* Headers */
|
||
|
struct {
|
||
|
const char *name;
|
||
|
unsigned char *value;
|
||
|
size_t value_length;
|
||
|
} headers[16];
|
||
|
size_t headers_count;
|
||
|
|
||
|
/* Cookies */
|
||
|
struct {
|
||
|
unsigned char *value;
|
||
|
size_t value_length;
|
||
|
} cookies[16];
|
||
|
size_t cookies_count;
|
||
|
|
||
|
/* Remove */
|
||
|
struct {
|
||
|
unsigned char *name;
|
||
|
} remove[16];
|
||
|
size_t remove_count;
|
||
|
} http;
|
||
|
|
||
|
unsigned tcp_connection_timeout;
|
||
|
|
||
|
/** Number of seconds to wait for a 'hello' from the server before
|
||
|
* giving up and sending a 'hello' from the client. Should be a small
|
||
|
* value when doing scans that expect client-side hellos, like HTTP or
|
||
|
* SSL, but should be a longer value when doing scans that expect server
|
||
|
* hellos, such as FTP or VNC */
|
||
|
unsigned tcp_hello_timeout;
|
||
|
|
||
|
|
||
|
char *bpf_filter;
|
||
|
|
||
|
struct {
|
||
|
ipaddress ip;
|
||
|
char *password;
|
||
|
unsigned port;
|
||
|
} redis;
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* --min-packet
|
||
|
*/
|
||
|
unsigned min_packet_size;
|
||
|
|
||
|
/**
|
||
|
* Number of rounds for randomization
|
||
|
* --blackrock-rounds
|
||
|
*/
|
||
|
unsigned blackrock_rounds;
|
||
|
|
||
|
/**
|
||
|
* --script <name>
|
||
|
*/
|
||
|
struct {
|
||
|
/* The name (filename) of the script to run */
|
||
|
char *name;
|
||
|
|
||
|
/* The script VM */
|
||
|
struct lua_State *L;
|
||
|
} scripting;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* --vuln <name>
|
||
|
* The name of a vuln to check, like "poodle"
|
||
|
*/
|
||
|
const char *vuln_name;
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
int mainconf_selftest(void);
|
||
|
void masscan_read_config_file(struct Masscan *masscan, const char *filename);
|
||
|
void masscan_command_line(struct Masscan *masscan, int argc, char *argv[]);
|
||
|
void masscan_usage(void);
|
||
|
void masscan_save_state(struct Masscan *masscan);
|
||
|
void main_listscan(struct Masscan *masscan);
|
||
|
|
||
|
/**
|
||
|
* Load databases, such as:
|
||
|
* - nmap-payloads
|
||
|
* - nmap-service-probes
|
||
|
* - pcap-payloads
|
||
|
*/
|
||
|
void masscan_load_database_files(struct Masscan *masscan);
|
||
|
|
||
|
/**
|
||
|
* Pre-scan the command-line looking for options that may affect how
|
||
|
* previous options are handled. This is a bit of a kludge, really.
|
||
|
*/
|
||
|
int masscan_conf_contains(const char *x, int argc, char **argv);
|
||
|
|
||
|
/**
|
||
|
* Called to set a <name=value> pair.
|
||
|
*/
|
||
|
void
|
||
|
masscan_set_parameter(struct Masscan *masscan,
|
||
|
const char *name, const char *value);
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Discover the local network adapter parameters, such as which
|
||
|
* MAC address we are using and the MAC addresses of the
|
||
|
* local routers.
|
||
|
*/
|
||
|
int
|
||
|
masscan_initialize_adapter(
|
||
|
struct Masscan *masscan,
|
||
|
unsigned index,
|
||
|
macaddress_t *source_mac,
|
||
|
macaddress_t *router_mac_ipv4,
|
||
|
macaddress_t *router_mac_ipv6);
|
||
|
|
||
|
/**
|
||
|
* Echoes the settings to the command-line. By default, echoes only
|
||
|
* non-default values. With "echo-all", everything is echoed.
|
||
|
*/
|
||
|
void
|
||
|
masscan_echo(struct Masscan *masscan, FILE *fp, unsigned is_echo_all);
|
||
|
|
||
|
/**
|
||
|
* Echoes the list of CIDR ranges to scan.
|
||
|
*/
|
||
|
void
|
||
|
masscan_echo_cidr(struct Masscan *masscan, FILE *fp, unsigned is_echo_all);
|
||
|
|
||
|
#endif
|