Commit 30e420d7 authored by robertdavidgraham's avatar robertdavidgraham
Browse files

enabled pause/resume

parent 7097e106
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ endif
INCLUDES = -I.
DEFINES = 
CC = gcc
CFLAGS = -g $(INCLUDES) $(DEFINES) -Wall -O3 -rdynamic
CFLAGS = -g $(INCLUDES) $(DEFINES) -Wall -O3 -rdynamic -Wno-format
.SUFFIXES: .c .cpp

tmp/%.o: src/%.c
+124 −57
Original line number Diff line number Diff line
@@ -72,26 +72,30 @@ parse_port_list(struct RangeList *ports, const char *string)
 * Use#2: make sure your configuration was interpreted correctly.
 ***************************************************************************/
void
masscan_echo(struct Masscan *masscan)
masscan_echo(struct Masscan *masscan, FILE *fp)
{
    unsigned i;

    printf("rate = %10.2f\n", masscan->max_rate);
    printf("adapter = %s\n", masscan->ifname);
    printf("adapter-ip = %u.%u.%u.%u\n", 
    fprintf(fp, "rate = %10.2f\n", masscan->max_rate);
    fprintf(fp, "randomize-hosts = true\n");
    

    fprintf(fp, "\n# adapter settings\n");
    fprintf(fp, "adapter = %s\n", masscan->ifname);
    fprintf(fp, "adapter-ip = %u.%u.%u.%u\n", 
        (masscan->adapter_ip>>24)&0xFF,
        (masscan->adapter_ip>>16)&0xFF,
        (masscan->adapter_ip>> 8)&0xFF,
        (masscan->adapter_ip>> 0)&0xFF
        );
    printf("adapter.mac = %02x:%02x:%02x:%02x:%02x:%02x\n",
    fprintf(fp, "adapter.mac = %02x:%02x:%02x:%02x:%02x:%02x\n",
            masscan->adapter_mac[0],
            masscan->adapter_mac[1],
            masscan->adapter_mac[2],
            masscan->adapter_mac[3],
            masscan->adapter_mac[4],
            masscan->adapter_mac[5]);
    printf("router.mac = %02x:%02x:%02x:%02x:%02x:%02x\n",
    fprintf(fp, "router.mac = %02x:%02x:%02x:%02x:%02x:%02x\n",
            masscan->router_mac[0],
            masscan->router_mac[1],
            masscan->router_mac[2],
@@ -100,80 +104,96 @@ masscan_echo(struct Masscan *masscan)
            masscan->router_mac[5]);

    /*
     * PORTS
     * Output information
     */
    fprintf(fp, "# output\n");
    switch (masscan->nmap.format) {
    case Output_Interactive:
        fprintf(stderr, "output.format = interactive\n");
        break;
    case Output_List:
        fprintf(stderr, "output.format = list\n");
        break;
    default:
        fprintf(stderr, "output.format = unknown(%u)\n", masscan->nmap.format);
        break;
    }
    fprintf(fp, "output.filename = %s\n", masscan->nmap.filename);
    if (masscan->nmap.append)
        fprintf(fp, "output.append = true\n");


    /*
     * Targets
     */
    printf("ports = ");
    fprintf(fp, "\n# targets\n");
    fprintf(fp, "ports = ");
    for (i=0; i<masscan->ports.count; i++) {
        struct Range range = masscan->ports.list[i];
        if (range.begin == range.end)
            printf("%u", range.begin);
            fprintf(fp, "%u", range.begin);
        else
            printf("%u-%u", range.begin, range.end);
            fprintf(fp, "%u-%u", range.begin, range.end);
        if (i+1 < masscan->ports.count)
            printf(",");
            fprintf(fp, ",");
    }
    if (masscan->ports.count == 0)
        printf("65536,70000-80000");
    printf("\n");

    /*
     * RANGES
     */
    fprintf(fp, "\n");
    for (i=0; i<masscan->targets.count; i++) {
        struct Range range = masscan->targets.list[i];
        printf("range = ");
        printf("%u.%u.%u.%u", 
        fprintf(fp, "range = ");
        fprintf(fp, "%u.%u.%u.%u", 
            (range.begin>>24)&0xFF,
            (range.begin>>16)&0xFF,
            (range.begin>> 8)&0xFF,
            (range.begin>> 0)&0xFF
            );
        if (range.begin != range.end) {
            printf("-%u.%u.%u.%u", 
            fprintf(fp, "-%u.%u.%u.%u", 
                (range.end>>24)&0xFF,
                (range.end>>16)&0xFF,
                (range.end>> 8)&0xFF,
                (range.end>> 0)&0xFF
                );
        }
        printf("\n");
        fprintf(fp, "\n");
    }

    if (masscan->targets.count == 0) {
        printf("range = 0.0.0.0-0.0.0.0\n");
        printf("range = 0.0.0.0/32\n");
    }

    /*
     * EXCLUDE
     */
    for (i=0; i<masscan->exclude_ip.count; i++) {
        struct Range range = masscan->exclude_ip.list[i];
        printf("exclude = ");
        printf("%u.%u.%u.%u", 
            (range.begin>>24)&0xFF,
            (range.begin>>16)&0xFF,
            (range.begin>> 8)&0xFF,
            (range.begin>> 0)&0xFF
            );
        if (range.begin != range.end) {
            printf("-%u.%u.%u.%u", 
                (range.end>>24)&0xFF,
                (range.end>>16)&0xFF,
                (range.end>> 8)&0xFF,
                (range.end>> 0)&0xFF
                );
        }
        printf("\n");
}

    if (masscan->targets.count == 0) {
        printf("exclude = 255.255.255.255-255.255.255.255\n");
        printf("exclude = 255.255.255.255/32\n");
/***************************************************************************
 ***************************************************************************/
void
masscan_save_state(struct Masscan *masscan)
{
    char filename[512];
    FILE *fp;
    int err;
    

    strcpy_s(filename, sizeof(filename), "paused.scan");
    fprintf(stderr, "                                                                      \r");
    fprintf(stderr, "saving resume file to: %s\n", filename);

    err = fopen_s(&fp, filename, "wt");
    if (err) {
        perror(filename);
        return;
    }

    fprintf(fp, "\n# resume information\n");
    fprintf(fp, "resume-seed = %llu\n", masscan->resume.seed);
    fprintf(fp, "resume-index = %llu\n", masscan->resume.index);
    fprintf(fp, "resume-range = %llu\n", masscan->lcg.m);
    fprintf(fp, "resume-lcg-a = %llu\n", masscan->lcg.a);
    fprintf(fp, "resume-lcg-c = %llu\n", masscan->lcg.c);

    masscan_echo(masscan, fp);

    fclose(fp);
}


/***************************************************************************
 ***************************************************************************/
void ranges_from_file(struct RangeList *ranges, const char *filename)
@@ -293,6 +313,18 @@ parse_mac_address(const char *text, unsigned char *mac)
    return 0;
}

static uint64_t
parseInt(const char *str)
{
    uint64_t result = 0;

    while (*str && isdigit(*str & 0xFF)) {
        result = result * 10 + (*str - '0');
        str++;
    }
    return result;
}


/***************************************************************************
 * Called either from the "command-line" parser when it sees a --parm,
@@ -445,7 +477,7 @@ masscan_set_parameter(struct Masscan *masscan, const char *name, const char *val
				offset++; /* skip comma */
		}
      	masscan->op = Operation_Scan;
    } else if (EQUALS("append-output", name)) {
    } else if (EQUALS("append-output", name) || EQUALS("output-append", name)) {
        masscan->nmap.append = 1;
    } else if (EQUALS("badsum", name)) {
        masscan->nmap.badsum = 1;
@@ -466,7 +498,7 @@ masscan_set_parameter(struct Masscan *masscan, const char *name, const char *val
        fprintf(stderr, "nmap(%s): DNS lookups will never be supported by this code\n", name);
        exit(1);
    } else if (EQUALS("echo", name)) {
        masscan_echo(masscan);
        masscan_echo(masscan, stdout);
        exit(1);
    } else if (EQUALS("excludefile", name) || EQUALS("exclude-file", name) || EQUALS("exclude.file", name)) {
        ranges_from_file(&masscan->exclude_ip, value);
@@ -510,6 +542,16 @@ masscan_set_parameter(struct Masscan *masscan, const char *name, const char *val
    } else if (EQUALS("osscan-guess", name)) {
        fprintf(stderr, "nmap(%s): OS scanning unsupported\n", name);
        exit(1);
    } else if (EQUALS("output-format", name)) {
        if (EQUALS("list", value))
            masscan->nmap.format = Output_List;
        else if (EQUALS("interactive", value))
            masscan->nmap.format = Output_Interactive;
        else {
            fprintf(stderr, "error: %s=%s\n", name, value);
        }
    } else if (EQUALS("output-filename", name)) {
        strcpy_s(masscan->nmap.filename, sizeof(masscan->nmap.filename), value);
    } else if (EQUALS("packet-trace", name)) {
        masscan->nmap.packet_trace = 1;
    } else if (EQUALS("privileged", name) || EQUALS("unprivileged", name)) {
@@ -526,8 +568,19 @@ masscan_set_parameter(struct Masscan *masscan, const char *name, const char *val
    } else if (EQUALS("release-memory", name)) {
        fprintf(stderr, "nmap(%s): this is our default option\n", name);
    } else if (EQUALS("resume", name)) {
        fprintf(stderr, "nmap(%s): unsupported now, but we'll fix that soon!\n", name);
        exit(1);
        masscan_read_config_file(masscan, value);
    } else if (EQUALS("resume-seed", name)) {
        masscan->resume.seed = parseInt(value);
    } else if (EQUALS("resume-index", name)) {
        masscan->resume.index = parseInt(value);
    } else if (EQUALS("resume-range", name)) {
        masscan->lcg.m = parseInt(value);
    } else if (EQUALS("resume-lcg-m", name)) {
        masscan->lcg.m = parseInt(value);
    } else if (EQUALS("resume-lcg-a", name)) {
        masscan->lcg.a = parseInt(value);
    } else if (EQUALS("resume-lcg-c", name)) {
        masscan->lcg.c = parseInt(value);
    } else if (EQUALS("retries", name)) {
        unsigned x = strtoul(value, 0, 0);
        if (x >= 1000) {
@@ -761,18 +814,31 @@ masscan_command_line(struct Masscan *masscan, int argc, char *argv[])
                switch (argv[i][2]) {
                case 'A':
                    masscan->nmap.format = Output_All;
                    fprintf(stderr, "nmap(%s): unsupported output format\n", argv[i]);
                    exit(1);
                    break;
                case 'N':
                    masscan->nmap.format = Output_Normal;
                    fprintf(stderr, "nmap(%s): unsupported output format\n", argv[i]);
                    exit(1);
                    break;
                case 'X':
                    masscan->nmap.format = Output_XML;
                    fprintf(stderr, "nmap(%s): unsupported output format\n", argv[i]);
                    exit(1);
                    break;
                case 'S':
                    masscan->nmap.format = Output_ScriptKiddie;
                    fprintf(stderr, "nmap(%s): unsupported output format\n", argv[i]);
                    exit(1);
                    break;
                case 'G':
                    masscan->nmap.format = Output_Grepable;
                    fprintf(stderr, "nmap(%s): unsupported output format\n", argv[i]);
                    exit(1);
                    break;
                case 'L':
                    masscan_set_parameter(masscan, "output-format", "list");
                    break;
                default:
                    fprintf(stderr, "nmap(%s): unknown output format\n", argv[i]);
@@ -784,7 +850,8 @@ masscan_command_line(struct Masscan *masscan, int argc, char *argv[])
                    fprintf(stderr, "missing output filename\n");
                    exit(1);
                }
                strcpy_s(masscan->nmap.filename, sizeof(masscan->nmap.filename), argv[i]);

                masscan_set_parameter(masscan, "output-filename", argv[i]);
                break;
            case 'O':
                fprintf(stderr, "nmap(%s): unsupported, OS detection is too complex\n", argv[i]);
@@ -942,7 +1009,7 @@ masscan_read_config_file(struct Masscan *masscan, const char *filename)
    err = fopen_s(&fp, filename, "rt");
    if (err) {
        perror(filename);
        exit(1);
        return;
    }

    while (fgets(line, sizeof(line), fp)) {
+91 −32
Original line number Diff line number Diff line
@@ -20,8 +20,15 @@

#include <string.h>
#include <time.h>
#include <signal.h>


unsigned control_c_pressed=0;
void control_c_handler(int x)
{
	control_c_pressed = 1+x;
}


/***************************************************************************
 * This thread spews packets as fast as it can
@@ -42,7 +49,7 @@ scanning_thread(void *v)
	struct Status status;
    struct Throttler throttler;
    struct TcpPacket *pkt_template = masscan->pkt_template;
   	uint64_t index;
   	uint64_t seed;
    unsigned packet_trace = masscan->nmap.packet_trace;
    double timestamp_start;

@@ -55,12 +62,12 @@ scanning_thread(void *v)
    /*
     * Seed the LCG so that it does a different scan every time.
     */
    index = time(0) % masscan->lcg.m;
    seed = masscan->resume.seed;

    /*
     * the main loop
     */
	for (i=0; i<masscan->lcg.m; ) {
	for (i=masscan->resume.index; i<masscan->lcg.m; ) {
        uint64_t batch_size;

        /*
@@ -78,11 +85,11 @@ scanning_thread(void *v)

			/* randomize the index
             *  index = lcg_rand(index, a, c, m); */
			index = (index * a + c) % m;
			seed = (seed * a + c) % m;

			/* Pick the IPv4 address pointed to by this index */
			ip = rangelist_pick(&masscan->targets, index%count_ips);
			port = rangelist_pick(&masscan->ports, index/count_ips);
			ip = rangelist_pick(&masscan->targets, seed%count_ips);
			port = rangelist_pick(&masscan->ports, seed/count_ips);

            /* Send the probe */
			rawsock_send_probe(masscan->adapter, ip, port, pkt_template);
@@ -102,6 +109,15 @@ scanning_thread(void *v)
            if (packet_trace)
                tcpkt_trace(pkt_template, ip, port, timestamp_start);
        }

        if (control_c_pressed) {
            masscan->resume.seed = seed;
            masscan->resume.index = i;
            masscan_save_state(masscan);
            fprintf(stderr, "waiting 10 seconds to exit...\n");
            fflush(stderr);
            break;
        }
	}

    /*
@@ -113,6 +129,7 @@ scanning_thread(void *v)
            status_print(&status, i++, m);
            port_usleep(1000000);
        }
        fprintf(stderr, "                                                                      \r");
    }

    /* Tell the other it's time to exit the program */
@@ -292,6 +309,7 @@ main_scan(struct Masscan *masscan)
    unsigned char adapter_mac[6];
    unsigned char router_mac[6];
    int err;
    FILE *fpout = stdout;
    
    /*
     * Turn the adapter on, and get the running configuration
@@ -354,6 +372,14 @@ main_scan(struct Masscan *masscan)
	 * This can take a couple seconds on a slow CPU. We have to find all the
     * primes out to 2^24 when doing large ranges.
	 */
    if (masscan->resume.index && masscan->resume.seed && masscan->lcg.m
        && masscan->lcg.a && masscan->lcg.c) {
        if (masscan->lcg.m != count_ips * count_ports) {
            fprintf(stderr, "FAIL: corrupt resume data\n");
            exit(1);
        } else
            fprintf(stderr, "resuming scan...\n");
    } else {
	    masscan->lcg.m = count_ips * count_ports;
	    lcg_calculate_constants(
		    masscan->lcg.m,
@@ -365,8 +391,23 @@ main_scan(struct Masscan *masscan)
		    masscan->lcg.c,
		    masscan->lcg.m
            );
        masscan->resume.seed = time(0) % masscan->lcg.m;
        masscan->resume.index = 0;
    }


    /*
     * Open output
     */
    if (masscan->nmap.format != Output_Interactive && masscan->nmap.filename[0]) {
        FILE *fp;
        err = fopen_s(&fp, masscan->nmap.filename, masscan->nmap.append?"a":"w");
        if (err || fp == NULL) {
            perror(masscan->nmap.filename);
            exit(1);
        }
    }

    /*
     * Start the scanning thread.
     * THIS IS WHERE THE PROGRAM STARTS SPEWING OUT PACKETS AT A HIGH
@@ -447,18 +488,32 @@ main_scan(struct Masscan *masscan)
         */
        src = parsed.ip_src[0]<<24 | parsed.ip_src[1]<<16
            | parsed.ip_src[2]<< 8 | parsed.ip_src[3]<<0;
        if (masscan->nmap.format == Output_Interactive) {
            printf("Discovered open port %u/tcp on %u.%u.%u.%u                          \n",
        switch (masscan->nmap.format) {
        case Output_Interactive:
            fprintf(fpout, "Discovered open port %u/tcp on %u.%u.%u.%u                          \n",
                parsed.port_src,
                (src>>24)&0xFF,
                (src>>16)&0xFF,
                (src>> 8)&0xFF,
                (src>> 0)&0xFF
                );
            break;
        case Output_List:
            fprintf(fpout, "open tcp %u %u.%u.%u.%u\n",
                parsed.port_src,
                (src>>24)&0xFF,
                (src>>16)&0xFF,
                (src>> 8)&0xFF,
                (src>> 0)&0xFF
                );
            break;
        }
    }


    if (fpout != stdout)
        fclose(fpout);

    return 0;
}

@@ -468,18 +523,12 @@ int main(int argc, char *argv[])
{
    struct Masscan masscan[1];

    {
        char buffer[80];
        time_t now  = time(0);
        struct tm x;

        gmtime_s(&x, &now);
        strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S GMT", &x); 
        fprintf(stderr, "\nStarting masscan 1.0 (http://github.com/robertdavidgraham/masscan) at %s\n", buffer);
    }


	memset(masscan, 0, sizeof(*masscan));
   	/*
	 * Register a signal handler for the <ctrl-c> key. This allows
     * us to pause and then resume a scan.
     */
	signal(SIGINT, control_c_handler);


    /* We need to do a separate "raw socket" initialization step */
@@ -490,6 +539,7 @@ int main(int argc, char *argv[])
	 * Read in the configuration from the command-line. We are looking for
     * either options or a list of IPv4 address ranges.
	 */
	memset(masscan, 0, sizeof(*masscan));
    masscan->max_rate = 100.0; /* initialize: max rate = hundred packets-per-second */
    masscan->adapter_port = 0x10000; /* value not set */
	
@@ -527,6 +577,15 @@ int main(int argc, char *argv[])
        /*
         * THIS IS THE NORMAL THING
         */
        {
            char buffer[80];
            time_t now  = time(0);
            struct tm x;

            gmtime_s(&x, &now);
            strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S GMT", &x); 
            fprintf(stderr, "\nStarting masscan 1.0 (http://github.com/robertdavidgraham/masscan) at %s\n", buffer);
        }
        fprintf(stderr, " -- forced options: -sS -Pn -n --randomize-hosts -v\n");
        fprintf(stderr, "Initiating SYN Stealth Scan\n");
        return main_scan(masscan);
+9 −1
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@ enum OutpuFormat {
    Output_XML,
    Output_ScriptKiddie,
    Output_Grepable,
    Output_All
    Output_All,
    Output_List /* specific to Masscan */
};

struct Masscan
@@ -96,6 +97,12 @@ struct Masscan
        char stylesheet[256];
    } nmap;


    struct {
        uint64_t seed;
        uint64_t index;
    } resume;

    /**
     * The packet template we are current using
     */
@@ -112,6 +119,7 @@ struct Masscan
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 masscan_save_state(struct Masscan *masscan);


#endif