C 使用原始套接字抓包

2021-08-20 07:27:40 字數 3825 閱讀 2482

最近在研究使用原始套接字抓包,在網上找各種資料,下面是自己整理的測試**

程式設計實現主要有以下幾個步驟:

1.初始化winsock庫;

2.建立socket控制代碼;

3.繫結socket控制代碼到乙個本地位址;

4.設定該socket為接收所有資料的模式;

5.接收資料報;

6.關閉socket控制代碼,清理winsock庫.

#include #include #include #include #pragma comment(lib,"ws2_32.lib")

#pragma pack(1)

struct tcpheader

;struct udpheader

;struct ipheader

; byte servicetype; // 服務型別

word totallen; // 總長

word id; // 標識

union;

byte timetolive; // 生命期

byte protocol; // 協議

word hdrchksum; // 頭校驗和

dword srcaddr; // 源位址

dword dstaddr; // 目的位址

//byte options; // 選項

}; // test

struct netdata

};#pragma pack()

// 使用原始套接字抓取網絡卡資料報

int capturenetpackage()

// 此處必須以管理員執行vs,否則返回10013

sock = socket(af_inet, sock_raw, ipproto_ip);

if (sock == socket_error)

char strhostname[255];

iret = gethostname(strhostname, sizeof(strhostname));

if (iret != 0)

// 根據主機名取得主機位址

hostent *phostent = gethostbyname(strhostname);

sockaddr_in addrself;

addrself.sin_family = af_inet;

addrself.sin_port = htons(0);

memcpy(&addrself.sin_addr.s_un.s_addr, phostent->h_addr_list[0], phostent->h_length);

printf("self local ip addr is %s\n\n",inet_ntoa(addrself.sin_addr));

iret = bind(sock, (psockaddr)&addrself, sizeof(addrself));

if (iret != 0)

dword dwbufferlen[10] = ;

dword dwbufferinlen = 1;

dword dwbytesreturned = 0;

// 設定該socket為接收所有流經繫結的ip的網絡卡的所有資料,包括接收和傳送的資料報

iret = wsaioctl(sock, sio_rcvall, &dwbufferinlen, sizeof(dwbufferinlen),

&dwbufferlen, sizeof(dwbufferlen), &dwbytesreturned, null, null);

if (iret != 0)

sockaddr_in addrfrom;

int fromlen = sizeof(addrfrom);

time_t temp;

char strfromip[16] = , strcurtime[32] = ;

char strbuffer[1024 * 10], strdata[4096] = ;

ipheader ipdata;

tcpheader tcpdata;

udpheader udpdata;

netdata netdata;

while (true)

strcpy(strfromip, inet_ntoa(addrfrom.sin_addr));

// if(strcmp(strfromip, "192.168.0.104") == 0

// || strcmp(strfromip, "192.168.0.1") == 0

// || strcmp(strfromip, "192.168.0.103") == 0)

if(strcmp(strfromip, "192.168.0.104") != 0)

// 處理ip包頭資料

memcpy(&ipdata, strbuffer, sizeof(ipdata));

byte protocol = 0;

sockaddr_in addrsrc, addrdst;

char strsrcip[16] = , strdstip[16] = ;

addrsrc.sin_addr.s_un.s_addr = ipdata.srcaddr;

addrdst.sin_addr.s_un.s_addr = ipdata.dstaddr;

strcpy(strsrcip, inet_ntoa(addrsrc.sin_addr));

strcpy(strdstip, inet_ntoa(addrdst.sin_addr));

if(strcmp(strsrcip, "192.168.0.104") != 0 || strcmp(strdstip, "192.168.0.104") != 0)

// udp協議

if(ipdata.protocol == ipproto_udp)

memcpy(&udpdata, strbuffer + sizeof(ipdata), sizeof(udpdata));

int isrcport = ntohs(udpdata.srcport);

int idstport = ntohs(udpdata.dstport);

memcpy(&netdata, strbuffer + sizeof(ipdata) + sizeof(udpdata), sizeof(netdata));

} // tcp協議

else if(ipdata.protocol == ipproto_tcp)

memcpy(&tcpdata, strbuffer + sizeof(ipdata), sizeof(tcpdata));

int isrcport = ntohs(tcpdata.srcport);

int idstport = ntohs(tcpdata.dstport);

memcpy(&netdata, strbuffer + sizeof(ipdata) + sizeof(tcpdata), sizeof(netdata));

} else{}

time(&temp);

strftime(strcurtime, sizeof(strcurtime), "%y-%m-%d %h:%m:%s",localtime(&temp) );

printf("time:%s length:%d from %s\n", strcurtime, iret, strfromip);

}tag_end:

if(sock != socket_error)

} if (wsacleanup() == socket_error)

return 0;

}

原始套接字實現抓包,分析tcp ip報文

模擬抓包,並且解析報文。這邊先貼上 和部分資料。詳細解釋以後再寫 1.乙太網幀 2.ip報文 3.tcp報文 4.udp報文 解析出mac位址 void dump mac const char header,char buf,int start printf n 解析出乙太網幀型別 unsigned...

包分析(原始套接字七)

緊接上節 decodeippack 函式完成包的解析 ip包解析 int decodeippack char buf,int ibufsize return true 上述程式解析ip包型別後又分別呼叫decodetcppack decodeu ack decodeicmppack 解析相應的tcp...

golang使用原始套接字構造UDP包

這裡先看ip頭結構 其中16位總長度包括ip頭長度和資料的長度,8位協議填寫17,因為udp協議型別為17。這裡要說明一下ip頭中的首部校驗,這個值只校驗ip頭部,不包含資料。這裡給出校驗演算法,ip頭和udp頭中使用的校驗演算法是一樣的。func checksum msg byte uint16 ...