Loading Makefile +19 −0 Original line number Diff line number Diff line SYS := $(shell gcc -dumpmachine) ifneq (, $(findstring linux, $(SYS))) LIBS = -lpcap -lm -lrt endif ifneq (, $(findstring darwin, $(SYS))) LIBS = -lpcap -lm endif ifneq (, $(findstring mingw, $(SYS))) LIBS = -lwpcap endif ifneq (, $(findstring cygwin, $(SYS))) LIBS = -lwpcap endif INCLUDES = -I. DEFINES = CC = gcc Loading README.md +41 −24 Original line number Diff line number Diff line Loading @@ -16,29 +16,42 @@ only see 1 packet per second comming in. # Building First, install libpcap. $ apt-get install libpcap-dev Then type make, there is no configuration step. On Debian/Ubuntu, it goes something like this: $ git clone https://github.com/robertdavidgraham/masscan $ cd masscan $ sudo apt-get install build-essential $ sudo apt-get install libpcap-dev $ make $ make regresss This puts the program in the 'bin' subdirectory. On Windows, use the VisualStudio 2010 project. On Mac OS X, once you've installed a developer environment, you should be able to likewise just "make; make regress". Detecting the network adapter is currently broken, so you'll get errors telling you what to manually configure when running the program. On BSD's, it oughta be close to working, but I haven't tried it yet. I'd like to see what 'netmap' can do with it -- in theory should be a lot faster than Linux. # Regression testing The project contains a built-in self-test: $ make regress masscan --selftest bin/masscan --selftest selftest: success! If the self-test fails, the program returns an exit code of '1' and an error message particular to which module and subtest failed. The regression test is completely offline: it doesn't send any packets. NOTE: The regression test is completely offline: it doesn't send any packets. It's just testing the invidual units within the program. I plan to create an online test, where a second program listens on the network to verify that what's transmitted is the same thing that was specified to be sent. Loading @@ -46,34 +59,38 @@ that what's transmitted is the same thing that was specified to be sent. # Usage An example usage is the following: Usage is similar to ''nmap'', such as the following scan: $ masscan -i eth0 -p80,8000-8100 10.0.0.0/8 -c settings.conf # bin/masscan -p80,8000-8100 10.0.0.0/8 This will: * scan the 10.x.x.x subnet, all 16 million addresses * scans port 80 and the range 8000 to 8100, or 102 addresses total ## Setting router MAC address (IMPORTANT!!) You need to set the destination router's MAC address. I haven't added the code to figure this out yet. This is done by putting it in the configuration file: Some comparison with ''nmap'': * no default ports to scan, you must specify ''-p <ports>'' * the ''-sS'' option is enabled: this does SYN scan only * the ''-n'' option is enabled: no DNS resolution happens * the ''-Pn'' option is enabled: doesn't ping hosts first * target hosts are IP addresses or ranges, not DNS names * specify ''--rate <rate>'' router-mac = 00:11:22:33:44:55 I've tried to make this familiar to ''nmap'' users, but fundamentally it's a vastly different scanner. You can try some ''nmap'' options you think might work -- it'll quickly tell you if they don't. or on the command line $ masscan --router-mac=00:11:22:33:44:55 ## Transmit rate (IMPORTANT!!) This program spews out packets very fast. Even in virtual-machine through a virtualized network layer, it can transmit 200,000 packets per second. This will overload a lot of network. This program spews out packets very fast. On Windows, or from VMs, it can do 300,000 packets/second. On a Linux (no virtualization) it'll do 1.6 million packets-per-second. That's fast enough to melt most networks. Note that it'll only melt your own network. It randomizes the target IP addresses so that it shouldn't overwhelm any one network. By default, the program attempts to throttle transmission, but this code is broken at the moment. By default, the rate is set to 100 packets/second. To increase the rate to a million use something like "--rate 1000000". # How it works Loading Loading @@ -109,7 +126,7 @@ The `translate()` function uses some quirky math, based on the LCG PRNG translation. The key property here is that we can completely randomize the order withou keeping any state in memory. In other words, scanning the without keeping any state in memory. In other words, scanning the entire Internet for all ports is a 48-bit problem (32-bit address and 16-bit port), but we accomplish this with only a few kilobytes of memory. Loading src/main-conf.c +377 −28 File changed.Preview size limit exceeded, changes collapsed. Show changes src/main-status.c +19 −5 Original line number Diff line number Diff line Loading @@ -44,21 +44,35 @@ status_print(struct Status *status, uint64_t count, uint64_t max_count) status->last.time = t; } /* If nothing's changed, then stop here, because otherwise we'll * be dividing by zero or something */ if (count <= status->last.count) return; /* Get the time. NOTE: this is CLOCK_MONOTONIC_RAW on Linux, not * wall-clock time. */ now = port_gettime(); elapsed = ((double)now - (double)status->last.clock)/(double)1000000.0; if (elapsed == 0) return; status->last.clock = now; fprintf(stderr, "rate = %5.3f-kilaprobes/sec %5.3f%% done \r", ((double)(count - status->last.count)*1.0/elapsed)/1000.0, (double)(count*100.0/max_count) /* * Print the message to <stderr> so that <stdout> can be redirected * to a file (<stdout> reports what systems were found). */ { double rate = ((double)(count - status->last.count)*1.0/elapsed); double percent_done = (double)(count*100.0/max_count); /* (%u-days %02u:%02u:%02u remaining) */ fprintf(stderr, "rate = %5.3f-kpps: About %5.2f%% done; \r", rate/1000.0, percent_done ); fflush(stderr); } status->last.count = count; } Loading src/main-throttle.c +41 −2 Original line number Diff line number Diff line /* rate calculations for the packets Rate-limit/throttler: stops us from transmiting too fast. We can send packets at millions of packets/second. This will melt most networks. Therefore, we need to throttle or rate-limit how fast we go. Since we are sending packet at a rate of 10-million-per-second, we the calculations need to be done in a light-weight manner. For one Loading @@ -21,7 +25,8 @@ /*************************************************************************** ***************************************************************************/ void throttler_start(struct Throttler *throttler, double max_rate) void throttler_start(struct Throttler *throttler, double max_rate) { unsigned i; Loading Loading @@ -62,8 +67,15 @@ throttler_next_batch(struct Throttler *throttler, uint64_t packet_count) again: /* NOTE: this uses CLOCK_MONOTONIC_RAW on Linux, so the timstamp doesn't * move forward when the machine is suspended */ timestamp = port_gettime(); /* * We record that last 256 buckets, and average the rate over all of * them. */ index = (throttler->index) & 0xFF; throttler->buckets[index].timestamp = timestamp; throttler->buckets[index].packet_count = packet_count; Loading @@ -72,9 +84,28 @@ again: old_timestamp = throttler->buckets[index].timestamp; old_packet_count = throttler->buckets[index].packet_count; /* * If the delay is more than 1-second, then we should reset the system * in order to avoid transmittting too fast. */ if (timestamp - old_timestamp > 1000000) { //throttler_start(throttler, throttler->max_rate); throttler->batch_size = 1; goto again; } /* * Calculate the recent rate. * NOTE: this isn't the rate "since start", but only the "recent" rate. * That's so that if the system pauses for a while, we don't flood the * network trying to catch up. */ current_rate = 1.0*(packet_count - old_packet_count)/((timestamp - old_timestamp)/1000000.0); /* * If we've been going too fast, then <pause> for a moment, then * try again. */ if (current_rate > max_rate) { double waittime; Loading @@ -90,6 +121,14 @@ again: goto again; } /* * Calculate how many packets are needed to catch up again to the current * rate, and return that. * * NOTE: this is almost always going to have the value of 1 (one). Only at * very high speeds (above 100,000 packets/second) will this value get * larger. */ throttler->batch_size *= 1.005; if (throttler->batch_size > 10000) throttler->batch_size = 10000; Loading Loading
Makefile +19 −0 Original line number Diff line number Diff line SYS := $(shell gcc -dumpmachine) ifneq (, $(findstring linux, $(SYS))) LIBS = -lpcap -lm -lrt endif ifneq (, $(findstring darwin, $(SYS))) LIBS = -lpcap -lm endif ifneq (, $(findstring mingw, $(SYS))) LIBS = -lwpcap endif ifneq (, $(findstring cygwin, $(SYS))) LIBS = -lwpcap endif INCLUDES = -I. DEFINES = CC = gcc Loading
README.md +41 −24 Original line number Diff line number Diff line Loading @@ -16,29 +16,42 @@ only see 1 packet per second comming in. # Building First, install libpcap. $ apt-get install libpcap-dev Then type make, there is no configuration step. On Debian/Ubuntu, it goes something like this: $ git clone https://github.com/robertdavidgraham/masscan $ cd masscan $ sudo apt-get install build-essential $ sudo apt-get install libpcap-dev $ make $ make regresss This puts the program in the 'bin' subdirectory. On Windows, use the VisualStudio 2010 project. On Mac OS X, once you've installed a developer environment, you should be able to likewise just "make; make regress". Detecting the network adapter is currently broken, so you'll get errors telling you what to manually configure when running the program. On BSD's, it oughta be close to working, but I haven't tried it yet. I'd like to see what 'netmap' can do with it -- in theory should be a lot faster than Linux. # Regression testing The project contains a built-in self-test: $ make regress masscan --selftest bin/masscan --selftest selftest: success! If the self-test fails, the program returns an exit code of '1' and an error message particular to which module and subtest failed. The regression test is completely offline: it doesn't send any packets. NOTE: The regression test is completely offline: it doesn't send any packets. It's just testing the invidual units within the program. I plan to create an online test, where a second program listens on the network to verify that what's transmitted is the same thing that was specified to be sent. Loading @@ -46,34 +59,38 @@ that what's transmitted is the same thing that was specified to be sent. # Usage An example usage is the following: Usage is similar to ''nmap'', such as the following scan: $ masscan -i eth0 -p80,8000-8100 10.0.0.0/8 -c settings.conf # bin/masscan -p80,8000-8100 10.0.0.0/8 This will: * scan the 10.x.x.x subnet, all 16 million addresses * scans port 80 and the range 8000 to 8100, or 102 addresses total ## Setting router MAC address (IMPORTANT!!) You need to set the destination router's MAC address. I haven't added the code to figure this out yet. This is done by putting it in the configuration file: Some comparison with ''nmap'': * no default ports to scan, you must specify ''-p <ports>'' * the ''-sS'' option is enabled: this does SYN scan only * the ''-n'' option is enabled: no DNS resolution happens * the ''-Pn'' option is enabled: doesn't ping hosts first * target hosts are IP addresses or ranges, not DNS names * specify ''--rate <rate>'' router-mac = 00:11:22:33:44:55 I've tried to make this familiar to ''nmap'' users, but fundamentally it's a vastly different scanner. You can try some ''nmap'' options you think might work -- it'll quickly tell you if they don't. or on the command line $ masscan --router-mac=00:11:22:33:44:55 ## Transmit rate (IMPORTANT!!) This program spews out packets very fast. Even in virtual-machine through a virtualized network layer, it can transmit 200,000 packets per second. This will overload a lot of network. This program spews out packets very fast. On Windows, or from VMs, it can do 300,000 packets/second. On a Linux (no virtualization) it'll do 1.6 million packets-per-second. That's fast enough to melt most networks. Note that it'll only melt your own network. It randomizes the target IP addresses so that it shouldn't overwhelm any one network. By default, the program attempts to throttle transmission, but this code is broken at the moment. By default, the rate is set to 100 packets/second. To increase the rate to a million use something like "--rate 1000000". # How it works Loading Loading @@ -109,7 +126,7 @@ The `translate()` function uses some quirky math, based on the LCG PRNG translation. The key property here is that we can completely randomize the order withou keeping any state in memory. In other words, scanning the without keeping any state in memory. In other words, scanning the entire Internet for all ports is a 48-bit problem (32-bit address and 16-bit port), but we accomplish this with only a few kilobytes of memory. Loading
src/main-status.c +19 −5 Original line number Diff line number Diff line Loading @@ -44,21 +44,35 @@ status_print(struct Status *status, uint64_t count, uint64_t max_count) status->last.time = t; } /* If nothing's changed, then stop here, because otherwise we'll * be dividing by zero or something */ if (count <= status->last.count) return; /* Get the time. NOTE: this is CLOCK_MONOTONIC_RAW on Linux, not * wall-clock time. */ now = port_gettime(); elapsed = ((double)now - (double)status->last.clock)/(double)1000000.0; if (elapsed == 0) return; status->last.clock = now; fprintf(stderr, "rate = %5.3f-kilaprobes/sec %5.3f%% done \r", ((double)(count - status->last.count)*1.0/elapsed)/1000.0, (double)(count*100.0/max_count) /* * Print the message to <stderr> so that <stdout> can be redirected * to a file (<stdout> reports what systems were found). */ { double rate = ((double)(count - status->last.count)*1.0/elapsed); double percent_done = (double)(count*100.0/max_count); /* (%u-days %02u:%02u:%02u remaining) */ fprintf(stderr, "rate = %5.3f-kpps: About %5.2f%% done; \r", rate/1000.0, percent_done ); fflush(stderr); } status->last.count = count; } Loading
src/main-throttle.c +41 −2 Original line number Diff line number Diff line /* rate calculations for the packets Rate-limit/throttler: stops us from transmiting too fast. We can send packets at millions of packets/second. This will melt most networks. Therefore, we need to throttle or rate-limit how fast we go. Since we are sending packet at a rate of 10-million-per-second, we the calculations need to be done in a light-weight manner. For one Loading @@ -21,7 +25,8 @@ /*************************************************************************** ***************************************************************************/ void throttler_start(struct Throttler *throttler, double max_rate) void throttler_start(struct Throttler *throttler, double max_rate) { unsigned i; Loading Loading @@ -62,8 +67,15 @@ throttler_next_batch(struct Throttler *throttler, uint64_t packet_count) again: /* NOTE: this uses CLOCK_MONOTONIC_RAW on Linux, so the timstamp doesn't * move forward when the machine is suspended */ timestamp = port_gettime(); /* * We record that last 256 buckets, and average the rate over all of * them. */ index = (throttler->index) & 0xFF; throttler->buckets[index].timestamp = timestamp; throttler->buckets[index].packet_count = packet_count; Loading @@ -72,9 +84,28 @@ again: old_timestamp = throttler->buckets[index].timestamp; old_packet_count = throttler->buckets[index].packet_count; /* * If the delay is more than 1-second, then we should reset the system * in order to avoid transmittting too fast. */ if (timestamp - old_timestamp > 1000000) { //throttler_start(throttler, throttler->max_rate); throttler->batch_size = 1; goto again; } /* * Calculate the recent rate. * NOTE: this isn't the rate "since start", but only the "recent" rate. * That's so that if the system pauses for a while, we don't flood the * network trying to catch up. */ current_rate = 1.0*(packet_count - old_packet_count)/((timestamp - old_timestamp)/1000000.0); /* * If we've been going too fast, then <pause> for a moment, then * try again. */ if (current_rate > max_rate) { double waittime; Loading @@ -90,6 +121,14 @@ again: goto again; } /* * Calculate how many packets are needed to catch up again to the current * rate, and return that. * * NOTE: this is almost always going to have the value of 1 (one). Only at * very high speeds (above 100,000 packets/second) will this value get * larger. */ throttler->batch_size *= 1.005; if (throttler->batch_size > 10000) throttler->batch_size = 10000; Loading