Execution
In my last blog I promised to show me hacking into Serval; my web
server platform. I also had another blog where I showed how I setup Caprica so
she could dual boot into Puppy Linux mode. I wrote a simple raw socket program
that I compiled on Puppy Caprica and ran to "attack" Serval. Nothing
showed up in the WinPcap program running on Serval; i.e., nothing from the raw
socket program arrived in Serval's network adapter. I thought Linux allowed you
to run raw sockets. All of a sudden I was afraid I wouldn't be hacking into
Serval.
My virtual XP system is using SP1, which supports raw sockets, supposedly. I did try upgrading the service pack, but that failed; SP1 is no longer supported by Microsoft. So I should be able to use virtual Caprica to attack Serval. Still nothing showing up on Serval. Getting desperate, I copied some code from http://www.binarytides.com/raw-sockets-packets-with-winpcap/ , a WinPcap implementation of a raw socket program. This program was written to be compiled with VC++ 6.0, so I found a copy on the Internet, compiled and still no luck! Maybe SP1 doesn't work with raw sockets either. ...or, my attempt at upgrading virtual Caprica ruined her ability too spoof.
I thought, I might as well try Windows 2000. So, I created a virtual Windows 2000 system and ran the raw socket program on it. Success! I compiled on XP SP1, so SP1 probably can support raw sockets. Here are some screen shots of me hacking (kinda sorta, I used the real source IP so I wouldn't have too syn flood anyone).
Here's some more code; first the sending ("attacking") program.
/* Author: Silver Moon ( m00n.silv3r@gmail.com ) Slightly modified by Dave Marshall Katelansky (dave@community-info.org) Description: Send Raw packets using winpcap Using SendArp of iphlpapi.dll to retrive the MAC Address of the IP Address. SendArp function available only on Windows 2000 and above */ #define HAVE_REMOTE // For Promiscous mode sniffing :) #undef _WIN64 #include#include "pcap.h" #include "raw.h" #include "adapter.h" #include #pragma comment(lib,"ws2_32.lib") //For winsock #pragma comment(lib,"wpcap.lib") //For winpcap void ifprint(pcap_if_t *d); //Checksum function USHORT in_checksum(unsigned short* , int); int init_winsock(); int main() { pcap_if_t *alldevs , *d , dev[100]; pcap_t *fp; pcap_addr_t *a; u_char packet[65536],s_mac[6],d_mac[6]; in_addr srcip , destip; ETHER_HDR *ehdr; IPV4_HDR *iphdr; TCP_HDR *tcphdr; P_HDR pseudo_header; char *dump = "GET / HTTP/1.0"; char sgatewayip[16],errbuf[PCAP_ERRBUF_SIZE+1], *data; int gatewayip , count = 1 , process_id = GetCurrentProcessId(); char acUserName[100]; DWORD nUserName = sizeof(acUserName); if (GetUserName(acUserName, &nUserName)) { printf("Username : %s \n" , acUserName); } else { printf("Failed to lookup user name, error code %d \n" , GetLastError() ); } loadiphlpapi(); // Retrieve the interfaces list from winpcap printf("Retrieving the available devices..."); if (pcap_findalldevs_ex("rpcap://", NULL, &alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf); exit(1); } printf("Retrieved.\n"); printf("The following devices found : \n\n"); for(d = alldevs ; d ; d = d->next) //Print the devices { printf("%d)\n",count); dev[count++] = *d; ifprint(d); } //Ask user to select the device he wants to use printf("Enter the device number you want to use : "); scanf("%d",&count); a = dev[count].addresses; //Get mac addresses of source and gateway ips srcip = ((struct sockaddr_in *)a->addr)->sin_addr; GetMacAddress(s_mac , srcip); printf("Selected device has mac address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X",s_mac[0],s_mac[1],s_mac[2],s_mac[3],s_mac[4],s_mac[5]); GetGateway(srcip , sgatewayip , &gatewayip); printf("\nSelected device has gateway : %s",sgatewayip); destip.s_addr = gatewayip; GetMacAddress(d_mac , destip); printf(" (Mac : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X)",d_mac[0],d_mac[1],d_mac[2],d_mac[3],d_mac[4],d_mac[5]); //Now open the selected device printf("\nOpening the selected device..."); if ( (fp = pcap_open(dev[count].name, // name of the device 100, // portion of the packet to capture (only the first 100 bytes) PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode 1000, // read timeout NULL, // authentication on the remote machine errbuf // error buffer ) ) == NULL) { fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", dev[count].name); return 1; } printf("Opened"); pcap_freealldevs(alldevs); // ******************* Ethernet Header ***************** ehdr = (PETHER_HDR)packet; memcpy(ehdr->source , s_mac , 6); //Source Mac address memcpy(ehdr->dest,d_mac,6); //Destination MAC address ehdr->type = htons(0x0800); //IP Frames // ******************* IP Header ***************** iphdr = (PIPV4_HDR)(packet + sizeof(ETHER_HDR)); iphdr->ip_version = 4; iphdr->ip_header_len = 5; //In double words thats 4 bytes iphdr->ip_tos = 0; iphdr->ip_total_length = htons (sizeof(IPV4_HDR) + sizeof(TCP_HDR) + strlen(dump)); iphdr->ip_id = htons(2); iphdr->ip_frag_offset = 0; iphdr->ip_reserved_zero=0; iphdr->ip_dont_fragment=1; iphdr->ip_more_fragment=0; iphdr->ip_frag_offset1 = 0; iphdr->ip_ttl = 3; iphdr->ip_protocol = IPPROTO_TCP; iphdr->ip_srcaddr = srcip.s_addr; //inet_addr("76.18.55.205"); iphdr->ip_destaddr = inet_addr("76.18.55.205"); iphdr->ip_checksum =0; iphdr->ip_checksum = in_checksum((unsigned short*)iphdr, sizeof(IPV4_HDR)); // ******************* TCP Header ***************** tcphdr = (PTCP_HDR)(packet + sizeof(ETHER_HDR) + sizeof(IPV4_HDR)); tcphdr->source_port = htons( 5000 ); tcphdr->dest_port = htons(80); tcphdr->sequence=0; tcphdr->acknowledge=0; tcphdr->reserved_part1=0; tcphdr->data_offset=5; tcphdr->fin=0; tcphdr->syn=1; tcphdr->rst=0; tcphdr->psh=0; tcphdr->ack=0; tcphdr->urg=0; tcphdr->ecn=0; tcphdr->cwr=0; tcphdr->window = htons(64240); tcphdr->checksum=0; tcphdr->urgent_pointer = 0; // ******************* Data Dump ***************** data = (char*)(packet + sizeof(ETHER_HDR) + sizeof(IPV4_HDR) + sizeof(TCP_HDR)); strcpy(data,dump); // ******************* Checksum calculation ***************** pseudo_header.source_address = srcip.s_addr; //inet_addr("76.18.55.205"); //forge it >:) srcip.s_addr; pseudo_header.dest_address = inet_addr("76.18.55.205"); //destip.s_addr; pseudo_header.placeholder = 0; pseudo_header.protocol = IPPROTO_TCP; pseudo_header.tcp_length = htons(sizeof(TCP_HDR) + strlen(dump)); memcpy(&pseudo_header.tcp , tcphdr , sizeof TCP_HDR); unsigned char *seudo; seudo = new unsigned char(sizeof P_HDR + strlen(dump)); memcpy(seudo, &pseudo_header, sizeof P_HDR); memcpy(seudo + sizeof P_HDR , data , strlen(dump)); tcphdr->checksum = in_checksum((unsigned short*)seudo, sizeof(P_HDR) + strlen(dump)); printf("\nSending Packet..."); //Uncomment this line if you want to flood char seqnbr[11]; //DMK 11/01/2012, my modifications start here and end at the bottom char ch; // of the "while loop" //while(1) { pcap_sendpacket(fp , packet , sizeof(ETHER_HDR) + sizeof(IPV4_HDR) + sizeof(TCP_HDR) + strlen(dump)); printf("Just sent the syn packet\n\n"); ch = getchar(); printf("Enter the sequence number:"); //remember to switch fgets(seqnbr, sizeof(seqnbr), stdin); //the ack and seq back tcphdr->sequence = atoi(seqnbr); //and inc our ack printf("Enter the acknowledge number:"); ch = getchar(); fgets(seqnbr, sizeof(seqnbr), stdin); tcphdr->acknowledge = atoi(seqnbr); tcphdr->syn=0; //our final hand shake is an ack tcphdr->ack=1; pcap_sendpacket(fp , packet , sizeof(ETHER_HDR) + sizeof(IPV4_HDR) + sizeof(TCP_HDR) + strlen(dump)); pcap_sendpacket(fp , packet , sizeof(ETHER_HDR) + sizeof(IPV4_HDR) + sizeof(TCP_HDR) + strlen(dump)); } return 0; } /* Print all the available information about a winpcap device like lo , eth0 */ void ifprint(pcap_if_t *d) { pcap_addr_t *a; printf("%s\n",d->name); //Name if (d->description) { printf("Description: %s\n",d->description); //Description } // Loopback Address printf("Loopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"Yes":"No"); for(a = d->addresses ; a ; a=a->next) //Now print the IP addresses etc of each device { printf("Address Family: #%d\n",a->addr->sa_family); switch(a->addr->sa_family) { case AF_INET: printf("Address Family Name: AF_INET\n"); if (a->addr) { printf("Address: %s\n",inet_ntoa(((struct sockaddr_in *)a->addr)->sin_addr)); } if (a->netmask) { //If a valid netmask has been detected printf("Netmask: %s\n",inet_ntoa(((struct sockaddr_in *)a->netmask)->sin_addr)); } if (a->broadaddr) { //If a valid Broadcast Address is detected printf("Broadcast Address: %s\n",inet_ntoa(((struct sockaddr_in *)a->broadaddr)->sin_addr)); } if (a->dstaddr) { printf("Destination Address: %s\n",inet_ntoa(((struct sockaddr_in *)a->dstaddr)->sin_addr)); } break; default: printf("Address Family Name: Unknown\n"); break; } } printf("\n"); } /* General Networking Functions Checksum function - used to calculate the IP header and TCP header checksums */ unsigned short in_checksum(unsigned short *ptr,int nbytes) { register long sum; unsigned short oddbyte; register short answer; sum=0; while(nbytes>1) { sum+=*ptr++; nbytes-=2; } if(nbytes==1) { oddbyte=0; *((u_char*)&oddbyte)=*(u_char*)ptr; sum+=oddbyte; } sum = (sum>>16)+(sum & 0xffff); sum = sum + (sum>>16); answer=(SHORT)~sum; return(answer); } /* Initialise Winsock with the WSAStartup function */ int init_winsock() { WSADATA firstsock; if (WSAStartup(MAKEWORD(2,2),&firstsock) != 0) { printf("\nFailed to initialise winsock."); printf("\nError Code : %d",WSAGetLastError()); return 1; //Return 1 on error } return 0; //Return 0 on successful }
Here's my Modified basic_dump code, further modified too
allow manual control of the display lines:
#include#include #include #include "winsock2.h" //need this for the ntohs and ntohl functions #pragma comment(lib, "ws2_32.lib") //I added the wpcap.lib library in the project settings but I wasn't sure about how too add this //so I'm adding the library for winsock here, the old fashioned way using namespace System; /* prototype of the packet handler */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); // prototype of dotted decimal formatting functio void createDotted(char *binaryStr); FILE *network_records; int main(int argc, char *argv[]) { pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; pcap_t *adhandle; char errbuf[PCAP_ERRBUF_SIZE]; network_records = fopen("network_records.txt.","w"); /* Retrieve the device list */ if(pcap_findalldevs(&alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); exit(1); } /* Print the list */ for(d=alldevs; d; d=d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)\n", d->description); else printf(" (No description available)\n"); } if(i==0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return -1; } printf("Enter the interface number (1-%d):",i); scanf("%d", &inum); if(inum < 1 || inum > i) { printf("\nInterface number out of range.\n"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } /* Jump to the selected adapter */ for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); /* Open the device */ /* Open the adapter */ if ((adhandle= pcap_open_live(d->name, // name of the device 65536, // portion of the packet to capture. // 65536 grants that the whole packet will be captured on all the MACs. 1, // promiscuous mode (nonzero means promiscuous) 1000, // read timeout errbuf // error buffer )) == NULL) { fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } printf("\nlistening on %s...\n", d->description); /* At this point, we don't need any more the device list. Free it */ pcap_freealldevs(alldevs); /* start the capture */ pcap_loop(adhandle, 0, packet_handler, NULL); pcap_close(adhandle); fclose(network_records); return 0; } /* Callback function invoked by libpcap for every incoming packet */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { struct tm *ltime; char timestr[16]; time_t local_tv_sec; typedef struct tcp_header { unsigned short source_port; // source port unsigned short dest_port; // destination port unsigned int sequence; // sequence number - 32 bits unsigned int acknowledge; // acknowledgement number - 32 bits unsigned char ns :1; //Nonce Sum Flag Added in RFC 3540. unsigned char reserved_part1:3; //according to rfc unsigned char data_offset:4; /*The number of 32-bit words in the TCP header. This indicates where the data begins. The length of the TCP header is always a multiple of 32 bits.*/ unsigned char fin :1; //Finish Flag unsigned char syn :1; //Synchronise Flag unsigned char rst :1; //Reset Flag unsigned char psh :1; //Push Flag unsigned char ack :1; //Acknowledgement Flag unsigned char urg :1; //Urgent Flag unsigned char ecn :1; //ECN-Echo Flag unsigned char cwr :1; //Congestion Window Reduced Flag unsigned short window; // window unsigned short checksum; // checksum unsigned short urgent_pointer; // urgent pointer } TCP_HDR; /* Ip header (v4) */ typedef struct ip_hdr { unsigned char ip_header_len:4; // 4-bit header length (in 32-bit words) normally=5 (Means 20 Bytes may be 24 also) unsigned char ip_version :4; // 4-bit IPv4 version unsigned char ip_tos; // IP type of service unsigned short ip_total_length; // Total length unsigned short ip_id; // Unique identifier unsigned char ip_frag_offset :5; // Fragment offset field unsigned char ip_more_fragment :1; unsigned char ip_dont_fragment :1; unsigned char ip_reserved_zero :1; unsigned char ip_frag_offset1; //fragment offset unsigned char ip_ttl; // Time to live unsigned char ip_protocol; // Protocol(TCP,UDP etc) unsigned short ip_checksum; // IP checksum unsigned int ip_srcaddr; // Source address unsigned int ip_destaddr; // Source address } IPV4_HDR; /* Ethernet Header */ typedef struct ethernet_header { UCHAR dest[6]; UCHAR source[6]; USHORT type; } ETHER_HDR; ETHER_HDR *ethhdr; IPV4_HDR *iphdr; TCP_HDR *tcpheader; unsigned char iphdrlen = 0; unsigned int sequence = 0; unsigned int ack = 0; unsigned short dest_port = 0; unsigned short source_port = 0; int flags = 0; unsigned int sourceip = 0; unsigned int destip = 0; char binaryStr[255]; /* * unused parameter */ (VOID)(param); /* Get the sequence number from pkt_data */ iphdr = (IPV4_HDR *) (pkt_data + sizeof(ETHER_HDR)); iphdrlen = iphdr->ip_header_len*4; tcpheader = (TCP_HDR*) (pkt_data +iphdrlen + sizeof(ETHER_HDR)); if (tcpheader != NULL) { sequence = ntohl(tcpheader->sequence); ack = ntohl(tcpheader->acknowledge);; source_port = ntohs(tcpheader->source_port); dest_port = ntohs(tcpheader->dest_port); sourceip = iphdr->ip_srcaddr; destip = iphdr->ip_destaddr; } else { sequence = -1; } /* convert the timestamp to readable format */ local_tv_sec = header->ts.tv_sec; ltime=localtime(&local_tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); //I just want info from web connections - filtering for port 80 // if ((dest_port == 80) || (source_port == 80)) if (tcpheader->syn) { ++flags; } if (tcpheader->ack) { flags += 2; } switch (flags) { case 1: printf("flag = syn\n"); fputs("flag = syn\n", network_records); break; case 2: printf("flag = ackn\n"); fputs("flag = ack\n", network_records); break; case 3: printf("flag = syn + ack\n"); fputs("flag = ack + syn\n", network_records); break; } if (flags != 0) { char ch; itoa(sourceip, binaryStr, 2); createDotted(binaryStr); printf("source %s\n", binaryStr); fprintf(network_records, "source %s\n", binaryStr); itoa(destip, binaryStr, 2); createDotted(binaryStr); printf("dest %s\n", binaryStr); fprintf(network_records, "dest %s\n", binaryStr); printf("%s,%.6d len:%d, seqnbr:%u, acknbr:%u, source_port:%u, dest_port:%u, sourceip:%u, destip:%u\n", timestr, header->ts.tv_usec, header->len, sequence, ack, source_port, dest_port, sourceip, destip); fprintf(network_records, "%s,%.6d len:%d, seqnbr:%u, acknbr:%u, source_port:%u, dest_port:%u, sourceip:%u, destip:%u\n", timestr, header->ts.tv_usec, header->len, sequence, ack, source_port, dest_port, sourceip, destip); printf("Hit ennto continue\n"); ch = getchar(); } } void createDotted(char *binaryStr) { struct dottedType { char seg0[9]; char seg1[9]; char seg2[9]; char seg3[9]; } Dotted; memset(Dotted.seg3, 0, 9); strncpy(Dotted.seg3, binaryStr, 8); memset(Dotted.seg2, 0, 9); strncpy(Dotted.seg2, binaryStr + 8, 8); memset(Dotted.seg1, 0, 9); strncpy(Dotted.seg1, binaryStr + 16, 8); memset(Dotted.seg0, 0, 9); strncpy(Dotted.seg0, binaryStr + 24, 8); sprintf(binaryStr, "ip: %u.%u.%u.%u\n", strtoul(Dotted.seg0, NULL, 2), strtoul(Dotted.seg1, NULL, 2), strtoul(Dotted.seg2, NULL, 2), strtoul(Dotted.seg3, NULL, 2)); }