windows抓包程序

生成RAW Socket

SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if(INVALID_SOCKET == s)
{
	printf("socket(AF_INET, SOCK_RAW, IPPROTO_IP) == INVALID_SOCKET, ErrorCode=%d", GetLastError());
	return false;
}

RAW Socket接收到的数据包保留原始的IP包头。

SOCK_RAW能操作底层传输,所以它们能用于造成安全威胁的恶意目的,故在Windows2000及以后操作系统中只有Administrator组成员可以创建RAW socket。

RAW Socket发送和接收的所有包一概视为无连接的数据报。


绑定本地地址

sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.4.111");
addr.sin_port = htons(4445);

if(SOCKET_ERROR == bind(s, (sockaddr*)&addr, sizeof(addr)))
{
	printf("bind == SOCKET_ERROR, ErrorCode=%d
", GetLastError());
	return 0;
}

必须进行地址绑定否则设置SIO_RCVALL时出10022错误。

socket绑定IP后将仅接收通过该网卡的IP数据包。它不会接收到流经其他网卡的IP数据包。

有多个网卡,则需循环处理,一次绑定一个,不能使用htonl(INADDR_ANY),否则失败。


设置SIO_RCVALL控制码

RCVALL_VALUE emRcvallValue = RCVALL_IPLEVEL;
DWORD dwBytesReturned = 0;
if(SOCKET_ERROR == WSAIoctl(s, SIO_RCVALL, &emRcvallValue, sizeof(emRcvallValue), NULL, 0, &dwBytesReturned, NULL, NULL))
{
	printf("WSAIoctl == SOCKET_ERROR, ErrorCode=%d", GetLastError());
	return 0;
}
SIO_RCVALL控制码将使一个socket能够接收经过该网卡的所有IP数据包。

RCVALL_IPLEVEL为SIO_RCVALL控制码的选项值,类型为RCVALL_VALUE

typedef enum {
    RCVALL_OFF             = 0,
    RCVALL_ON              = 1,
    RCVALL_SOCKETLEVELONLY = 2,
    RCVALL_IPLEVEL         = 3,
} RCVALL_VALUE, *PRCVALL_VALUE;

RCVALL_IPLEVEL在IP层抓包,不会设置网卡为杂乱模式避免了可能的错误,网卡仍旧仅接收发给自己的数据包或广播数据包。该选项仅影响IP层对数据包的处理过程。

不允许先将该控制码作用于一个网卡而后作用于另一个网卡。在把该控制码用于其他网卡前必选先关闭现有socket的SIO_RCVALL控制码。(因电脑只有一个网卡故未得到验证)


抓包

char cBuffer[100*1024] = {0};
int iLenRecv = recv(s, cBuffer, 100*1024, 0);
if(SOCKET_ERROR == iLenRecv)
{
	printf("recv == SOCKET_ERROR, ErrorCode=%d", GetLastError());
	return false;
}
if(0 == iLenRecv)
{
	printf("recv == SOCKET_ERROR, Connection Closed");
	break;
}

cBuffer[iLenRecv] = '';

妥善关闭

/*关闭SIO_RCVALL*/
emRcvallValue = RCVALL_OFF;
if(SOCKET_ERROR == WSAIoctl(s, SIO_RCVALL, &emRcvallValue, sizeof(emRcvallValue), NULL, 0, &dwBytesReturned, NULL, NULL))
{
	printf("WSAIoctl == SOCKET_ERROR, ErrorCode=%d
", GetLastError());
	return false;
}

/*关闭socket*/
closesocket(s);


完整代码

/*生成RAW socket*/
SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if(INVALID_SOCKET == s)
{
	WriteToLog("LogicModule::GetProcNetworkFlow: socket == INVALID_SOCKET, ErrorCode=%d", GetLastError());
	return false;
}

/*初始化sockaddr*/
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.4.111");
addr.sin_port = htons(4444);

/*绑定网卡地址*/
if(SOCKET_ERROR == bind(s, (sockaddr*)&addr, sizeof(addr)))
{
	printf("bind == SOCKET_ERROR, ErrorCode=%d", GetLastError());
	return false;
}

/*设置socket模式*/
RCVALL_VALUE emRcvallValue = RCVALL_IPLEVEL;
DWORD dwBytesReturned = 0;
if(SOCKET_ERROR == WSAIoctl(s, SIO_RCVALL, &emRcvallValue, sizeof(emRcvallValue), NULL, 0, &dwBytesReturned, NULL, NULL))
{
	printf("WSAIoctl == SOCKET_ERROR, ErrorCode=%d", GetLastError());
	return false;
}

/*抓包*/
char cBuffer[100*1024] = {0};
int iLenRecv = recv(s, cBuffer, 100*1024, 0);
if(SOCKET_ERROR == iLenRecv)
{
	printf("recv == SOCKET_ERROR, ErrorCode=%d", GetLastError());
	return false;
}
if(0 == iLenRecv)
{
	printf("recv == SOCKET_ERROR, Connection Closed");
	break;
}

cBuffer[iLenRecv] = '';

/*关闭SIO_RCVALL*/
emRcvallValue = RCVALL_OFF;
if(SOCKET_ERROR == WSAIoctl(s, SIO_RCVALL, &emRcvallValue, sizeof(emRcvallValue), NULL, 0, &dwBytesReturned, NULL, NULL))
{
	printf("WSAIoctl == SOCKET_ERROR, ErrorCode=%d
", GetLastError());
	return false;
}

/*关闭socket*/
closesocket(s);


原文地址:https://www.cnblogs.com/chaikefusibushiji/p/7475602.html