网络嗅探器和网络抓包软件的简单实现

协议分析课的大作业,简单实现抓包软件,网络嗅探器

通过查阅网上的博客和资料,再以自己的理解整理之后,写了这篇小博客

希望对计算机系有同样作业,或是感兴趣的同学有所帮助

程序可能还不够完善,但基本功能已经实现


抓包软件的工作原理、使用的技术、实现的过程

抓包器也叫嗅探器,是一种网络通信程序,通过对网卡的编程即可完成简单的实现。网络编程通常是基于socket套接字进行的,但正常的套接字程序只能响应与自己地址相匹配或是广播的数据帧,无法收取其他的数据包。而嗅探器程序可以从网卡接收所有经过它的数据包,即使该数据包的目的地址不是自己网卡的地址。

实现抓包软件需要将网卡置为混杂模式,使用SOCK_ROW,并用WSAIoctl函数进行操作选项设置,然后通过bind函数将SOCK_ROW与本机网卡绑定。

 

抓包软件具体实现过程

1.加载socket编程所需库  2.建立原始套接字SOCK_RAW  3.获取本机名称

4.获取本机可用IP地址  5.将原始套接字与本机IP地址绑定  6.将网卡置于混杂模式,用WSAIoctl设置SOCK_RAW选项  7.创建线程或使用循环,接收数据 8.对数据进行简单分析

 

   

IP数据包首部格式如下:

 

|--------|--------|----------------|--------------------------------|
  | Ver (4位) | IHL(4)  |Type of service(8) |     Total length(16)     |
 |--------|--------|----------------|--------------------------------|
  | Identification (16)|   Flags(3)   |     Fragment offset(13)    |
  |--------|--------|----------------|--------------------------------|
  | Time to live(8) |  Protocol(8) |     Header checksum (16)   |
 |--------|--------|----------------|--------------------------------|
  |             Source address(32)              |
  |--------|--------|----------------|--------------------------------|
  |            Destination address(32)           |
 |--------|--------|----------------|--------------------------------|
  |            Option + Padding              |
  |--------|--------|----------------|--------------------------------|
  |                Data                |

 |--------|--------|----------------|--------------------------------|


具体代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include "packdef.h"

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

using namespace std;

int main()
{
	//1.加载库
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested,&wsaData);
	if (err != 0) {

        printf("WSAStartup failed with error: %d\n", err);
        return 1;
    }
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {

        printf("Could not find a usable version of Winsock.dll\n");
        WSACleanup();
        return 1;
    }
	else
       printf("The Winsock 2.2 dll was found okay\n");

	//建立原始套接字
	SOCKET sniffersock;
	sniffersock = socket(AF_INET,SOCK_RAW/*原始套接字*/,IPPROTO_IP);
	if(INVALID_SOCKET == sniffersock)
	{
		closesocket(sniffersock);
		WSACleanup();
	}
	
	//获取本机名称
	char hostname[DEFAULT_NAMELEN];
	if(SOCKET_ERROR == gethostname(hostname,DEFAULT_NAMELEN))
	{
		cout<<"获取本机名失败"<h_addr_list[i] != 0)
	{
		myAddr.s_addr = *(u_long*)local->h_addr_list[i++];
		cout<>num;
	SOCKADDR_IN localAddr;
	localAddr.sin_family = AF_INET;
	localAddr.sin_port = 0;
	memset(&localAddr.sin_addr.S_un.S_addr,0,sizeof(localAddr.sin_addr.S_un.S_addr));
	memcpy(&localAddr.sin_addr.S_un.S_addr,local->h_addr_list[num - 1],
		sizeof(localAddr.sin_addr.S_un.S_addr));
	
	if(SOCKET_ERROR == bind(sniffersock,(const sockaddr*)&localAddr,sizeof(localAddr)))
	{
		closesocket(sniffersock);
		WSACleanup();
		return 1;
	}
	
	//将网卡置于混杂模式,接收所有数据
	u_long sioarg = 1;
	DWORD dwValue=0;
	if(SOCKET_ERROR == WSAIoctl(sniffersock,SIO_RCVALL,&sioarg,sizeof(sioarg),NULL,0,&dwValue,NULL,NULL))
	{
		closesocket(sniffersock);
		return 1;
	}

	//开始接受数据  
    cout<<"开始接受数据"< 0)
		{
			IPHEAD iphead = *(IPHEAD*)buf;
			cout<<"版本号:"<<(iphead.version_hl>>4)<

 运行结果:

网络嗅探器和网络抓包软件的简单实现_第1张图片


你可能感兴趣的:(C++,网络编程,协议分析,网络嗅探器,网络抓包,C++)