| 1 | /* sloth@ww88.org - 01/05/2010 |
|---|
| 2 | * |
|---|
| 3 | * Product of the GNAA |
|---|
| 4 | * |
|---|
| 5 | * Receiver code isn't done but this works just fine: |
|---|
| 6 | * tcpdump -i eth0 -n -s 50 dst port <your port> and 'tcp[13] = 18' |
|---|
| 7 | * |
|---|
| 8 | * Spoofed TCP SYN scan to offload ip reputation hits from port scanning |
|---|
| 9 | * use your fast server to send the packets and use your cheap DSL/VPS |
|---|
| 10 | * to listen for the SYN/SYNACK. |
|---|
| 11 | */ |
|---|
| 12 | |
|---|
| 13 | #include <stdio.h> |
|---|
| 14 | #include <stdlib.h> |
|---|
| 15 | #include <string.h> |
|---|
| 16 | #include <unistd.h> |
|---|
| 17 | #include <netdb.h> |
|---|
| 18 | #include <netinet/in.h> |
|---|
| 19 | #include <arpa/inet.h> |
|---|
| 20 | #include <sys/socket.h> |
|---|
| 21 | #include <sys/time.h> |
|---|
| 22 | #include <sys/types.h> |
|---|
| 23 | #include <sys/select.h> |
|---|
| 24 | #include <signal.h> |
|---|
| 25 | #include <time.h> |
|---|
| 26 | |
|---|
| 27 | struct ip_header { |
|---|
| 28 | uint8_t len:4, |
|---|
| 29 | version:4; |
|---|
| 30 | uint8_t tos; |
|---|
| 31 | uint16_t tot_len; |
|---|
| 32 | uint16_t id; |
|---|
| 33 | uint16_t frag_off; |
|---|
| 34 | uint8_t ttl; |
|---|
| 35 | uint8_t protocol; |
|---|
| 36 | uint16_t sum; |
|---|
| 37 | uint32_t saddr; |
|---|
| 38 | uint32_t daddr; |
|---|
| 39 | } __attribute__((packed)); |
|---|
| 40 | |
|---|
| 41 | struct tcp_header { |
|---|
| 42 | uint16_t sport; |
|---|
| 43 | uint16_t dport; |
|---|
| 44 | uint32_t seq; |
|---|
| 45 | uint32_t ack_seq; |
|---|
| 46 | uint8_t len; |
|---|
| 47 | uint8_t flags; |
|---|
| 48 | uint16_t win; |
|---|
| 49 | uint16_t sum; |
|---|
| 50 | uint16_t urg; |
|---|
| 51 | } __attribute__((packed)); |
|---|
| 52 | |
|---|
| 53 | struct tcp_packet { |
|---|
| 54 | struct ip_header iph; |
|---|
| 55 | struct tcp_header tcph; |
|---|
| 56 | }; |
|---|
| 57 | |
|---|
| 58 | struct Receiver { |
|---|
| 59 | struct in_addr addr; |
|---|
| 60 | uint16_t sport; |
|---|
| 61 | int sock; |
|---|
| 62 | struct tcp_packet *tcp_packet; |
|---|
| 63 | struct sockaddr_in sin; |
|---|
| 64 | }; |
|---|
| 65 | |
|---|
| 66 | uint32_t tot_count = 0, last_count = 0; |
|---|
| 67 | uint8_t timer = 10; |
|---|
| 68 | |
|---|
| 69 | void usage(char *message) { |
|---|
| 70 | fprintf(stderr, "usage: ./flood_ns [options]\n" |
|---|
| 71 | " -r <ip>/<bitmask> * random scan ex: 192.168.1.0/24\n" |
|---|
| 72 | " -p <port> * scan port\n" |
|---|
| 73 | " -l <filename> * host[:port] list of receivers\n" |
|---|
| 74 | " -u <number> * random scan reusable seed\n" |
|---|
| 75 | " -C <number> * random scan resume count\n" |
|---|
| 76 | "%s", message ? message : ""); |
|---|
| 77 | exit(-1); |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | void fatal(char *reason) { |
|---|
| 81 | fprintf(stderr, "fatal: %s\n", reason); |
|---|
| 82 | exit(-1); |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | void update_count() { |
|---|
| 86 | uint32_t delta; |
|---|
| 87 | |
|---|
| 88 | delta = tot_count - last_count; |
|---|
| 89 | printf("--------------------------------\n" |
|---|
| 90 | " Counter: %u\n" |
|---|
| 91 | " hosts/second: %u\n" |
|---|
| 92 | " kilobits/second: %u\n", |
|---|
| 93 | tot_count, delta / timer, |
|---|
| 94 | ((sizeof(struct tcp_header) * 8) * (delta / timer)) / 1000); |
|---|
| 95 | last_count = tot_count; |
|---|
| 96 | alarm(timer); |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | struct tcp_packet *alloc_packet() { |
|---|
| 100 | struct tcp_packet *packet; |
|---|
| 101 | struct ip_header *iph; |
|---|
| 102 | struct tcp_header *tcph; |
|---|
| 103 | |
|---|
| 104 | if(!(packet = malloc(sizeof(struct tcp_packet)))) |
|---|
| 105 | fatal("error: allocating tcp packet"); |
|---|
| 106 | |
|---|
| 107 | iph = &packet->iph; |
|---|
| 108 | tcph = &packet->tcph; |
|---|
| 109 | |
|---|
| 110 | iph->len = 5; |
|---|
| 111 | iph->version = 4; |
|---|
| 112 | iph->tos = 0; |
|---|
| 113 | iph->tot_len = htons(sizeof(struct tcp_packet)); |
|---|
| 114 | iph->id = 0xffff; //1 + (int)(65000.0 * (rand() / (RAND_MAX + 1.0)));; |
|---|
| 115 | iph->frag_off = 0; |
|---|
| 116 | iph->ttl = 255; |
|---|
| 117 | |
|---|
| 118 | iph->protocol = 6; |
|---|
| 119 | |
|---|
| 120 | tcph->seq = random(); |
|---|
| 121 | tcph->ack_seq = random(); |
|---|
| 122 | tcph->win = htons(8192); |
|---|
| 123 | tcph->len = 5 << 4; |
|---|
| 124 | tcph->flags = 2; |
|---|
| 125 | return(packet); |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | void init_packet(long source, int sport, long dest, int port, |
|---|
| 129 | struct tcp_packet *tcp_packet) { |
|---|
| 130 | struct ip_header *iph; |
|---|
| 131 | struct tcp_header *tcph; |
|---|
| 132 | |
|---|
| 133 | iph = &tcp_packet->iph; |
|---|
| 134 | tcph = &tcp_packet->tcph; |
|---|
| 135 | |
|---|
| 136 | iph->saddr = source; |
|---|
| 137 | iph->daddr = dest; |
|---|
| 138 | iph->sum = 0; // csum((unsigned short *)iph, sizeof(struct ip_header)); |
|---|
| 139 | |
|---|
| 140 | tcph->sum = 0; |
|---|
| 141 | tcph->sport = htons(sport); |
|---|
| 142 | tcph->dport = htons(port); |
|---|
| 143 | } |
|---|
| 144 | |
|---|
| 145 | void do_scan(uint16_t dport, struct Receiver *rx_list, uint32_t ip_base, |
|---|
| 146 | uint32_t seed, char shift) { |
|---|
| 147 | struct tcp_packet *tcp_packet; |
|---|
| 148 | struct ip_header *iph; |
|---|
| 149 | struct tcp_header *tcph; |
|---|
| 150 | char *pos; |
|---|
| 151 | uint16_t sport; |
|---|
| 152 | uint32_t x, y, i, s, olen, tmp[32]; |
|---|
| 153 | register int count = 20 >> 1,sum; |
|---|
| 154 | register unsigned short *p; |
|---|
| 155 | struct in_addr ip; |
|---|
| 156 | |
|---|
| 157 | /* pre-init packets */ |
|---|
| 158 | for(i = 0; rx_list[i].addr.s_addr; i++) { |
|---|
| 159 | |
|---|
| 160 | tcp_packet = alloc_packet(); |
|---|
| 161 | |
|---|
| 162 | if(!rx_list[i].sport) |
|---|
| 163 | rx_list[i].sport = 1024 + (int)(65000.0 * (rand() / (RAND_MAX + 1024.0))); |
|---|
| 164 | |
|---|
| 165 | sport = rx_list[i].sport; |
|---|
| 166 | init_packet(rx_list[i].addr.s_addr, sport, 0, dport, tcp_packet); |
|---|
| 167 | |
|---|
| 168 | rx_list[i].tcp_packet = tcp_packet; |
|---|
| 169 | |
|---|
| 170 | rx_list[i].sin.sin_family = AF_INET; |
|---|
| 171 | rx_list[i].sin.sin_addr.s_addr = inet_addr("1.1.1.1"); |
|---|
| 172 | rx_list[i].sin.sin_port = htons(sport); |
|---|
| 173 | |
|---|
| 174 | if((s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { |
|---|
| 175 | fprintf(stderr, "ERROR send_packet() -> socket()\n"); |
|---|
| 176 | } |
|---|
| 177 | else if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &olen, sizeof(olen)) < 0) { |
|---|
| 178 | fprintf(stderr, "ERROR: could not set socket option IP_HDRINCL.\n"); |
|---|
| 179 | close(s); |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | rx_list[i].sock = s; |
|---|
| 183 | |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | /* initialize random scan parameters */ |
|---|
| 187 | if(seed) |
|---|
| 188 | srand(seed); |
|---|
| 189 | else { |
|---|
| 190 | seed = 1; |
|---|
| 191 | printf("resume seed: %d\n", seed); |
|---|
| 192 | srand(seed); |
|---|
| 193 | } |
|---|
| 194 | |
|---|
| 195 | if(!(pos = malloc(shift))) { |
|---|
| 196 | fprintf(stderr, "malloc()\n"); |
|---|
| 197 | exit(-1); |
|---|
| 198 | } |
|---|
| 199 | |
|---|
| 200 | memset(pos, 0, shift); |
|---|
| 201 | memset(&tmp, 0, shift * 4); |
|---|
| 202 | |
|---|
| 203 | for(i = 0; i < shift;) { |
|---|
| 204 | x = (int)((float)shift*rand()/(RAND_MAX+1.0)); |
|---|
| 205 | |
|---|
| 206 | if(tmp[x] || x == i) |
|---|
| 207 | continue; |
|---|
| 208 | |
|---|
| 209 | pos[i] = x; |
|---|
| 210 | tmp[x] = x+1; |
|---|
| 211 | i++; |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | /* scan */ |
|---|
| 215 | signal(SIGALRM, update_count); |
|---|
| 216 | alarm(timer); |
|---|
| 217 | |
|---|
| 218 | for(i = 0; tot_count < (0xffffffff >> (32 - shift)); tot_count++, i++) { |
|---|
| 219 | |
|---|
| 220 | if(!rx_list[i].addr.s_addr) |
|---|
| 221 | i = 0; |
|---|
| 222 | |
|---|
| 223 | iph = &rx_list[i].tcp_packet->iph; |
|---|
| 224 | tcph = &rx_list[i].tcp_packet->tcph; |
|---|
| 225 | |
|---|
| 226 | for(y = 0, x = 0; y < shift; y++) { |
|---|
| 227 | tmp[y] = ((tot_count >> y) & 1) << pos[y]; |
|---|
| 228 | x += tmp[y]; |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | iph->daddr = htonl(x + htonl(ip_base)); |
|---|
| 232 | |
|---|
| 233 | count = 20 >> 1; |
|---|
| 234 | tcph->sum = 0; |
|---|
| 235 | p = (uint16_t *)&rx_list[i].tcp_packet->tcph; |
|---|
| 236 | |
|---|
| 237 | sum = (iph->saddr >> 16) + (iph->saddr & 0xffff) + (iph->daddr >> 16) |
|---|
| 238 | + (iph->daddr & 0xffff) + 1536 + htons(count << 1); |
|---|
| 239 | |
|---|
| 240 | while(count--) sum += *p++; |
|---|
| 241 | |
|---|
| 242 | sum = (sum >> 16) + (sum & 0xffff); |
|---|
| 243 | tcph->sum = ~(sum += (sum >> 16)); |
|---|
| 244 | |
|---|
| 245 | if(sendto(rx_list[i].sock, rx_list[i].tcp_packet, sizeof(struct tcp_packet), |
|---|
| 246 | 0, (struct sockaddr *)&rx_list[i].sin, sizeof(rx_list[i].sin)) < 1) { |
|---|
| 247 | printf("sendto() failed, backing off\n"); |
|---|
| 248 | usleep(50); |
|---|
| 249 | } |
|---|
| 250 | |
|---|
| 251 | |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | } |
|---|
| 255 | |
|---|
| 256 | long resolve(char *host) { |
|---|
| 257 | struct in_addr ip; |
|---|
| 258 | struct hostent *he; |
|---|
| 259 | |
|---|
| 260 | if((ip.s_addr = inet_addr(host)) == -1) { |
|---|
| 261 | if(!(he = gethostbyname(host))) |
|---|
| 262 | return(-1); |
|---|
| 263 | else |
|---|
| 264 | memcpy(&ip.s_addr, he->h_addr, 4); |
|---|
| 265 | } |
|---|
| 266 | return(ip.s_addr); |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | struct Receiver *read_rxs(char *filename) { |
|---|
| 270 | FILE *fp; |
|---|
| 271 | uint32_t len = 0, count = 0, i; |
|---|
| 272 | struct Receiver *rx_list; |
|---|
| 273 | struct in_addr ip; |
|---|
| 274 | char buffer[256], *p; |
|---|
| 275 | |
|---|
| 276 | if(!(fp = fopen(filename, "r"))) { |
|---|
| 277 | fprintf(stderr, "Error: can't open file: %s\n", filename); |
|---|
| 278 | exit(-1); |
|---|
| 279 | } |
|---|
| 280 | |
|---|
| 281 | len = 256 * sizeof(struct Receiver); |
|---|
| 282 | |
|---|
| 283 | if(!(rx_list = malloc(len))) { |
|---|
| 284 | fprintf(stderr, "Error: malloc\n"); |
|---|
| 285 | exit(-1); |
|---|
| 286 | } |
|---|
| 287 | |
|---|
| 288 | while(fgets(buffer, sizeof(buffer), fp)) { |
|---|
| 289 | |
|---|
| 290 | if (count >= (len / sizeof(struct Receiver)) - 2) { |
|---|
| 291 | if (!(rx_list = realloc(rx_list, len + |
|---|
| 292 | (256 * sizeof(struct Receiver))))) { |
|---|
| 293 | fprintf(stderr, "Error: realloc\n"); |
|---|
| 294 | exit(-1); |
|---|
| 295 | } |
|---|
| 296 | |
|---|
| 297 | len += 256 * sizeof(struct Receiver); |
|---|
| 298 | } |
|---|
| 299 | |
|---|
| 300 | if(buffer[strlen(buffer) - 1] == '\n') |
|---|
| 301 | buffer[strlen(buffer) - 1] = 0; |
|---|
| 302 | |
|---|
| 303 | if(!(p = strchr(buffer, ':'))) |
|---|
| 304 | rx_list[count].sport = 0; |
|---|
| 305 | else { |
|---|
| 306 | *p = 0; |
|---|
| 307 | p++; |
|---|
| 308 | rx_list[count].sport = atoi(p); |
|---|
| 309 | //printf("%d %d\n", rx_list[count].sport, atoi(p)); |
|---|
| 310 | } |
|---|
| 311 | |
|---|
| 312 | if((rx_list[count].addr.s_addr = resolve(buffer)) == -1) |
|---|
| 313 | continue; |
|---|
| 314 | |
|---|
| 315 | printf("%s:%u\n", inet_ntoa(rx_list[count].addr), rx_list[count].sport); |
|---|
| 316 | count++; |
|---|
| 317 | |
|---|
| 318 | } |
|---|
| 319 | |
|---|
| 320 | printf("*** Loaded %u Receivers ***\n", count); |
|---|
| 321 | |
|---|
| 322 | if(!count) { |
|---|
| 323 | fprintf(stderr, "Error: 0 Receivers Found\n"); |
|---|
| 324 | exit(-1); |
|---|
| 325 | } |
|---|
| 326 | |
|---|
| 327 | return(rx_list); |
|---|
| 328 | } |
|---|
| 329 | |
|---|
| 330 | int main(int argc, char *argv[]) { |
|---|
| 331 | struct Receiver *rx_list; |
|---|
| 332 | struct in_addr ip_base; |
|---|
| 333 | uint16_t shift = 0; |
|---|
| 334 | uint32_t c, i, dport, stime, rseed, dtime; |
|---|
| 335 | char rxlist_file[255], *p; |
|---|
| 336 | |
|---|
| 337 | printf("###### scansyn_tx.c - sloth@ww88.org ######\n"); |
|---|
| 338 | |
|---|
| 339 | if(argc == 1) |
|---|
| 340 | usage(NULL); |
|---|
| 341 | |
|---|
| 342 | ip_base.s_addr = 0; |
|---|
| 343 | rxlist_file[0] = 0; |
|---|
| 344 | |
|---|
| 345 | while((c = getopt(argc, argv, "l:p:r:u:C:")) != -1) { |
|---|
| 346 | |
|---|
| 347 | switch(c) { |
|---|
| 348 | |
|---|
| 349 | case 'l': |
|---|
| 350 | |
|---|
| 351 | strncpy(rxlist_file, optarg, sizeof(rxlist_file) - 1); |
|---|
| 352 | break; |
|---|
| 353 | |
|---|
| 354 | case 'p': |
|---|
| 355 | |
|---|
| 356 | dport = atoi(optarg); |
|---|
| 357 | break; |
|---|
| 358 | |
|---|
| 359 | case 'r': |
|---|
| 360 | |
|---|
| 361 | if(!(p = strchr(optarg, '/'))) |
|---|
| 362 | usage("error: invalid range ex: 192.168.1.0/24\n"); |
|---|
| 363 | |
|---|
| 364 | p[0] = 0; |
|---|
| 365 | if(!inet_aton(optarg, &ip_base)) |
|---|
| 366 | usage("error: invalid random base address\n"); |
|---|
| 367 | |
|---|
| 368 | p++; |
|---|
| 369 | shift = 32 - atoi(p); |
|---|
| 370 | if(shift > 32) |
|---|
| 371 | usage("error: invalid range ex: 192.168.1.0/24\n"); |
|---|
| 372 | |
|---|
| 373 | printf("random scanning %s/%d\n", inet_ntoa(ip_base), 32 - shift); |
|---|
| 374 | break; |
|---|
| 375 | |
|---|
| 376 | case 'u': |
|---|
| 377 | |
|---|
| 378 | rseed = atoi(optarg); |
|---|
| 379 | printf("resumable seed: %d\n", rseed); |
|---|
| 380 | break; |
|---|
| 381 | |
|---|
| 382 | case 'C': |
|---|
| 383 | |
|---|
| 384 | tot_count = atol(optarg); |
|---|
| 385 | printf("resumable count: %d\n", tot_count); |
|---|
| 386 | break; |
|---|
| 387 | |
|---|
| 388 | default: |
|---|
| 389 | |
|---|
| 390 | usage(NULL); |
|---|
| 391 | exit(-1); |
|---|
| 392 | |
|---|
| 393 | } |
|---|
| 394 | |
|---|
| 395 | } |
|---|
| 396 | |
|---|
| 397 | if(!dport) |
|---|
| 398 | usage("-p is required\n"); |
|---|
| 399 | |
|---|
| 400 | if(!ip_base.s_addr && !shift) |
|---|
| 401 | usage("-r is required\n"); |
|---|
| 402 | |
|---|
| 403 | if(!rxlist_file[0]) |
|---|
| 404 | usage("-l is required\n"); |
|---|
| 405 | |
|---|
| 406 | printf("hosts to scan: %d\n", 0xffffffff >> (32 - shift)); |
|---|
| 407 | |
|---|
| 408 | rx_list = read_rxs(rxlist_file); |
|---|
| 409 | |
|---|
| 410 | stime = time(0); |
|---|
| 411 | srand(getpid() * getuid() + time(0)); |
|---|
| 412 | |
|---|
| 413 | do_scan(dport, rx_list, ip_base.s_addr, rseed, shift); |
|---|
| 414 | |
|---|
| 415 | if(!(dtime = time(0) - stime)) |
|---|
| 416 | dtime = 1; |
|---|
| 417 | |
|---|
| 418 | printf("-------- COMPLETED SCAN ---------\n" |
|---|
| 419 | " Hosts Scanned: %u\n" |
|---|
| 420 | " Total Seconds: %u\n" |
|---|
| 421 | " hosts/second: %u\n" |
|---|
| 422 | " kilobits/second: %u\n", |
|---|
| 423 | tot_count, |
|---|
| 424 | dtime, |
|---|
| 425 | tot_count / dtime, |
|---|
| 426 | ((tot_count * sizeof(struct tcp_packet) * 8) / 1000) / dtime); |
|---|
| 427 | } |
|---|
| 428 | |
|---|