網絡嗅探器:把網卡設置成混雜模式,并可實現對網絡上傳輸的數據包的捕獲與分析。
原理:
通常的套接字程序只能響應與自己MAC地址相匹配的 或者是 廣播形式發出的數據幀,對于其他形式的數據幀網絡接口采取的動作是直接丟棄
為了使網卡接收所有經過他的封包,要將其設置成混雜模式,通過原始套接字來實現。
設置混雜模式:
創建原始套接字,
綁定到一個明確的本地地址,
向套接字發送SIO_RCVALL控制命令,
接收所有的IP包
代碼實現步驟:
1 創建原始套接字
2 綁定到明確地址
3 這是SIO_RCVALL控制代碼
4 進入循環,調用recv函數接收經過本地網卡的IP封包。
主程序代碼如下:
void main(){ //創建原始套接字 SOCKET sRaw = socket(AF_INET,SOCK_RAW,IPPROTO_IP); //獲取本地IP地址 char szHostName[56]; SOCKADDR_IN addr_in; struct hostent *pHost; gethostname(szHostName,56); if((pHost=gethostbyname((char*)szHostName))==NULL) return; //套接字綁定 addr_in.sin_family = AF_INET; addr_in.sin_port = htons(0); memcpy(&addr_in.sin_addr.S_un.S_addr,pHost->h_addr_list[0],pHost->h_length); printf("Binding to interface:%sn",::inet_ntoa(addr_in.sin_addr)); if(bind(sRaw,(sockaddr*)&addr_in,sizeof(addr_in))==SOCKET_ERROR) return; //設置SIO_RECVALL控制代碼 DWORD dwValue = 1; if(ioctlsocket(sRaw,SIO_RCVALL,&dwValue)!=0) return; //開始接收封包 char buff[1024]; int nRet; while(true) { nRet = recv(sRaw,buff,1024,0); if(nRet>0) { DecodeIPPacket(buff); } } closesocket(sRaw);}
程序接收到IP封包后,調用自定義的DecodeIPPacket進行解包。取出封包中的協議頭,向用戶打印出協議信息。
解析IP頭代碼:
void DecodeIPPacket(char *pData){ IPHeader *pIPHdr = (IPHeader*)pData; in_addr source,dest; char szSourceIp[32],szDestIp[32]; printf("nn------------------------------------------------n"); //從IP頭中取出源IP和目的IP source.S_un.S_addr = pIPHdr->ipSource; dest.S_un.S_addr = pIPhdr->ipDestination; strcpy(szSourceIp,::inet_ntoa(source)); strcpy(szDestIp,::inet_ntoa(dest)); printf(" %s->%sn",szSourceIp,szDestIp); //IP長度 int nHeaderLen = (pIPHdr->iphVerLen & 0xf)*sizeof(ULONG); switch(pIPHdr->ipProtocol) { case IPPROTO_TCP: DecodeTCPPacket(pData+nHeaderLen); break; case IPPROTO_UDP: break; case IPPROTO_ICMP: break; }}
解析TCP頭代碼如下:取出端口號,輸出
void DecodeTCPPacket(char *pData){ TCPHeader &pTCPHdr = (TCPHeader*)pData; printf("Port:%d->%dn",ntohs(pTCPHdr->sourcePort),ntohs(pTCOHdr->destinationPort)); switch(::ntohs(pTCPHdr->destinationPort)) { case 21: break; case 80: break; case 8080: break; }}
VS下完整代碼:
initsock.h:
#include <winsock2.h>#pragma comment(lib, "WS2_32") // 鏈接到WS2_32.libclass CInitSock {public: CInitSock(BYTE minorVer = 2, BYTE majorVer = 2) { // 初始化WS2_32.dll WSADATA wsaData; WORD sockVersion = MAKEWORD(minorVer, majorVer); if(::WSAStartup(sockVersion, &wsaData) != 0) { exit(0); } } ~CInitSock() { ::WSACleanup(); }};
protoinfo.h:
//////////////////////////////////////////////////// protoinfo.h文件/*定義協議格式定義協議中使用的宏 */#ifndef __PROTOINFO_H__#define __PROTOINFO_H__#define ETHERTYPE_IP 0x0800#define ETHERTYPE_ARP 0x0806typedef struct _ETHeader // 14字節的以太頭{ UCHAR dhost[6]; // 目的MAC地址destination mac address UCHAR shost[6]; // 源MAC地址source mac address USHORT type; // 下層協議類型,如IP(ETHERTYPE_IP)、ARP(ETHERTYPE_ARP)等} ETHeader, *PETHeader;#define ARPHRD_ETHER 1// ARP協議opcodes#define ARPOP_REQUEST 1 // ARP 請求 #define ARPOP_REPLY 2 // ARP 響應typedef struct _ARPHeader // 28字節的ARP頭{ USHORT hrd; // 硬件地址空間,以太網中為ARPHRD_ETHER USHORT eth_type; // 以太網類型,ETHERTYPE_IP ?? UCHAR maclen; // MAC地址的長度,為6 UCHAR iplen; // IP地址的長度,為4 USHORT opcode; // 操作代碼,ARPOP_REQUEST為請求,ARPOP_REPLY為響應 UCHAR smac[6]; // 源MAC地址 UCHAR saddr[4]; // 源IP地址 UCHAR dmac[6]; // 目的MAC地址 UCHAR daddr[4]; // 目的IP地址} ARPHeader, *PARPHeader;// 協議#define PROTO_ICMP 1#define PROTO_IGMP 2#define PROTO_TCP 6#define PROTO_UDP 17typedef struct _IPHeader // 20字節的IP頭{ UCHAR iphVerLen; // 版本號和頭長度(各占4位) UCHAR ipTOS; // 服務類型 USHORT ipLength; // 封包總長度,即整個IP報的長度 USHORT ipID; // 封包標識,惟一標識發送的每一個數據報 USHORT ipFlags; // 標志 UCHAR ipTTL; // 生存時間,就是TTL UCHAR ipProtocol; // 協議,可能是TCP、UDP、ICMP等 USHORT ipChecksum; // 校驗和 ULONG ipSource; // 源IP地址 ULONG ipDestination; // 目標IP地址} IPHeader, *PIPHeader; // 定義TCP標志#define TCP_FIN 0x01#define TCP_SYN 0x02#define TCP_RST 0x04#define TCP_PSH 0x08#define TCP_ACK 0x10#define TCP_URG 0x20#define TCP_ACE 0x40#define TCP_CWR 0x80typedef struct _TCPHeader // 20字節的TCP頭{ USHORT sourcePort; // 16位源端口號 USHORT destinationPort; // 16位目的端口號 ULONG sequenceNumber; // 32位序列號 ULONG acknowledgeNumber; // 32位確認號 UCHAR dataoffset; // 高4位表示數據偏移 UCHAR flags; // 6位標志位 //FIN - 0x01 //SYN - 0x02 //RST - 0x04 //PUSH- 0x08 //ACK- 0x10 //URG- 0x20 //ACE- 0x40 //CWR- 0x80 USHORT windows; // 16位窗口大小 USHORT checksum; // 16位校驗和 USHORT urgentPointer; // 16位緊急數據偏移量 } TCPHeader, *PTCPHeader;typedef struct _UDPHeader{ USHORT sourcePort; // 源端口號 USHORT destinationPort;// 目的端口號 USHORT len; // 封包長度 USHORT checksum; // 校驗和} UDPHeader, *PUDPHeader;#endif // __PROTOINFO_H__
#include "../common/initsock.h"#include "../common/protoinfo.h" #include <stdio.h>#include <mstcpip.h>#pragma comment(lib, "Advapi32.lib")CInitSock theSock;void DecodeTCPPacket(char *pData){ TCPHeader *pTCPHdr = (TCPHeader *)pData; printf(" Port: %d -> %d n", ntohs(pTCPHdr->sourcePort), ntohs(pTCPHdr->destinationPort)); // 下面還可以根據目的端口號進一步解析應用層協議 switch(::ntohs(pTCPHdr->destinationPort)) { case 21: break; case 80: case 8080: break; }}void DecodeIPPacket(char *pData){ IPHeader *pIPHdr = (IPHeader*)pData; in_addr source, dest; char szSourceIp[32], szDestIp[32]; printf("nn-------------------------------n"); // 從IP頭中取出源IP地址和目的IP地址 source.S_un.S_addr = pIPHdr->ipSource; dest.S_un.S_addr = pIPHdr->ipDestination; strcpy(szSourceIp, ::inet_ntoa(source)); strcpy(szDestIp, ::inet_ntoa(dest)); printf(" %s -> %s n", szSourceIp, szDestIp); // IP頭長度 int nHeaderLen = (pIPHdr->iphVerLen & 0xf) * sizeof(ULONG); switch(pIPHdr->ipProtocol) { case IPPROTO_TCP: // TCP協議 DecodeTCPPacket(pData + nHeaderLen); break; case IPPROTO_UDP: break; case IPPROTO_ICMP: break; }}void main(){ // 創建原始套節字 SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_IP); // 獲取本地IP地址 char szHostName[56]; SOCKADDR_IN addr_in; struct hostent *pHost; gethostname(szHostName, 56); if((pHost = gethostbyname((char*)szHostName)) == NULL) return ; // 在調用ioctl之前,套節字必須綁定 addr_in.sin_family = AF_INET; addr_in.sin_port = htons(0); memcpy(&addr_in.sin_addr.S_un.S_addr, pHost->h_addr_list[0], pHost->h_length); printf(" Binding to interface : %s n", ::inet_ntoa(addr_in.sin_addr)); if(bind(sRaw, (PSOCKADDR)&addr_in, sizeof(addr_in)) == SOCKET_ERROR) return; // 設置SIO_RCVALL控制代碼,以便接收所有的IP包 DWORD dwValue = 1; if(ioctlsocket(sRaw, SIO_RCVALL, &dwValue) != 0) return ; // 開始接收封包 char buff[1024]; int nRet; while(TRUE) { nRet = recv(sRaw, buff, 1024, 0); if(nRet > 0) { DecodeIPPacket(buff); } } closesocket(sRaw);}
運行結果
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
iphone6如何啟用hi Siri?首先打開蘋果手機上的設置功能選項,下拉界面找到【通用】選項。點擊設置菜單中的【通用】選項,進入通用界面,在這里可以找到siri選項。點擊【siri】選項進入siri設置界面,默認不開啟?;瑒佑疫叺陌粹o打開該功能,會彈出一個下拉窗口。選擇[啟用siri]選項。點擊【啟用siri】選項,此時siri界面出現允許Hey siri功能選項,默認不開啟?;瑒佑益I打開...
簡述分類變量與數值變量的根本區別?區別:1。數值變量是指其值可以采用某些列的數字。這些值對于加法、減法、平均和其他運算都有意義。2. 分類變量對上述操作沒有意義。C語言是不是只能使用數據類型的關鍵字來定義變量?為什么?感謝您的邀請。大多數情況下,C語言只能使用數據類型關鍵字來定義變量,例如:int、long int、double void等。但是可以使用許多其他類型的關鍵字,例如:1,const:...
現在市面上有沒有除了百度以外的靠譜搜索引擎?書籍、視頻、各種教程等。我們一般都喜歡在百度的在線盤上尋找資源。其實,“西林街尋”的資源也非常豐富。整個網絡資源的垂直搜索引擎是在線磁盤搜索的產物。視頻、音樂、文章、購物、信息熱點等搜索引擎,一鍵切換,超級高效簡單,讓您無需在多個網站之間來回切換。集成多個電子書資源平臺,無需注冊,免費下載。對電子書愛好者來說是個好消息。新電影上映后,我們可以花錢去電影院...