Windows下利用原始套接字实现的一个抓包程序Demo

来源:互联网 发布:js数组转字符串 join 编辑:程序博客网 时间:2024/06/07 01:07

早就学过了套接字编程,但是原始套接字还没用过。最近听了网络安全老师的课,心血来潮,写了个抓包程序Demo,把代码分享给大家,感兴趣的可以看看。引用一句网络安全老师的话:“你们要本着技术的心态去实践,哎,一部分人,写着写着就成黑客了”。


#define _CRT_SECURE_NO_WARNINGS #include <stdio.h>#include <WinSock2.h>#include <WS2tcpip.h>#include <stdlib.h>#include <Windows.h>#include <string.h>#pragma comment(lib,"Ws2_32.lib")#define SOURCE_PORT 7234#define MAX_RECEIVEBYTE 255#define MAX_ADDR_LEN 32#define SIO_RCVALL  (IOC_IN|IOC_VENDOR|1)//定义网卡为混杂模式typedef struct ip_hdr//定义IP首部{unsigned char h_verlen;//4位首部长度,4位IP版本号unsigned char tos;//8位服务类型TOSunsigned short tatal_len;//16位总长度unsigned short ident;//16位标示unsigned short frag_and_flags;//偏移量和3位标志位unsigned char ttl;//8位生存时间TTLunsigned char proto;//8位协议(TCP,UDP或其他)unsigned short checksum;//16位IP首部检验和unsigned int sourceIP;//32位源IP地址unsigned int destIP;//32位目的IP地址}IPHEADER;typedef struct tsd_hdr//定义TCP伪首部{unsigned long saddr;//源地址unsigned long daddr;//目的地址char mbz;char ptcl;//协议类型unsigned short tcpl;//TCP长度}PSDHEADER;typedef struct tcp_hdr//定义TCP首部{unsigned short sport;//16位源端口unsigned short dport;//16位目的端口unsigned int seq;//32位序列号unsigned int ack;//32位确认号unsigned char lenres;//4位首部长度/6位保留字unsigned char flag;//6位标志位unsigned short win;//16位窗口大小unsigned short sum;//16位检验和unsigned short urp;//16位紧急数据偏移量}TCPHEADER;typedef struct udp_hdr//定义UDP首部{unsigned short sport;//16位源端口unsigned short dport;//16位目的端口unsigned short len;//UDP 长度unsigned short cksum;//检查和}UDPHEADER;typedef struct icmp_hdr//定义ICMP首部{unsigned short sport;unsigned short dport;unsigned char type;unsigned char code;unsigned short cksum;unsigned short id;unsigned short seq;unsigned long timestamp;}ICMPHEADER;int main(int argc, char **argv){SOCKET sock;WSADATA wsd;char recvBuf[65535] = { 0 };char temp[65535] = { 0 };DWORD dwBytesRet;int pCount = 0;unsigned int optval = 1;unsigned char* dataip = nullptr;unsigned char* datatcp = nullptr;unsigned char* dataudp = nullptr;unsigned char* dataicmp = nullptr;int lentcp, lenudp, lenicmp, lenip;char TcpFlag[6] = { 'F', 'S', 'R', 'A', 'U' };//定义TCP标志位WSAStartup(MAKEWORD(2, 1), &wsd);if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == SOCKET_ERROR)//创建一个原始套接字{exit(0);}char FAR name[MAXBYTE];gethostname(name, MAXBYTE);struct hostent FAR* pHostent;pHostent = (struct hostent*)malloc(sizeof(struct hostent));pHostent = gethostbyname(name);SOCKADDR_IN sa;sa.sin_family = AF_INET;sa.sin_port = htons(1);//原始套接字没有端口的概念,所以这个值随便设置memcpy(&sa.sin_addr,pHostent->h_addr_list[0],pHostent->h_length);//设置本机地址bind(sock, (SOCKADDR*)&sa, sizeof(sa));//绑定if (WSAGetLastError() == 10013){exit(0);}//设置网卡为混杂模式,也叫泛听模式。可以侦听经过的所有的包。WSAIoctl(sock, SIO_RCVALL, &optval, sizeof(optval), nullptr, 0, &dwBytesRet,nullptr,nullptr);UDPHEADER * pUdpheader;//UDP头结构体指针IPHEADER * pIpheader;//IP头结构体指针TCPHEADER * pTcpheader;//TCP头结构体指针ICMPHEADER * pIcmpheader;//ICMP头结构体指针char szSourceIP[MAX_ADDR_LEN], szDestIP[MAX_ADDR_LEN];//源IP和目的IPSOCKADDR_IN saSource, saDest;//源地址结构体,目的地址结构体//设置各种头指针pIpheader = (IPHEADER*)recvBuf;pTcpheader = (TCPHEADER*)(recvBuf + sizeof(IPHEADER));pUdpheader = (UDPHEADER*)(recvBuf + sizeof(IPHEADER));pIcmpheader = (ICMPHEADER*)(recvBuf + sizeof(IPHEADER));int iIphLen = sizeof(unsigned long)*(pIpheader->h_verlen & 0x0f);while (1){memset(recvBuf, 0, sizeof(recvBuf));//清空缓冲区recv(sock, recvBuf, sizeof(recvBuf), 0);//接收包//获得源地址和目的地址saSource.sin_addr.s_addr = pIpheader->sourceIP;strncpy(szSourceIP, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN);saDest.sin_addr.s_addr = pIpheader->destIP;strncpy(szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN);//计算各种包的长度(只有判断是否是该包后才有意义,先计算出来)lenip = ntohs(pIpheader->tatal_len);lentcp = ntohs(pIpheader->tatal_len) - (sizeof(IPHEADER) + sizeof(TCPHEADER));lenudp = ntohs(pIpheader->tatal_len) - (sizeof(IPHEADER) + sizeof(UDPHEADER));lenicmp = ntohs(pIpheader->tatal_len) - (sizeof(IPHEADER) + sizeof(ICMPHEADER));//判断是否是TCP包if (pIpheader->proto == IPPROTO_TCP&&lentcp != 0){pCount++;//计数加一dataip = (unsigned char *)recvBuf;datatcp = (unsigned char *)recvBuf + sizeof(IPHEADER) + sizeof(TCPHEADER);system("cls");printf("\n#################数据包[%i]=%d字节数据#############", pCount, lentcp);printf("\n**********IP协议头部***********");printf("\n标示:%i", ntohs(pIpheader->ident));printf("\n总长度:%i", ntohs(pIpheader->tatal_len));printf("\n偏移量:%i", ntohs(pIpheader->frag_and_flags));printf("\n生存时间:%d",pIpheader->ttl);printf("\n服务类型:%d",pIpheader->tos);printf("\n协议类型:%d",pIpheader->proto);printf("\n检验和:%i", ntohs(pIpheader->checksum));printf("\n源IP:%s", szSourceIP);printf("\n目的IP:%s", szDestIP);printf("\n**********TCP协议头部***********");printf("\n源端口:%i", ntohs(pTcpheader->sport));printf("\n目的端口:%i", ntohs(pTcpheader->dport));printf("\n序列号:%i", ntohs(pTcpheader->seq));printf("\n应答号:%i", ntohs(pTcpheader->ack));printf("\n检验和:%i", ntohs(pTcpheader->sum));printf("\n标志位:");unsigned char FlagMask = 1;int k;//打印标志位for (k = 0; k < 6; k++){if ((pTcpheader->flag)&FlagMask)printf("%c", TcpFlag[k]);elseprintf(" ");FlagMask = FlagMask << 1;}//打印出前100个字节的十六进制数据printf("\n数据:\n");for (int i = 0; i < 100; i++){printf("%x", datatcp[i]);}}//+++++++++++++++++++++++++++++//在这里可以加入其它封包的判断和处理//+++++++++++++++++++++++++++++}}

运行效果




0 0
原创粉丝点击