天天看點

攔截網絡資料包(SOCK_RAW)

#include <winsock2.h>

#include <ws2tcpip.h>

#include <iostream>

using namespace std;

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

#define BUFFER_SIZE 1024

#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)

typedef struct _TCP //應用層,傳輸層層

{

WORD SrcPort; // 源端口

WORD DstPort; // 目的端口

DWORD SeqNum; // 順序号

DWORD AckNum; // 确認号

BYTE DataOff; // TCP頭長

BYTE Flags; // 标志(URG、ACK等)

WORD Window; // 視窗大小

WORD Chksum; // 校驗和

WORD UrgPtr; // 緊急指針

} TCP;

typedef TCP *LPTCP;

typedef TCP UNALIGNED * ULPTCP;

typedef struct _IP //傳輸層,網絡層

{

union

{

BYTE Version; // 版本

BYTE HdrLen; // IHL

};

BYTE ServiceType; // 服務類型

WORD TotalLen; // 總長

WORD ID; // 辨別

union

{

WORD Flags; // 标志

WORD FragOff; // 分段偏移

};

BYTE TimeToLive; // 生命期

BYTE Protocol; // 協定

WORD HdrChksum; // 頭校驗和

DWORD SrcAddr; // 源位址

DWORD DstAddr; // 目的位址

BYTE Options; // 選項

} IP;

typedef IP * LPIP;

typedef IP UNALIGNED * ULPIP;

#define PROTOCOL_STRING_ICMP_TXT "ICMP"

#define PROTOCOL_STRING_TCP_TXT "TCP"

#define PROTOCOL_STRING_UDP_TXT "UDP"

#define PROTOCOL_STRING_SPX_TXT "SPX"

#define PROTOCOL_STRING_NCP_TXT "NCP"

#define PROTOCOL_STRING_UNKNOW_TXT "UNKNOW"

char* GetProtocolTxt(int Protocol)

{

switch (Protocol)

{

case IPPROTO_ICMP : //1

return PROTOCOL_STRING_ICMP_TXT;

case IPPROTO_TCP : //6

return PROTOCOL_STRING_TCP_TXT;

case IPPROTO_UDP : //17

return PROTOCOL_STRING_UDP_TXT;

default:

return PROTOCOL_STRING_UNKNOW_TXT;

}

}

//*.cpp

void main()

{

WSADATA wsadata;

// 檢查 Winsock 版本号,WSAData為WSADATA結構對象

int erro=WSAStartup(MAKEWORD(1, 1), &wsadata);

if(erro!=0)

{

cout<<"初始化失敗"<<endl;

return ;

}

// 建立原始套接字

SOCKET sock;

sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);

// 設定IP頭操作選項,其中flag 設定為ture,親自對IP頭進行處理

BOOL flag=TRUE;

setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag));

// 擷取本機名

char LocalName[512];

gethostname((char*)LocalName, sizeof(LocalName)-1);

// 擷取本地 IP 位址

hostent * pHost;

pHost=gethostbyname((char*)LocalName);

// 填充SOCKADDR_IN結構

SOCKADDR_IN addr_in;

addr_in.sin_addr= *(in_addr *)pHost->h_addr;//h_addr_list[0]; //IP h_addr定義的宏

addr_in.sin_family = AF_INET;

addr_in.sin_port = htons(1004);

// 把原始套接字sock 綁定到本地網卡位址上

bind(sock, (PSOCKADDR)&addr_in, sizeof(addr_in));

// dwValue為輸入輸出參數,為1時執行,0時取消

DWORD dwValue = 1;

// 設定 SOCK_RAW 為SIO_RCVALL,以便接收所有的IP包。其中SIO_RCVALL

// 的定義為: #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)

ioctlsocket(sock, SIO_RCVALL, &dwValue); //将網卡設定為混合模式

char RecvBuf[BUFFER_SIZE];

IP ip;

TCP tcp;

while (true)

{

// 接收原始資料包資訊

int ret = recv(sock, RecvBuf, BUFFER_SIZE, 0);

if (ret !=0)

{

// 對資料包進行分析,并輸出分析結果

ip = *(IP*)RecvBuf;

tcp = *(TCP*)(RecvBuf + ip.HdrLen);

cout<<"協定"<<GetProtocolTxt(ip.Protocol)<<endl;

cout<<"IP源位址"<<inet_ntoa(*(in_addr*)&ip.SrcAddr)<<endl;

cout<<"IP目标位址"<<inet_ntoa(*(in_addr*)&ip.DstAddr)<<endl;

cout<<"TCP源端口号"<<tcp.SrcPort<<endl;

cout<<"TCP目标端口号"<<tcp.DstPort<<endl;

cout<<"資料包長度"<<ntohs(ip.TotalLen)<<endl;

//cout<<(char *)(RecvBuf+sizeof(ip)+sizeof(tcp));

//cout<<(char *)(RecvBuf+28)<<endl;

}

}

}

轉自:http://hi.baidu.com/gm123092267/blog/item/93a4583a5de63af8b311c7ce.html

繼續閱讀