/**************************************************** This program is based on code found at this URL: http://www.Planet-Source-Code.com/vb/scripts/ShowCode.asp?txtCodeId=4952&lngWId=3 Modified by Keith Oxenrider koxenrider@sol-biotech.com August 22, 2003 NOTE: You have to be logged on as a member of the administrator group to run this. This program crashes sometimes when reading packets (mostly ping) Comments from original author: Packet Sniffer 12.10.02 Made By KT RFC 768 User Datagram Protocol RFC 791 Internet Protocol RFC 792 Internet Control Message Protocol RFC 793 Transmission Control Protocol ****************************************************/ #define MAX_PACKET_SIZE 65525 #define BIND2IP "127.0.0.1" //put your real IP here #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1) #include #include #include std::string m_strFileName = "RawPackts.dat"; typedef struct iphdr{ unsigned char VerIHL; //Version and IP Header Length unsigned char Tos; unsigned short Total_len;//to get length in bytes, divide by 256 unsigned short ID; unsigned short Flags_and_Frags; //Flags 3 bits and Fragment offset 13 bits unsigned char TTL; unsigned char Protocol; unsigned short Checksum; unsigned long SrcIP; unsigned long DstIP; //unsigned long Options_and_Padding; } IpHeader; typedef struct TCPUDPPORT{ unsigned short SrcPort; unsigned short DstPort; } TcpUdpPort; /******************************* ReadCapturedPackets Analyzes raw packets captured to file *******************************/ void ReadCapturedPackets(){ IpHeader *iphdr; TcpUdpPort *port; struct sockaddr_in SockAddr; unsigned short iphdrlen; char C; std::string strIPs, strPorts; FILE *fin; char *Buffer = (char *)malloc(MAX_PACKET_SIZE + 1); char int2str[20]; unsigned long bytesRead; long filePos; int Size, packetNumber = 1;; if (Buffer == NULL){ printf("Buffer malloc() failed in ReadCapturedPackets.\n"); exit(1); } if ((fin = fopen(m_strFileName.c_str(), "rb")) == NULL){ printf("Unable to open %s for binary read!\n", m_strFileName.c_str()); exit(1); } printf("Reading raw packet data from file...\n"); try{ while (true){ memset(Buffer, 0, MAX_PACKET_SIZE + 1); //get current postion of file pointer for use in calculating start of next packet filePos = ftell(fin); bytesRead = fread(Buffer, 1, MAX_PACKET_SIZE, fin); if (bytesRead < 1) break; iphdr = (IpHeader *)Buffer;//cast blob of bytes into an IP header iphdrlen = (iphdr->VerIHL << 4); memcpy(&C, &iphdrlen, 1); iphdrlen = (C >> 4) * 4; //20 Size = iphdr->Total_len / 256;//dunno why the value is multiplied by 256! //this little bit is so that the next read will start at the next packet filePos += Size; if (fseek(fin, filePos, SEEK_SET)){ printf("Error in fseek (see ReadCapturedPackets)!\n"); exit(1); } memset(&SockAddr, 0, sizeof(SockAddr)); SockAddr.sin_addr.s_addr = iphdr->SrcIP; strIPs = inet_ntoa(SockAddr.sin_addr); memset(&SockAddr, 0, sizeof(SockAddr)); SockAddr.sin_addr.s_addr = iphdr->DstIP; strIPs += " -> " + (std::string) inet_ntoa(SockAddr.sin_addr); switch (iphdr->Protocol){ case 1: strPorts = "ICMP"; break; case 2: strPorts = "IGMP"; break; case 6: strPorts = "TCP"; if (Size > iphdrlen){ port = (TcpUdpPort *)(Buffer + iphdrlen); sprintf(int2str, "%i", ntohs(port->SrcPort)); strPorts += " " + (std::string) int2str; sprintf(int2str, "%i", ntohs(port->DstPort)); strPorts += " -> " + (std::string) int2str; } break; case 17: strPorts = "UDP"; if (Size > iphdrlen){ sprintf(int2str, "%i", ntohs(port->SrcPort)); strPorts += " " + (std::string) int2str; sprintf(int2str, "%i", ntohs(port->DstPort)); strPorts += " -> " + (std::string) int2str; } break; default: sprintf(int2str, "%i", iphdr->Protocol); strPorts = "Protocol: " + (std::string) int2str; } printf("Packet %d: Len: %d, %s %s\n", packetNumber++, Size, strIPs.c_str(), strPorts.c_str()); } }catch (exception &e){ printf("Exception in ReadCapturedPackets: %s\n", e.what()); }catch (...){ printf("CRASH: Unknown exception in ReadCapturedPackets\n"); } fclose(fin); free(Buffer); } /******************************* ProcessPacketSTDOUT Shows data about packets as they are collected *******************************/ void ProcessPacketSTDOUT(char* Buffer, int Size){ IpHeader *iphdr; TcpUdpPort *port; struct sockaddr_in SockAddr; unsigned short iphdrlen; char C; iphdr = (IpHeader *)Buffer; iphdrlen = (iphdr->VerIHL << 4); memcpy(&C, &iphdrlen, 1); iphdrlen = (C >> 4) * 4; //20 memset(&SockAddr, 0, sizeof(SockAddr)); SockAddr.sin_addr.s_addr = iphdr->SrcIP; printf("Src: %16s ", inet_ntoa(SockAddr.sin_addr)); memset(&SockAddr, 0, sizeof(SockAddr)); SockAddr.sin_addr.s_addr = iphdr->DstIP; printf("Dest: %16s ", inet_ntoa(SockAddr.sin_addr)); switch (iphdr->Protocol){ case 1: printf(" ICMP "); break; case 2: printf(" IGMP "); break; case 6: printf(" TCP "); if (Size > iphdrlen){ port = (TcpUdpPort *)(Buffer + iphdrlen); printf("Src Port: %6i To Port: %6i ", ntohs(port->SrcPort), ntohs(port->DstPort)); } break; case 17: printf(" UDP "); if (Size > iphdrlen){ port = (TcpUdpPort *)(Buffer + iphdrlen); printf("Src Port: %6i To Port: %6i ", ntohs(port->SrcPort), ntohs(port->DstPort)); } break; default: printf("Protocol: %6i ", iphdr->Protocol); } printf("\n"); printf("\tiphdr->Checksum: %u\n", iphdr->Checksum); printf("\tiphdr->Flags_and_Frags: %u\n", iphdr->Flags_and_Frags); printf("\tiphdr->ID: %u\n", iphdr->ID); printf("\tiphdr->Tos: %u\n", iphdr->Tos); printf("\tiphdr->Total_len: %u\n", iphdr->Total_len); printf("\tiphdr->TTL: %u\n", iphdr->TTL); printf("\tiphdr->VerIHL: %u\n", iphdr->VerIHL); printf("\n"); } /******************************* StartSniffing This program dumps the raw socket data to file for later analysis *******************************/ void StartSniffing(SOCKET Sock, int NumPackets){ char *RecvBuffer = (char *)malloc(MAX_PACKET_SIZE + 1); int BytesRecv, BytesWritten; unsigned long numPackets = 0; FILE *fout; unsigned long totalPacketSize = 0; if (RecvBuffer == NULL){ printf("RecvBuffer malloc() failed in StartSniffing.\n"); exit(1); } if ((fout = fopen(m_strFileName.c_str(), "wb")) == NULL){ printf("Can't open %s! for binary write\n", m_strFileName.c_str()); exit(1); } try{ do{ memset(RecvBuffer, 0, MAX_PACKET_SIZE + 1); BytesRecv = recv(Sock, RecvBuffer, MAX_PACKET_SIZE, 0); printf("Packet %d has %d bytes\n", numPackets+1, BytesRecv); //do this if you want to see it as it happens... // ProcessPacketSTDOUT(RecvBuffer, BytesRecv); if (BytesRecv > 0){ BytesWritten = fwrite(RecvBuffer, 1, BytesRecv, fout); totalPacketSize += BytesWritten; if (BytesWritten != BytesRecv){ printf("Failure in fwrite: BytesWritten (%d) != BytesRecv (%d)\n", BytesWritten, BytesRecv); break; } }else{ printf( "recvfrom() failed.\n"); break; } numPackets++; fflush(fout); if (numPackets > NumPackets){ printf("Collected %d packets (%d total bytes), quiting\n", numPackets, totalPacketSize); break; } } while (BytesRecv > 0); }catch (exception &e){ printf("Exception in StartSniffing: %s\n", e.what()); }catch (...){ printf("CRASH: Unknown exception in StartSniffing\n"); } free(RecvBuffer); fclose(fout); } /******************************* main *******************************/ int main(){ WSAData wsaData; SOCKET Sock; struct sockaddr_in SockAddr; DWORD BytesReturned; int I = 1; if (0){//if you just want to read captured packets ReadCapturedPackets(); return 0; } try{ if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ printf("WSAStartup() failed.\n"); exit(-1); } Sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP); if (Sock == INVALID_SOCKET){ printf("socket() failed.\n"); exit(-1); } memset(&SockAddr, 0, sizeof(SockAddr)); SockAddr.sin_addr.s_addr = inet_addr(BIND2IP); SockAddr.sin_family = AF_INET; SockAddr.sin_port = 0; if (bind(Sock, (sockaddr *)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR){ printf("bind(%s) failed.\n", BIND2IP); exit(-1); } if (WSAIoctl(Sock, SIO_RCVALL, &I, sizeof(I), NULL, NULL, &BytesReturned, NULL, NULL) == SOCKET_ERROR){ printf("WSAIoctl() failed.\n"); exit(-1); } StartSniffing(Sock, 5); }catch (exception &e){ printf("Exception in Main: %s\n", e.what()); }catch (...){ printf("CRASH: Unknown exception in Main\n"); } ReadCapturedPackets(); closesocket(Sock); WSACleanup(); return 0; }