Windows下C语言实现原始socket抓包

原始Socket抓包

0x01. 源码

#include 
#include 
#include  
#include 
#include 
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"IPHLPAPI.lib")//获取本地网络信息的开发接口

int main ()
{
	//初始化
	WSADATA wsadata;
	SOCKET SnifferSocket;
	hostent *pHostent;//指向主机名的指针
	SOCKADDR_IN sock;
	char Packet[60000];
	int retval;
	if (WSAStartup (MAKEWORD (2, 2), &wsadata) != 0) {
		printf ("WSAStartup failed!\n");
		system ("pause");
		return 1;
	}
	//创建原始socket
	SnifferSocket = socket (AF_INET, SOCK_RAW, IPPROTO_IP);
	if (SnifferSocket == INVALID_SOCKET) {
		printf ("Socket failed with error %d\n", WSAGetLastError ());//这里要必须用管理员身份运行,不然创建不了socket
		system ("pause");
		return 0;
	}
	//绑定到一个本地IP地址
	pHostent = gethostbyname ("SPWPUN");//这里填自己的主机名
	printf ("本机可用的IP地址:\n");
	for (int i = 0; pHostent->h_addr_list[i]; i++)
	{
		printf ("IP address %d:%s\n", i + 1, inet_ntoa (*(struct in_addr*)pHostent->h_addr_list[i]));
	}
	system ("pause");
	sock.sin_family = AF_INET;
	sock.sin_port = htons (80);
	memcpy (&sock.sin_addr.S_un.S_addr, pHostent->h_addr_list[3], pHostent->h_length);//选择第4个IP,有效
	retval = bind (SnifferSocket, (const sockaddr *)&sock, sizeof (sock));
	if (retval == SOCKET_ERROR) {
		printf ("Bind error!\n");
		system ("pause");
		return 0;
	}
	//设置网卡为混杂模式
	u_long InOutParam = 1;
	retval = ioctlsocket (SnifferSocket, SIO_RCVALL, &InOutParam);
	//开始循环接受数据
	while (true)
	{
		ZeroMemory (Packet, sizeof (Packet));
		retval = recv (SnifferSocket, Packet, sizeof (Packet), 0);//retval是接受数据的返回的字节数
		if (retval == 0 || retval == SOCKET_ERROR) {
			printf ("发生错误!\n");
			break;
		}
		else {
			printf ("抓包成功,抓到的数据包的大小为%d个字节。\n", retval);
		}
	}
	//关闭socket
	closesocket (SnifferSocket);
	WSACleanup ();
	system ("pause");
	return 0;
}

0x02. 说明

  • 这段代码只是简单实现了原始socket的抓包而已,并未涉及到具体的包的数据的分析,只是简单显示出抓到的包的大小而已。
  • 调试运行的时候,必须要使用管理员权限运行,这是原始socket的一个缺点。
  • 原始socket也不能获取链路层信息,不能获取arp包(在Linux下可以);也没有内核级的过滤机制,只能由程序员自己来过滤,既复杂又很慢,在千兆网上很容易丢包。
  • 在选择网络接口的时候需要根据自己的电脑的实际情况来确定,因为有一些IP的网络地址是虚拟机等的地址,实际上是不可用的,在虚拟机为开启的情况下。

0x03. 代码结构

1.创建原始socket
2.获取一个需要监听网络接口的ip地址,并绑定(必须要显示绑定)
3.设置网卡为混杂模式
4.开始循环接受数据
5.关闭socket

0x04. 后感

  • 这一次,我体会到了按着思路走写代码的好处,有种一气呵成的感觉,再加油吧!

你可能感兴趣的:(网络编程)