VC++编程实现网络嗅探器
课程设计--基于C#的网络嗅探器的设计和实现

网络与信息安全课程设计网络嗅探器的设计和实现学院:计算机科学与技术班级:网络工程08-1班姓名:学号:指导老师:目录一、什么是嗅探器--------------------------------------------1二、嗅探器的作用---------------------------------------------1三、网络嗅探器的原理-----------------------------------------1四、反嗅探技术----------------------------------------------7五、网络嗅探器的设计-----------------------------------------8六、结语---------------------------------------------------14参考书目--------------------------------------------------14网络嗅探器的实际与实现一、什么是嗅探器嗅探器,可以理解为一个安装在计算机上的窃听设备它可以用来窃听计算机在网络上所产生的众多的信息。
简单一点解释:一部电话的窃听装置, 可以用来窃听双方通话的内容,而计算机网络嗅探器则可以窃听计算机程序在网络上发送和接收到的数据。
可是,计算机直接所传送的数据,事实上是大量的二进制数据。
因此, 一个网络窃听程序必须也使用特定的网络协议来分解嗅探到的数据,嗅探器也就必须能够识别出那个协议对应于这个数据片断,只有这样才能够进行正确的解码。
计算机的嗅探器比起电话窃听器,有他独特的优势:很多的计算机网络采用的是“共享媒体"。
也就是说,你不必中断他的通讯,并且配置特别的线路,再安装嗅探器,你几乎可以在任何连接着的网络上直接窃听到你同一掩码范围内的计算机网络数据。
我们称这种窃听方式为“基于混杂模式的嗅探”(promiscuous mode)。
《网络嗅探器》课程设计报告

《网络与信息安全技术》课程报告课题名称:网络嗅探器提交报告时间:2010年12月17日各成员的工作量划分表网络嗅探器专业组号指导老师[摘要]随着网络技术的飞速发展,网络安全问题越来越被人重视。
嗅探技术作为网络安全攻防中最基础的技术,既可以用于获取网络中传输的大量敏感信息,也可以用于网络管理。
通过获取网络数据包的流向和内容等信息,可以进行网络安全分析和网络威胁应对。
因此对网络嗅探器的研究具有重要意义。
本课程设计通过分析网络上常用的嗅探器软件,在了解其功能和原理的基础上,以VC为开发平台,使用Windows环境下的网络数据包捕获开发库WinPcap,按照软件工程的思想进行设计并实现了一个网络嗅探工具。
该嗅探工具的总体架构划分为5部分,分别是最底层的数据缓存和数据访问,中间层的数据捕获,协议过滤,协议分析和最顶层的图形画用户界面。
本嗅探器工具完成了数据包捕获及分析,协议过滤的主要功能,实现了对网络协议,源IP 地址,目标IP地址及端口号等信息的显示,使得程序能够比较全面地分析出相关信息以供用户参考决策。
关键词:网络嗅探;WinPcap编程接口;数据包;网络协议;多线程(中文摘要在150字左右。
摘要正文尽量用纯文字叙述。
用五号宋体字。
姓名与摘要正文之间空二行。
关键词与摘要之间不空行。
“摘要”这两个字加粗)关键词:入侵检测系统;感应器;分析器;分布式入侵检测系统模型Network snifferMajor: software engineeringGroup Number: 29[Abstract] With the rapid development of network technology, network security is increasingly being attention. Sniffing network security technology as the most basic offensive and defensive techniques, both used to obtain a large number of network transmission of sensitive information can also be used for network management. Access to network packets through the flow and content and other information, can be network security threat analysis and response networks. Therefore, the network sniffer is of great significance.The course is designed by analyzing the commonly used network sniffer software, to understand the functions and principles, based on the VC as a development platform, using the Windows environment, the development of network packet capture library WinPcap, according to software engineering design And implementation of a network sniffer tool. The overall structure of the sniffer is divided into five parts, namely, the bottom of the data caching and data access, middle layer of the data capture, protocol filtering, protocol analysis and top graphic art user interface.The completed tool sniffer packet capture and analysis of data, protocol filtering of the main functions, the realization of network protocol, source IP address, destination IP address and port number and other information display, makes the program out to a more comprehensive analysis of relevant information Decision-making for user reference[Keyword]network sniffer; WinPcap programming interface; data packet; network protocol; multi-threaded《网络与信息安全》课程报告 0第一章绪论 (5)1.1背景 (5)1.2国内外现状 (6)1.3本文工作 (6)第二章相关技术 (7)2.1嗅探原理 (7)2.2捕获机制 (8)2.3Winpcap功能介绍 (9)2.4 Winpcap体系结构 (9)第三章研究内容描述 (11)第四章测试环境和过程描述 (12)4.1 程序调试 (13)4.2 程序测试 (14)第五章小结 (18)5.1成果 (18)5.2展望 (19)第一章绪论嗅探器是一种利用计算机网络接口监视网络数据运行,截获网络数据的工具,可用于网络管理,网络协议分析以及网络安全等众多方面。
网络编程课程设计-网路嗅探器

┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊目录1 设计目的 (2)2 设计内容 (2)3 程序流程 (2)4 设计步骤 (4)5 设计总结 (11)┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊1 设计目的网络通信课程设计是网络工程专业的大型作业课。
是培养计算机领域从事网络技术及应用工作的高级工程技术人才的必修课程。
本课的主要任务是使学生队所学的《计算机网络》知识从实践上有一个较清晰的了解。
对当前计算机网络的主要种类和常用的网络协议有更进一步的深入认识。
学会计算机网络设计和日常管理及维护的最基本方法。
网络编程简单的理解就两台计算机相互通讯数据,通过使用套接字来达到进程通信目的编程就是网络编程。
网络编程最主要工作就是在发送端把信息通过规定好的协议进行组包,在接收端按照规定好的协议把包进行解析,从而提取出相应的信息,达到通信的目的。
中间最主要的就是数据包的组装,数据包的过滤,数据包的捕获,数据包的分析,当然最后再做一些处理。
本次实验运用C++的网络编程相关知识,通过学习了解了TCP和UDP协议的基本知识和SOCKET编程的基本概念,完成tracert程序,实现ping功能和路由追踪功能。
2 设计内容一、学习实践要求1.对计算机网络的物理构成有清晰的了解;2.理解计算机网络体系结构的内涵;3.熟悉计算机网络的分类及常用的网络协议;4.基于掌握计算机网络软件的开发方法;5.具备管理计算机网络的基本知识及技能。
二、模块功能(1)pin功能:发送ICMP数据包到计算机,如有返回,显示相应时间等。
(2)路由探测功能:依次ping途经的路由器或网关设备,依次显示途经路由器的响应时间。
3 程序流程┊┊┊┊┊┊Array┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊图1 流程图4 设计步骤一、程序运行结果相关截图图2 运行结果┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊图3 运行结果图4 运行结果┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊图5 运行结果二、程序源代码#include <iostream>#include <winsock2.h>#include <ws2tcpip.h>using namespace std;#pragma comment(lib, "Ws2_32.lib")//IP报头typedef struct{unsigned char hdr_len:4; //4位头部长度 unsigned char version:4; //4位版本号unsigned char tos; //8位服务类型 unsigned short total_len; //16位总长度┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊ unsigned short identifier; //16位标识符unsigned short frag_and_flags; //3位标志加13位片偏移unsigned char ttl; //8位生存时间unsigned char protocol; //8位上层协议号unsigned short checksum; //16位校验和unsigned long sourceIP; //32位源IP地址unsigned long destIP; //32位目的IP地址} IP_HEADER;//ICMP报头typedef struct{BYTE type; //8位类型字段BYTE code; //8位代码字段USHORT cksum; //16位校验和USHORT id; //16位标识符USHORT seq; //16位序列号} ICMP_HEADER;//报文解码结构typedef struct{USHORT usSeqNo; //序列号DWORD dwRoundTripTime; //往返时间in_addr dwIPaddr; //返回报文的IP地址}DECODE_RESULT;//计算网际校验和函数USHORT checksum(USHORT *pBuf,int iSize){unsigned long cksum=0;while(iSize>1){cksum+=*pBuf++;iSize-=sizeof(USHORT);}if(iSize){cksum+=*(UCHAR *)pBuf;}cksum=(cksum>>16)+(cksum&0xffff);cksum+=(cksum>>16);return (USHORT)(~cksum);}//对数据包进行解码BOOL DecodeIcmpResponse(char * pBuf,int iPacketSize,DECODE_RESULT &DecodeResult,BYTE ICMP_ECHO_REPLY,BYTE ICMP_TIMEOUT){//检查数据报大小的合法性┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊ IP_HEADER* pIpHdr = (IP_HEADER*)pBuf;int iIpHdrLen = pIpHdr->hdr_len * 4;if (iPacketSize < (int)(iIpHdrLen+sizeof(ICMP_HEADER)))return FALSE;//根据ICMP报文类型提取ID字段和序列号字段ICMP_HEADER *pIcmpHdr=(ICMP_HEADER *)(pBuf+iIpHdrLen);USHORT usID,usSquNo;if(pIcmpHdr->type==ICMP_ECHO_REPLY) //ICMP回显应答报文{usID=pIcmpHdr->id; //报文IDusSquNo=pIcmpHdr->seq; //报文序列号}else if(pIcmpHdr->type==ICMP_TIMEOUT) //ICMP超时差错报文{char * pInnerIpHdr=pBuf+iIpHdrLen+sizeof(ICMP_HEADER); //载荷中的IP头int iInnerIPHdrLen=((IP_HEADER *)pInnerIpHdr)->hdr_len*4; //载荷中的IP头长ICMP_HEADER * pInnerIcmpHdr=(ICMP_HEADER *)(pInnerIpHdr+iInnerIPHdrLen);//载荷中的ICMP头usID=pInnerIcmpHdr->id; //报文IDusSquNo=pInnerIcmpHdr->seq; //序列号}else{return false;}//检查ID和序列号以确定收到期待数据报if(usID!=(USHORT)GetCurrentProcessId()||usSquNo!=SeqNo){return false;}//记录IP地址并计算往返时间DecodeResult.dwIPaddr.s_addr=pIpHdr->sourceIP;DecodeResult.dwRoundTripTime=GetTickCount()-DecodeResult.dwRoundTripTime;//处理正确收到的ICMP数据报if (pIcmpHdr->type == ICMP_ECHO_REPLY ||pIcmpHdr->type == ICMP_TIMEOUT){//输出往返时间信息if(DecodeResult.dwRoundTripTime)cout<<" "<<DecodeResult.dwRoundTripTime<<"ms"<<flush;elsecout<<" "<<"<1ms"<<flush;}return true;}┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊void main(){//初始化Windows sockets网络环境WSADATA wsa;WSAStartup(MAKEWORD(2,2),&wsa);char IpAddress[255];cout<<"请输入一个IP地址或域名:";cin>>IpAddress;//得到IP地址u_long ulDestIP=inet_addr(IpAddress);//转换不成功时按域名解析if(ulDestIP==INADDR_NONE){hostent * pHostent=gethostbyname(IpAddress);if(pHostent){ulDestIP=(*(in_addr*)pHostent->h_addr).s_addr;}else{cout<<"输入的IP地址或域名无效!"<<endl;WSACleanup();return;}}cout<<"Tracing roote to "<<IpAddress<<" with a maximum of 30 hops.\n"<<endl;//填充目地端socket地址sockaddr_in destSockAddr;ZeroMemory(&destSockAddr,sizeof(sockaddr_in));destSockAddr.sin_family=AF_INET;destSockAddr.sin_addr.s_addr=ulDestIP;//创建原始套接字SOCKETsockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);//超时时间int iTimeout=3000;//接收超时setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char *)&iTimeout,sizeof(iTimeout)); //发送超时setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char *)&iTimeout,sizeof(iTimeout));//构造ICMP回显请求消息,并以TTL递增的顺序发送报文//ICMP类型字段const BYTE ICMP_ECHO_REQUEST=8; //请求回显const BYTE ICMP_ECHO_REPLY=0; //回显应答const BYTE ICMP_TIMEOUT=11; //传输超时┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊ //其他常量定义const int DEF_ICMP_DATA_SIZE=32; //ICMP报文默认数据字段长度const int MAX_ICMP_PACKET_SIZE=1024;//ICMP报文最大长度(包括报头)const DWORD DEF_ICMP_TIMEOUT=3000; //回显应答超时时间const int DEF_MAX_HOP=30; //最大跳站数//填充ICMP报文中每次发送时不变的字段char IcmpSendBuf[sizeof(ICMP_HEADER)+DEF_ICMP_DATA_SIZE]; //发送缓冲区memset(IcmpSendBuf, 0, sizeof(IcmpSendBuf)); //初始化发送缓冲区 char IcmpRecvBuf[MAX_ICMP_PACKET_SIZE]; //接收缓冲区memset(IcmpRecvBuf, 0, sizeof(IcmpRecvBuf)); //初始化接收缓冲区ICMP_HEADER * pIcmpHeader=(ICMP_HEADER*)IcmpSendBuf;pIcmpHeader->type=ICMP_ECHO_REQUEST; //类型为请求回显pIcmpHeader->code=0; //代码字段为0pIcmpHeader->id=(USHORT)GetCurrentProcessId(); //ID字段为当前进程号memset(IcmpSendBuf+sizeof(ICMP_HEADER),'E',DEF_ICMP_DATA_SIZE);//数据字段USHORT usSeqNo=0; //ICMP报文序列号int iTTL=1; //TTL初始值为1BOOL bReachDestHost=FALSE; //循环退出标志int iMaxHot=DEF_MAX_HOP; //循环的最大次数DECODE_RESULT DecodeResult; //传递给报文解码函数的结构化参数while(!bReachDestHost&&iMaxHot--){//设置IP报头的TTL字段setsockopt(sockRaw,IPPROTO_IP,IP_TTL,(char *)&iTTL,sizeof(iTTL));cout<<iTTL<<flush; //输出当前序号//填充ICMP报文中每次发送变化的字段((ICMP_HEADER *)IcmpSendBuf)->cksum=0; //校验和先置为0((ICMP_HEADER *)IcmpSendBuf)->seq=htons(usSeqNo++); //填充序列号((ICMP_HEADER *)IcmpSendBuf)->cksum=checksum((USHORT*)IcmpSendBuf,sizeof(ICMP_HEADER)+DEF_ICMP_DATA_SIZE); //计算校验和//记录序列号和当前时间SeqNo=((ICMP_HEADER*)IcmpSendBuf)->seq; //当前序号DecodeResult.dwRoundTripTime=GetTickCount(); //当前时间//发送TCP回显请求信息sendto(sockRaw,IcmpSendBuf,sizeof(IcmpSendBuf),0,(sockaddr*)&destSockAddr,sizeof(de stSockAddr));//接收ICMP差错报文并进行解析处理sockaddr_in from; //对端socket地址int iFromLen=sizeof(from); //地址结构大小int iReadDataLen; //接收数据长度while(1){//接收数据┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊iReadDataLen=recvfrom(sockRaw,IcmpRecvBuf,MAX_ICMP_PACKET_SIZE,0,(sockaddr*)&from,& iFromLen);if(iReadDataLen!=SOCKET_ERROR) //有数据到达{//对数据包进行解码if(DecodeIcmpResponse(IcmpRecvBuf,iReadDataLen,DecodeResult,ICMP_ECHO_REPLY,ICMP_TI MEOUT)){//到达目的地,退出循环if(DecodeResult.dwIPaddr.s_addr==destSockAddr.sin_addr.s_addr) bReachDestHost=true;//输出IP地址cout<<'\t'<<inet_ntoa(DecodeResult.dwIPaddr)<<endl;break;}}else if(WSAGetLastError()==WSAETIMEDOUT) //接收超时,输出*号{cout<<" *"<<'\t'<<"Request timed out."<<endl;break;}else{break;}}iTTL++; //递增TTL值}}5 设计总结通过这次课程设计,让我受益匪浅,使我掌握了网络通信编程的基本思想。
网络嗅探器的制作PPT课件

2021
12
二、界面的简易设计
2021
13
双击左侧的Resource>MySniffer resources> IDD_MYSNIFFER_DIALOG,就可以进入图形化界 面设计
控件表
2021
14
静态文本
要用到的控件简介
编辑框
按钮
列表控件
2021
15
创建一个静态文本,并右键点击它,选中属性, 将ID修改为“IDC_STATIC_SELECT_DEVICE”, 标题修改为“选择网络适配器序号:”
49
到文件的最下面,添加对回调函数 packet_handler的函数定义:
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { }
2021
50
找到OnButtonStart函数,为“开始”按钮添 加动作响应:
else
{
m_str="No description available";
m_device.SetItemText(i-1,2,m_str);
}
}
2021
42
按F5调试运行,并单击“网络适配器”你会发 现第一个列表中显示出了当前主机上的网络适 配器的相关信息
2021
43
回到OnButtonGetDevice函数,并添加如下所 示代码:
2021
25
选中IDC_LIST_PACK,并点击NM_CLICK,再点 击ADD FUNCTION,添加事件响应函数
2021
26
基于C#的网络嗅探器设计与实现文献综述

基于C#的网络嗅探器设计与实现文献综述文献综述基于C#的网络嗅探器设计与实现一、前言部分写作目的随着网络技术的发展和网络应用的普及,越来越多的信息资源放在了互联网上,网络的安全性和可靠性显得越发重要。
因此,对于能够分析、诊断网络,测试网络性能与安全性的工具软件的需求也越来越迫切。
网络嗅探器就是一种用于网络分析的好工具,且它具有两面性,攻击者可以用它来监听网络中数据,达到非法获得信息的目的,网络管理者可以通过使用嗅探器捕获网络中传输的数据包并对其进行分析,分析结果可供网络安全分析之用。
于是编写一个网络嗅探器就极其重要了。
有关概念、综述范围网络嗅探器是一种网络分析工具,用于监听流经网络接口的信息,网络管理员可以用它来分析数据包,而黑客可以用它来窃听数据。
网卡的混杂模式:处于该模式的网卡能接受所有通过它的数据流,无论是什么格式,什么地址。
网卡的混杂模式是为网络分析提供的[11]。
Winpcap:它是一个基于Win32的开源的包捕获驱动构架,它弥补了windows系统内核本身提供很少包捕获接口的劣势,可以直接捕获到链路层的数据帧,而且基于它开发的监听程序具有很好的移植性。
它包含了一个内核级的数据包过滤器NPF,一个底层动态链接 Packet.dll 和一个高层的独立于系统的库Wpcap.dll。
NPF 模块过滤数据包, 将数据包不做任何改动的传递给用户。
Packet.dll 模块提供了Win32 平台下的捕获包的驱动接口,基于Packet.dll编写的程序可以不经过重新编译就在各种Win32 平台下实现捕获数据包[4]。
网络监听:一种监视网络状态、数据流程以及网络上信息传输的管理工具,它可以将网络界面设定成监听模式,并且可以截获网络上所传输的信息。
也就是说,当黑客登录网络主机并取得超级用户权限后,若要登录其它主机,使用网络监听便可以有效地截获网络上的数据,这是黑客使用最好的方法。
但是网络监听只能应用于连接同一网段的主机,通常被用来获取用户密码等[13]。
基于C#的网络嗅探器设计与实现【开题报告】

毕业设计开题报告计算机科学与技术基于C#的网络嗅探器设计与实现一、选题的背景、意义1.历史背景网络嗅探器,它与当前的网络生活有很大的关系,一些网络管理员普遍采用它,也有很多黑客通过使用它来获得他们想要的信息资料。
与电话线路不同,计算机网络是共享通信通道的,这就意味着计算机能够接收到发给其他计算机的信息。
捕获在网络中传输的数据信息就称为“窃听” [3]。
在内部网上,黑客想要迅速获得大量的账号,最有效的手段是使用嗅探程序。
这种方法要求运行嗅探器程序的主机和被监听的主机必须在同一个以太网段上。
以太网窃听则是对以太网设备上传送的数据包进行侦听,来探测感兴趣的包。
如果发现符合条件的包,就把它存下来[1]。
网络嗅探器通常运行在路由器或有路由功能的主机,这样就能对大量的数据进行监控。
信息革命正在改造我们的生活,这场革命早在工业化进程中就开始孕育。
20世纪50年代前的电报电话等基础通信技术和计算机技术的出现,为20世纪60年代计算机联网实验提供了最初的条件,20世纪70年代半导体微电子技术的飞跃以及数字技术的成熟为计算机网络走出军事的封锁环境、研究所和校园的象牙塔奠定了技术基础。
美国著名的未来学家阿尔温深刻地指出:“电脑网络的建立与普及将彻底改变人类的生存及生活模式,而控制与掌握网络的人就是人类未来的主宰,谁掌握了信息,控制了网络,谁就拥有整个世界[2]。
”为了发觉信息革命的巨大潜能,美国率先提出了信息高速公路的构思,提倡实施国家信息基础设施,西方发达国家紧跟着提出全球信息基础设施的提倡。
我国也大力推动信息化,普通老百姓在家里上Internet 周游世界已经成为今天的社会现实。
人们热情高涨地推动着信息化,期盼着信息化带来的理想成真[6]。
信息技术一个面促进了生产力的发展,提高了生产的效率,但同时对社会的稳定、生产秩序、经济基础的危险也在加大。
从历史上看,每次生产力的飞跃往往带来更为残冷的战争,使人类遭受更大的痛苦。
5-编程实现简单的网络嗅探器

2.5也可以只分析一种协议,比如IEEE802.3协议、IP协议、TCP协议、或UDP协议等。如果每层协议都分析,可获加分。
2.6显示分析结果
3.开发工具不限,建议使用VC++
设计内容与步骤
1.学习原始套接字编程的基本机制;
2.学习对数据包进行协议分析的基本方法。
计算机网络课程设计任务书
设计题目
编程实现简单的网络嗅探器——协议分析
已知技术参数和设计要求
1.利用原始套接字实现简单的网络嗅探器。
2.系统功能包括:
2.1原始套接字与网卡邦定,并接收流经网卡的所有数据包;
2.2对数据包进行分析以获得源IP地址和目的IP地址;
2.3对数据包进行分析以获得运输层协议类型、源端口号和目的端口号;
3.设计简单网络嗅探器的基本框架。
4.设计并实现简单的网络嗅探器。
5.课程设计任务说明书
设计工作计划与进度安排
1.原始套接字编程的基本机制2小时
2.对数据包进行网络嗅探器框架结构设计4小时
5.简单网络嗅探器设计与实现16小时
6.课程设计说明书12小时
利用VC++6.0实现基于嗅探器防火墙系统模型的设计

4 )记录通 过 防火 墙 的信息 内容和 活动 ; 5 )对 网络 攻 击进 行检 测和 告警 。 此外 , C T P的序列 号 、 确认 号 、P校验 和 分割 偏 I
转 发 到 另 外 的链 路 上 去 , 将
网络 上 的 流 量 通 过 相 应 的 网
网络编程界面 Scel okt
含 了数 据包 的各 种 信 息 , 协 议 和 服务 、 地址 、 如 源 源
端 口、 目的地址 、 目的端 口和帧 的格 式等 等 。通过对
与 Sce 的关 系 okt
然后 将 符 合 通 过 条 件 的 报 文 图 1 防火墙 应用 程 序 从 相 应 的 网 络 接 口送 出 , 而
结构 如 图 1 所示 。
jl ‘j j j 坐 j 业 坐 j ● j 业
数 据包 报头 的分 析来 获取 数据 封包 信 息是 网络封 包
捕 获 中要实 现 的重要 功能 。 我们 根据 嗅 探器原 理 , 流 经 网络 的数 据包 进 对
j j 曲 } jl 业 jl j j } _ j 业 j
d t a k g r n lz d Th e in sh meo h ie l a d t ek y p o rmm ig s cin t aap c a ea ea ay e . ed sg c e ft ef wal n h e r g a r n eto swi vC+ + h 6 0a egv n i eal tcn b a e sasmpeta hn d lfrt ed sg e fn t r e u i . r ie n d ti .I a etk n a i l e c ig mo e o h e in ro ewo ks c rt v
ARP探测C语言实现

ARP探测C语言实现ARP(Address Resolution Protocol,地址解析协议)是用于将IP 地址转换为物理地址(MAC地址)的协议。
在网络中,ARP请求和应答消息的交互可以帮助主机发现目标主机的物理地址。
下面是一个基于C语言的简单ARP探测实现。
ARP请求阶段:1.创建原始套接字,用于发送和接收网络数据包。
```cint sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);if (sockfd < 0)perror("Failed to create socket.");return -1;```2.设置套接字选项,允许发送与接收IP首部。
```cif (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &enable, sizeof(enable)) < 0)perror("Failed to set socket options.");return -1;}```3.设置目标主机的IP地址。
```cstruct in_addr dest_ip;if (inet_aton(target_ip, &dest_ip) == 0)printf("Invalid IP address specified.");return -1;```4.构造ARP请求包。
```cstruct arphdr arp_header;memset(&arp_header, 0, sizeof(arp_header));arp_header.ar_hrd = htons(ARPHRD_ETHER); // 以太网地址类型arp_header.ar_pro = htons(ETH_P_IP); // IP地址类型arp_header.ar_hln = ETH_ALEN; // MAC地址长度arp_header.ar_pln = sizeof(in_addr_t); // IP地址长度arp_header.ar_op = htons(ARPOP_REQUEST); // ARP请求操作码struct ether_arp ether_arp_pkt;memset(ðer_arp_pkt, 0, sizeof(ether_arp_pkt));//设置以太网帧的源地址和目标地址memcpy(ether_arp_pkt.arp_sha, mac_addr, ETH_ALEN); memset(ether_arp_pkt.arp_tha, 0xff, ETH_ALEN);//设置以太网帧的协议类型ether_arp_pkt.ea_hdr.ar_hrd = arp_header.ar_hrd;ether_arp_pkt.ea_hdr.ar_pro = arp_header.ar_pro;ether_arp_pkt.ea_hdr.ar_hln = arp_header.ar_hln;ether_arp_pkt.ea_hdr.ar_pln = arp_header.ar_pln;ether_arp_pkt.ea_hdr.ar_op = arp_header.ar_op;//设置ARP请求的源IP地址和目标IP地址ether_arp_pkt.arp_spa = inet_addr(sender_ip);ether_arp_pkt.arp_tpa = dest_ip.s_addr;//构造完成的ARP请求数据包memcpy(buffer, ðer_arp_pkt, sizeof(ether_arp_pkt)); ```5.设置套接字的目标地址。
一个简易网络嗅探器的实现源代码

摘要:本文介绍一个用C语言和网络数据包分析开发工具实现的简易网络Sniffer。
要害词:网络;数据包;Sniffer引言目前,已经有不少的Sniff工具软件,如Windows环境下,最富盛名的工具是Netxray和Sniffer pro,用它们在Windows环境下抓包来分析,非常方便。
在UNIX环境下如Sniffit,Snoop,Tcpdump,Dsniff 等都是比较常见的。
这里介绍一个用C语言和网络数据包和分析开发工具libpcap及winpcap实现的简易网络Sniffer。
网络嗅探器程序框图首先给出流程如图1所示。
图1 流程图网络嗅探器程序实现在c环境下编程,源码如下:/* June 2nd,2002* Project for graduation qualification By Bby Team 19 */ #include <stdio.h>#include <conio.h>//必须加路径,必须把头文件packet32.h包含进去#include "..\..\Include\packet32.h"#include "..\..\Include\ntddndis.h"#define Max_Num_Adapter 10// Prototypes原形//发包void PrintPackets(LPPACKET lpPacket);//设备列表char AdapterList[Max_Num_Adapter][1024];// 主程序开始int main(){//define a pointer to an ADAPTER strUCture设备指针LPADAPTER lpAdapter = 0;//define a pointer to a PACKET structure包指针LPPACKET lpPacket;int i;DWord dwErrorCode;DWORD dwVersion;DWORD dwWindowsMajorVersion;//Unicode strings (WinNT)WCHAR AdapterName[8192]; //网络适配器设备列表WCHAR *temp,*temp1;//ASCII strings (Win9x)char AdapterNamea[8192]; //网络适配器设备列表char *tempa,*temp1a;int AdapterNum=0,Open;ULONG AdapterLength;char buffer[256000]; // 容纳来自驱动器的数据的缓冲区struct bpf_stat stat;// 获得本机网卡名AdapterLength=4096;printf("Packet.dll test application. Library version:%s\n", PacketGetVersion());printf("Adapters installed:\n");i=0;下面这段代码是用来在不同版本下得到网络适配器名:Win9x 和WinNT中的网卡名称是分别用ASCII和UNICODE实现的,所以首先要得到本地操作系统的版本号:dwVersion=GetVersion();dwWindowsMajorVersion= (DWORD)(LOBYTE(LOWORD(dwVersion)));这里首先用到的Packet.dll函数是PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize,通常它是与驱动程序通信并被调用的第一个函数,它将返回的用户本地系统中安装的网络适配器的名字放在缓冲区pStr中;BufferSize是缓冲区的长度:if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4)){//是Windows NT// 找不到设备列表if(PacketGetAdapterNames(AdapterName,&AdapterLength)==FALSE){printf("Unable to retrieve the list of the adapters!\n");return -1;}// 找到设备列表temp=AdapterName;temp1=AdapterName;while ((*temp!='\0')(*(temp-1)!='\0')){if (*temp=='\0'){memcpy(AdapterList[i],temp1,(temp-temp1)*2);temp1=temp+1;i++;}temp++;}// 显示适配器列表AdapterNum=i;for (i=0;i<AdapterNum;i++)wprintf(L"\n%d- %s\n",i+1,AdapterList[i]);printf("\n");}else //否则就是windows 9x,获取适配器名的方法同WinNT下{if(PacketGetAdapterNames(AdapterNamea,&AdapterLength)==FALSE){ printf("Unable to retrieve the list of the adapters!\n");return -1;}tempa=AdapterNamea;temp1a=AdapterNamea;while ((*tempa!='\0')(*(tempa-1)!='\0')){if (*tempa=='\0'){memcpy(AdapterList[i],temp1a,tempa-temp1a);temp1a=tempa+1;i++;}tempa++;}AdapterNum=i;for (i=0;i<AdapterNum;i++)printf("\n%d- %s\n",i+1,AdapterList[i]);printf("\n");}下面这段代码就是让用户选择监听的网络适配器号:// 选择设备do{printf("Select the number of the adapter to open : ");scanf("%d",&Open);if (Open>AdapterNum)printf("\nThe number must be smaller than %d",AdapterNum);} while (Open>AdapterNum);然后,将所选择的设备打开,这里可以设置为“混杂”模式打开,也可以是“直接”模式打开。
网络嗅探器源代码

#include <winsock2.h> /*windows socket的头文件,系统定义的*/ #include <windows.h>#include <ws2tcpip.h>#include <stdio.h>#include <stdlib.h>#pragma comment(lib,"ws2_32.lib") /*链接API相关连的Ws2_32.lib静态库*/#define MAX_HOSTNAME_LAN 255#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)#define MAX_ADDR_LEN 16struct ipheader {unsigned char ip_hl:4; /*header length(报头长度)*/unsigned char ip_v:4; /*version(版本)*/unsigned char ip_tos; /*type os service服务类型*/unsigned short int ip_len; /*total length (总长度)*/unsigned short int ip_id; /*identification (标识符)*/unsigned short int ip_off; /*fragment offset field(段移位域)*/unsigned char ip_ttl; /*time to live (生存时间)*/unsigned char ip_p; /*protocol(协议)*/unsigned short int ip_sum; /*checksum(校验和)*/unsigned int ip_src; /*source address(源地址)*/unsigned int ip_dst; /*destination address(目的地址)*/}; /* total ip header length: 20 bytes (=160 bits) */typedef struct tcpheader {unsigned short int sport; /*source port (源端口号)*/unsigned short int dport; /*destination port(目的端口号)*/unsigned int th_seq; /*sequence number(包的序列号)*/unsigned int th_ack; /*acknowledgement number(确认应答号)*/ unsigned char th_x:4; /*unused(未使用)*/unsigned char th_off:4; /*data offset(数据偏移量)*/unsigned char Flags; /*标志全*/unsigned short int th_win; /*windows(窗口)*/unsigned short int th_sum; /*checksum(校验和)*/unsigned short int th_urp; /*urgent pointer(紧急指针)*/}TCP_HDR;typedef struct udphdr {unsigned short sport; /*source port(源端口号)*/unsigned short dport; /*destination port(目的端口号)*/unsigned short len; /*udp length(udp长度)*/unsigned short cksum; /*udp checksum(udp校验和)*/}UDP_HDR;void main(){SOCKET sock;WSADATA wsd;DWORD dwBytesRet;unsigned int optval = 1;unsigned char *dataudp,*datatcp;int i,pCount=0,lentcp, lenudp;SOCKADDR_IN sa,saSource, saDest;struct hostent FAR * pHostent;char FAR name[MAX_HOSTNAME_LAN];char szSourceIP[MAX_ADDR_LEN], szDestIP[MAX_ADDR_LEN],RecvBuf[65535] = {0};struct udphdr *pUdpheader;struct ipheader *pIpheader;struct tcpheader *pTcpheader;WSAStartup(MAKEWORD(2,1),&wsd);if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP))==SOCKET_ERROR) exit(1);gethostname(name, MAX_HOSTNAME_LAN);pHostent = gethostbyname(name);sa.sin_family = AF_INET;sa.sin_port = htons(6000);memcpy(&sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length);bind(sock, (SOCKADDR *)&sa, sizeof(sa)); /*bind()设定自己主机的IP地址和端口号*/if ((WSAGetLastError())==10013)exit(1);WSAIoctl(sock, SIO_RCVALL, &optval, sizeof(optval), NULL, 0, &dwBytesRet, NULL, NULL);pIpheader = (struct ipheader *)RecvBuf;pTcpheader = (struct tcpheader *)(RecvBuf+ sizeof(struct ipheader ));pUdpheader = (struct udphdr *) (RecvBuf+ sizeof(struct ipheader ));while (1){memset(RecvBuf, 0, sizeof(RecvBuf));recv(sock, RecvBuf, sizeof(RecvBuf), 0);saSource.sin_addr.s_addr = pIpheader->ip_src;strncpy(szSourceIP, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN);saDest.sin_addr.s_addr = pIpheader->ip_dst;strncpy(szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN);lentcp =(ntohs(pIpheader->ip_len)-(sizeof(struct ipheader)+sizeof(struct tcpheader)));lenudp =(ntohs(pIpheader->ip_len)-(sizeof(struct ipheader)+sizeof(struct udphdr)));if((pIpheader->ip_p)==IPPROTO_TCP&&lentcp!=0){printf("*******************************************\n");pCount++;datatcp=(unsigned char *) RecvBuf+sizeof(struct ipheader)+sizeof(struct tcpheader);printf("-TCP-\n");printf("\n目的IP地址:%s\n",szDestIP);printf("\n目的端口:%i\n",ntohs(pTcpheader->dport));printf("datatcp address->%x\n",datatcp);printf("size of ipheader->%i\n",sizeof(struct ipheader));printf("size of tcpheader->%i\n",sizeof(struct tcpheader));printf("size of the hole packet->%i\n",ntohs(pIpheader->ip_len));printf("\nchar Packet%i [%i]=\"",pCount,lentcp-1);for (i=0;i<lentcp;i++){printf("\\x%.2x",*(datatcp+i));if (i%10==0)printf("\"\n\"");}printf("\";\n\n\n");for (i=0;i<lentcp;i++){if( *(datatcp+i)<=127&&*(datatcp+i)>=20)printf("%c",*(datatcp+i));elseprintf(".");}printf("\n\n*******************************************\n");}if((pIpheader->ip_p)==IPPROTO_UDP&&lentcp!=0){pCount++;dataudp=(unsigned char *) RecvBuf+sizeof(struct ipheader)+sizeof(struct udphdr);printf("-UDP-\n");printf("\n目的IP地址:%s\n",szDestIP);printf("\n目的端口:%d\n",ntohs(pTcpheader->dport));printf("UDP数据地址:%x\n",dataudp);printf("IP头部长度:%i\n",sizeof(struct ipheader));printf("UDP头部长度:%i\n",sizeof(struct udphdr));printf("包的大小:%i\n",ntohs(pIpheader->ip_len));printf("\nchar Packet%i [%i]=\"",pCount,lenudp-1);for (i=0;i<lenudp;i++){printf("\\x%.2x",*(dataudp+i));if (i%10==0)printf("\"\n\"");}printf("\";\n\n\n");for (i=0;i<lenudp;i++){if( *(dataudp+i)<=127&&*(dataudp+i)>=20)printf("%c",*(dataudp+i));elseprintf(".");}printf("\n\n*******************************************\n");}}}。
C#利用SharpPcap实现网络包捕获嗅探

C#利⽤SharpPcap实现⽹络包捕获嗅探本⽂是利⽤SharpPcap实现⽹络包的捕获的⼩例⼦,实现了端⼝监控,数据包捕获等功能,主要⽤于学习分享。
什么是SharpPcap?SharpPcap 是⼀个.NET 环境下的⽹络包捕获框架,基于著名的 pcap/WinPcap 库开发。
提供了捕获、注⼊、分析和构建的功能,适⽤于 C# 和 VB NET 开发语⾔。
SharpPcap有两部分组成:1> SharpPcap.dll 负责数据的捕获 2> PacketDotNet.dll负责数据包的解析思路:通过进程名字获取对应的端⼝号。
SharpPcap获取对应的数据包,通过解析数据包过滤相关的端⼝。
涉及知识点:Process 获取相关进程信息。
netstat命令:netstat -ano|find "3844" 获取进程对应的端⼝SharpPcap相关信息:通过CaptureDeviceList的静态⽅法获取设备列表。
通过OnPacketArrival事件接收数据包。
通过PacketDotNet来解析数据包效果图下:SharpPcap核⼼代码:/// <summary>/// 开始捕捉/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btnStart_Click(object sender, EventArgs e){if (bDevice.SelectedIndex > -1){StartCapture(bDevice.SelectedIndex);this.btnStart.Enabled = false;this.btnStop.Enabled = true;}else {MessageBox.Show(this,"请选择⼀个设备","提⽰",MessageBoxButtons.OK);}}/// <summary>/// 停⽌捕捉/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void btnStop_Click(object sender, EventArgs e){Shutdown();this.btnStop.Enabled = false;this.btnStart.Enabled = true;}private void StartCapture(int itemIndex){packetCount = 0;device = CaptureDeviceList.Instance[itemIndex];packetStrings = new Queue<PacketWrapper>();bs = new BindingSource();dgvData.DataSource = bs;LastStatisticsOutput = DateTime.Now;// start the background threadbackgroundThreadStop = false;backgroundThread = new Thread(BackgroundThread);backgroundThread.Start();// setup background capturedevice.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival);device.OnCaptureStopped += new CaptureStoppedEventHandler(device_OnCaptureStopped);device.Open();// tcpdump filter to capture only TCP/IP packetsstring filter = "ip and tcp";device.Filter = filter;// force an initial statistics updatecaptureStatistics = device.Statistics;UpdateCaptureStatistics();// start the background capturedevice.StartCapture();btnStop.Enabled = true;}/// <summary>/// 设备接收事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void device_OnPacketArrival(object sender, CaptureEventArgs e){// print out periodic statistics about this devicevar Now = DateTime.Now;var interval = Now - LastStatisticsOutput;if (interval > new TimeSpan(0, 0, 2)){Console.WriteLine("device_OnPacketArrival: " + e.Device.Statistics);captureStatistics = e.Device.Statistics;statisticsUiNeedsUpdate = true;LastStatisticsOutput = Now;}lock (QueueLock){PacketQueue.Add(e.Packet);}}/// <summary>/// 设备停⽌事件/// </summary>/// <param name="sender"></param>/// <param name="status"></param>private void device_OnCaptureStopped(object sender, CaptureStoppedEventStatus status){if (status != pletedWithoutError){MessageBox.Show("Error stopping capture", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);}}private void UpdateCaptureStatistics(){tlblStatistic.Text = string.Format("接收包: {0}, 丢弃包: {1}, 接⼝丢弃包: {2}", captureStatistics.ReceivedPackets,captureStatistics.DroppedPackets, captureStatistics.InterfaceDroppedPackets); }以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
利用C语言编写网络监控工具

利用C语言编写网络监控工具C语言是一种高级编程语言,广泛应用于系统开发和网络编程等领域。
利用C语言编写网络监控工具可以实现对网络环境进行监控和管理,提高网络安全性和性能。
本文将介绍如何利用C语言编写网络监控工具,并探讨其应用。
1、网络监控工具的概述网络监控工具是指用于监视和管理网络活动的软件程序。
它可以实时收集和分析网络流量数据,并提供各种网络状态信息。
网络监控工具可以用于检测网络攻击、优化网络性能、管理网络资源等。
2、C语言在网络监控中的应用C语言作为一种底层编程语言,具有高效的执行速度和灵活的编程特性,非常适合用于网络监控工具的开发。
C语言可以直接访问网络协议栈和硬件设备,实现对网络数据的实时捕获和分析。
3、利用C语言编写网络监控工具的基本步骤(1)网络捕获:利用C语言中的套接字编程接口,实现对网络数据包的捕获和监听。
可以使用第三方库如libpcap来简化网络捕获的工作。
(2)数据分析:对捕获到的网络数据包进行解析和分析,提取关键信息如源地址、目的地址、协议类型等。
可以利用C语言的字符串处理函数和结构体等特性来实现数据分析。
(3)数据存储:将分析后的数据存储到数据库或文件中,供后续分析和查询使用。
C语言可以调用数据库接口或文件操作函数来实现数据存储的功能。
(4)数据展示:将存储的数据以图表、报表等形式展示给用户,帮助用户了解网络状态和分析结果。
可以利用C语言的图形库或HTML/CSS等技术来实现数据展示的功能。
4、网络监控工具的应用场景(1)网络安全监控:通过对网络数据流量的监控和分析,及时发现和阻止网络攻击,提高网络的安全性。
(2)网络性能优化:通过对网络数据传输的监控和分析,找出瓶颈和问题所在,优化网络拓扑和配置,提高网络的性能和可靠性。
(3)网络资源管理:通过对网络流量和使用情况的监控和分析,合理分配带宽和资源,提高网络资源的利用率。
(4)网络故障排查:通过对网络数据传输和连接状态的监控和分析,快速定位和排查网络故障,减少故障对网络的影响。
VSCode代码嗅探插件推荐探索源码背后的奥秘的好帮手

VSCode代码嗅探插件推荐探索源码背后的奥秘的好帮手VSCode代码嗅探插件推荐:探索源码背后的奥秘的好帮手代码嗅探是软件开发中的一项重要技术,它可以帮助开发者深入了解源码的实现细节,提供更好的调试和分析工具。
而在众多代码编辑器中,VSCode(Visual Studio Code)凭借其灵活性和丰富的插件生态系统成为了许多开发者的首选。
本文将为大家推荐几款优秀的VSCode代码嗅探插件,助力开发者探索源码的奥秘。
一、Polacode:美化代码截图Polacode 是一款实用的 VSCode 插件,它能够让开发者将代码快照以优雅的方式展示出来。
通过 Polacode,你可以将代码片段截图,并选择合适的配色方案和背景,使代码截图具有更好的可读性和美观性。
这对于展示代码的同时保持专业形象十分重要。
二、Code Runner:快速运行代码当我们需要验证一小段代码的功能或进行某些简单的算法实验时,手动创建一个完整的项目并编译运行往往会浪费时间和精力。
Code Runner 是一款强大的VSCode插件,它支持多种编程语言,并能够快速运行选中的代码片段,提供了快速验证代码功能,让开发者能够更加便捷地进行代码的调试和测试。
三、Debugger for Chrome:调试前端JavaScript代码前端开发过程中,对于JavaScript代码的调试非常重要。
Debugger for Chrome 插件提供了一个在 VSCode 中调试运行JavaScript代码的环境,类似于Chrome浏览器的开发者工具。
它可以和Chrome浏览器进行无缝连接,支持断点调试、变量监视、单步执行等功能,方便开发者定位和解决JavaScript代码中的问题。
四、ESLint:代码规范检查良好的代码规范能够提高开发效率和代码质量,而ESLint是目前最受欢迎的JavaScript代码检查工具之一。
在VSCode中安装ESLint插件后,开发者可以根据自定义的代码规范,在开发过程中自动检查和修复代码中的潜在问题,确保代码质量的一致性和可维护性。
C语言实现LINUX下网络嗅探程序SNIFFER

C语言实现LINUX下网络嗅探程序SNIFFER#include#include#include#include#include#include#include#include#include#includeint main(int argc,char**argv){int sock,n;char buffer[2048];unsigned char*iphead,*ethhead;struct ifreq ethreq;int no=0;//设置原始套接字方式为接收所有的数据包if((sock=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_IP)))<0) {perror("\n原始套接字建立失败\n");exit(1);}//设置网卡工作方式为混杂模式,SIOCGIFFLAGS请求表示需要获取接口标志strncpy(ethreq.ifr_name,"eth0",IFNAMSIZ);//Interface Name size if(ioctl(sock,SIOCGIFFLAGS,ðreq)==-1){perror("\n设置混杂工作模式失败\n");close(sock);exit(1);}//开始捕获数据并进行简单分析while(1){n=recvfrom(sock,buffer,2048,0,NULL,NULL);no++;printf("\n************%d packet%d bytes************\n",no,n);//检查包是否包含了至少完整的以太帧(14),IP(20)和TCP/UDP(8)包头if(n<42){perror("recvfrom():");exit(0);} ethhead=buffer;printf("Dest MAC address:%02x:%02x:%02x:%02x:%02x:%02x\n",ethhead[0],ethhead[1],ethhead[2],ethhead[3],ethhead[4],ethhead[5]);printf("Source MAC address:%02x:%02x:%02x:%02x:%02x:%02x\n",ethhead[6],ethhead[7],ethhead[8],ethhead[9],ethhead[10],ethhead[11]);iphead=buffer+14;/*跳过Ethernet header*/if(*iphead==0x45){/*Double check for IPv4*and no options present*/printf("Source host:%d.%d.%d.%d,",iphead[12],iphead[13],iphead[14],iphead[15]);printf("Dest host:%d.%d.%d.%d\n",iphead[16],iphead[17],iphead[18],iphead[19]);printf("Source port:%d,Dest port:%d",(iphead[20]<<8)+iphead[21],(iphead[22]<<8)+iphead[23]); if(iphead[9]==6)printf("TCP\n");else if(iphead[9]==17)printf("UDP\n");else printf("protocol id:%d\n",iphead[9]);}}}。
基于VC++的网络扫描器设计与实现

基于VC++的⽹络扫描器设计与实现本⽂正⽂其实是⾃⼰的毕业论⽂,现在搬上来有两个原因。
⼀是之前⼤学的⽂档都放在百度⽹盘上,⼤概去年的时候百度⽹盘改版搞得不太稳定,⽂件夹移动次数⼀多⾥边就会有⼀些⽂件丢失了,也没有很在意。
但前⼏天看申请软著的汇编记事本代码⽂件怎么找都找不到,⾃⼰电脑也早就换了,放⽹盘不靠谱放⾃⼰电脑也不靠谱,这情况怕是现在没丢的东西以后也会丢有必要另想他法保存。
⼆是当时论⽂答辩的时候,导师问“你觉得你的扫描器对⽐⽹上现有的扫描器有什么优势”,当时回答的是“现在⽹上很多扫描器很多是闭源的这扫描器是开源的”----其实⼼⾥想的是“和⼗多年前的X-Scan⽐都差很远能有什么优势”----现在也还觉得功能⽐较差有很多问题(⽐如最明显的扫描时主线程卡死),但开源这事可以顺⼿做⼀下以便⾃我安慰当时并⾮随⼝乱说。
现在我也没有意会为什么两轮答辩导师都问我这个问题,感觉这不是给我挖坑吗。
不过⼀辩另外⼀位⽼师问的问题当时就反应过来了,他问“代码都是你⾃⼰写的吗有没有⽤到现成的代码”,我⾸先说“肯定有⽤现成的代码不管怎么样你最底层都得⽤系统的API,现在基本是⼀个页⾯⼀个类底层都⽤了现成的代码”,然后他⼜问“这些类都是你⾃⼰实现的吗”,我说“是我⾃⼰实现的”。
⾸先通过调⽤系统API这个没⼈能绕过的问题正⾯回答“有没有⽤现成代码”的问题,迫其把⾃⼰的提问修改成“这些类都是你⾃⼰实现的吗”,然后回答都是我⾃⼰实现的。
在“调⽤系统API”和“类⾃⼰实现”中间的“类的代码是不是你⾃⼰原创的”这最关键的地⽅直接被没有说谎地回避掉了。
其实这扫描器核⼼功能代码都出⾃李瑞民的《⽹络扫描技术揭密》,⾃⼰做的主要⼯作主要是筛选、验证、整合;⼀定要说代码原创的话,应该五五之间吧。
但其实也不⼀定是⽼师没有注意到我回避了他的问题,和很多时候⼀样别⼈问你⼀个问题并不⼀定是要你给出真实的、正确的答案,如果你的态度、思路、应变能⼒能让⼈认可那别⼈也就觉得够了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
VC++编程实现网络嗅探器中国电波传播研究所青岛分所郎锐引言从事网络安全的技术人员和相当一部分准黑客(指那些使用现成的黑客软件进行攻击而不是根据需要去自己编写代码的人)都一定不会对网络嗅探器(sniffer)感到陌生,网络嗅探器无论是在网络安全还是在黑客攻击方面均扮演了很重要的角色。
通过使用网络嗅探器可以把网卡设置于混杂模式,并可实现对网络上传输的数据包的捕获与分析。
此分析结果可供网络安全分析之用,但如为黑客所利用也可以为其发动进一步的攻击提供有价值的信息。
可见,嗅探器实际是一把双刃剑。
虽然网络嗅探器技术被黑客利用后会对网络安全构成一定的威胁,但嗅探器本身的危害并不是很大,主要是用来为其他黑客软件提供网络情报,真正的攻击主要是由其他黑软来完成的。
而在网络安全方面,网络嗅探手段可以有效地探测在网络上传输的数据包信息,通过对这些信息的分析利用是有助于网络安全维护的。
权衡利弊,有必要对网络嗅探器的实现原理进行介绍。
嗅探器设计原理嗅探器作为一种网络通讯程序,也是通过对网卡的编程来实现网络通讯的,对网卡的编程也是使用通常的套接字(socket)方式来进行。
但是,通常的套接字程序只能响应与自己硬件地址相匹配的或是以广播形式发出的数据帧,对于其他形式的数据帧比如已到达网络接口但却不是发给此地址的数据帧,网络接口在验证投递地址并非自身地址之后将不引起响应,也就是说应用程序无法收取到达的数据包。
而网络嗅探器的目的恰恰在于从网卡接收所有经过它的数据包,这些数据包即可以是发给它的也可以是发往别处的。
显然,要达到此目的就不能再让网卡按通常的正常模式工作,而必须将其设置为混杂模式。
具体到编程实现上,这种对网卡混杂模式的设置是通过原始套接字(raw socket)来实现的,这也有别于通常经常使用的数据流套接字和数据报套接字。
在创建了原始套接字后,需要通过setsockopt()函数来设置IP头操作选项,然后再通过bind()函数将原始套接字绑定到本地网卡。
为了让原始套接字能接受所有的数据,还需要通过ioctlsocket()来进行设置,而且还可以指定是否亲自处理IP头。
至此,实际就可以开始对网络数据包进行嗅探了,对数据包的获取仍象流式套接字或数据报套接字那样通过recv()函数来完成。
但是与其他两种套接字不同的是,原始套接字此时捕获到的数据包并不仅仅是单纯的数据信息,而是包含有IP头、TCP头等信息头的最原始的数据信息,这些信息保留了它在网络传输时的原貌。
通过对这些在低层传输的原始信息的分析可以得到有关网络的一些信息。
由于这些数据经过了网络层和传输层的打包,因此需要根据其附加的帧头对数据包进行分析。
下面先给出结构.数据包的总体结构:数据在从应用层到达传输层时,将添加TCP数据段头,或是UDP数据段头。
其中UDP数据段头比较简单,由一个8字节的头和数据部分组成,具体格式如下:而TCP数据头则比较复杂,以20个固定字节开始,在固定头后面还可以有一些长度不固定的可选项,下面给出TCP数据段头的格式组成:对于此TCP数据段头的分析在编程实现中可通过数据结构_TCP来定义: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;在网络层,还要给TCP数据包添加一个IP数据段头以组成IP数据报。
IP数据头以大端点机次序传送,从左到右,版本字段的高位字节先传输(SPARC是大端点机;Pentium是小端点机)。
如果是小端点机,就要在发送和接收时先行转换然后才能进行传输。
IP数据段头格式如下:同样,在实际编程中也需要通过一个数据结构来表示此IP数据段头,下面给出此数据结构的定义: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;在明确了以上几个数据段头的组成结构后,就可以对捕获到的数据包进行分析了。
嗅探器的具体实现根据前面的设计思路,不难写出网络嗅探器的实现代码,下面就给出一个简单的示例,该示例可以捕获到所有经过本地网卡的数据包,并可从中分析出协议、IP源地址、IP目标地址、TCP源端口号、TCP目标端口号以及数据包长度等信息。
由于前面已经将程序的设计流程讲述的比较清楚了,因此这里就不在赘述了,下面就结合注释对程序的具体是实现进行讲解,同时为程序流程的清晰起见,去掉了错误检查等保护性代码。
主要代码实现清单为:// 检查Winsock 版本号,WSAData为WSADATA结构对象WSAStartup(MAKEWORD(2, 2), &WSAData);// 创建原始套接字sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW));// 设置IP头操作选项,其中flag 设置为ture,亲自对IP头进行处理setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag));// 获取本机名gethostname((char*)LocalName, sizeof(LocalName)-1);// 获取本地IP 地址pHost = gethostbyname((char*)LocalName));// 填充SOCKADDR_IN结构addr_in.sin_addr = *(in_addr *)pHost->h_addr_list[0]; //IPaddr_in.sin_family = AF_INET;addr_in.sin_port = htons(57274);// 把原始套接字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);前面的工作基本上都是对原始套接字进行设置,在将原始套接字设置完毕,使其能按预期目的工作时,就可以通过recv()函数从网卡接收数据了,接收到的原始数据包存放在缓存RecvBuf[]中,缓冲区长度BUFFER_SIZE定义为65535。
然后就可以根据前面对IP数据段头、TCP数据段头的结构描述而对捕获的数据包进行分析:while (true){// 接收原始数据包信息int ret = recv(sock, RecvBuf, BUFFER_SIZE, 0);if (ret > 0){// 对数据包进行分析,并输出分析结果ip = *(IP*)RecvBuf;tcp = *(TCP*)(RecvBuf + ip.HdrLen);TRACE("协议:%s\r\n",GetProtocolTxt(ip.Protocol));TRACE("IP源地址:%s\r\n",inet_ntoa(*(in_addr*)&ip.SrcAddr));TRACE("IP目标地址: %s\r\n",inet_ntoa(*(in_addr*)&ip.DstAddr));TRACE("TCP源端口号:%d\r\n",tcp.SrcPort);TRACE("TCP目标端口号:%d\r\n",tcp.DstPort);TRACE("数据包长度:%d\r\n\r\n\r\n",ntohs(ip.TotalLen));}}其中,在进行协议分析时,使用了GetProtocolTxt()函数,该函数负责将IP包中的协议(数字标识的)转化为文字输出,该函数实现如下:#define PROTOCOL_STRING_SPX_TXT "SPX"#define PROTOCOL_STRING_NCP_TXT "NCP"#define PROTOCOL_STRING_UNKNOW_TXT "UNKNOW"……CString CSnifferDlg::GetProtocolTxt(int Protocol){switch (Protocol){case IPPROTO_ICMP : //1 /* control message protocol */return PROTOCOL_STRING_ICMP_TXT;case IPPROTO_TCP : //6 /* tcp */return PROTOCOL_STRING_TCP_TXT;case IPPROTO_UDP : //17 /* user datagram protocol */return PROTOCOL_STRING_UDP_TXT;default:return PROTOCOL_STRING_UNKNOW_TXT;}最后,为了使程序能成功编译,需要包含头文件winsock2.h和ws2tcpip.h。
在本示例中将分析结果用TRACE()宏进行输出,在调试状态下运行,得到的一个分析结果如下:协议:UDPIP源地址:172.168.1.5IP目标地址: 172.168.1.255TCP源端口号:16707TCP目标端口号:19522数据包长度:78……协议:TCPIP源地址:172.168.1.17IP目标地址: 172.168.1.1TCP源端口号:19714TCP目标端口号:10数据包长度:200……从分析结果可以看出,此程序完全具备了嗅探器的数据捕获以及对数据包的分析等基本功能。