网络安全实验--网络嗅探器
0x01 前言
本来以为可以划水过去的网络安全实验课,突然就被老师布置了一个作业,写一个网络嗅探器,大概要求如下:
利用Winsock编程接口,设计实现一个能够在共享式局域网中完成网络抓包并分析所截获数据包的嗅探程序。
要求:
1、能够捕获并分析IP分组,ARP分组,ICMP报文,TCP报文,UDP报文等(如果能解析到应用层更好)。
2、数据包显示界面尽量美观
0x02 分析
一开始很苦恼呀,这丢给一个小白怎么做呀,后来听大神说虚拟机里有两个例子,改改就能用了(实验课用的是什么中软的一套程序,网络信息安全 综合实验系统,在虚拟机里运行,拷了也会显示未授权,比较尴尬),知识类实验→网络攻防→实验3 网络嗅探→练习二、练习三,,请教请教学霸,大概看了看,差不多了
就是先捕获一个数据包,捕获数据包后,首先判断是ip分组还是arp分组,如果是ip分组,则调用判断高层协议子函数,进一步分析后输出分析结果,如果是arp分组,则输出判断结果,别的分组则直接输出结果
0x03 代码
#define _WIN32_WINNT 0x502
#include <pcap.h>
#include <stdio.h>
#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")#pragma comment(lib, "wpcap")#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)//Key offset
#define IP_HITYPE 9
#define IP_SADDR 12
#define IP_DADDR 16
#define IP_HEADLEN 32#define ICMP_TYPE 0#define TCP_SPORT 0
#define TCP_DPORT 2#define UDP_SPORT 0
#define UDP_DPORT 2//Higher layer Protocol Type#define HI_UNKNOW -1
//IP layer
#define HI_ICMP 1
#define HI_IGMP 2
#define HI_TCP 3
#define HI_UDP 4
#define HI_OSPF 5void ParseTCPLayer( const u_char* cBuff );
void ParseUDPLayer( const u_char* cBuff );
void ParseICMPLayer( const u_char* cBuff );
int ParseIPLayer( const u_char* cBuff );int main()
{pcap_if_t *alldevs;pcap_if_t *d;pcap_t *adhandle;char errbuf[PCAP_ERRBUF_SIZE];char timestr[16];int res,inum=0,i=0;int iPacketsum=0;struct tm *ltime;struct pcap_pkthdr *header;const u_char *pkt_data;int nIpHeaderLen = 5;//! 获取设备列表if( pcap_findalldevs(&alldevs, errbuf ) == -1 ){printf( "调用pcap_findalldevs时发生错误: %s\n", errbuf );exit(1);} //! 显示设备列表for( d=alldevs; d; d=d->next ){printf( "%d.%s", ++i, d->name );if(d->description)printf( " %s\n", d->description );elseprintf( " no description available\n" );}if( i==0 ){printf( "\nNo interfaces found! Make sure Winpcap is installed.\n" );return -1;}//! 指定可用设备printf( "Enter the interface number (1-%d):", i );scanf( "%d", &inum );if( inum<1 || inum >i ){printf( "\nInterface number out of range.\n" );// 释放设备列表pcap_freealldevs(alldevs);return -1;}//! 跳转到选中设备for(d=alldevs, i=0; i<inum-1; d=d->next,i++);//! 打开网络设备if( (adhandle=pcap_open_live(d->name, // 设备名称65535, // 捕获数据包最大长度(包括链路层数据)1, // 网卡混杂模式工作1000, // 读超时errbuf // 错误缓冲)) == NULL ){printf( "Unable to open the adapter. %s is not supported by Winpcap\n" );// 释放设备列表pcap_freealldevs(alldevs);return -1;}printf( "\nlistening on %s...\n", d->description );pcap_freealldevs(alldevs); // 此时已不再需要设备列表,释放设备列表//! 开始捕获数据包,这里没有使用pcap_loop调用回调函数的方法,而是循环调用pcap_next_ex。while( (res=pcap_next_ex( adhandle, &header, &pkt_data)) >=0 ){if( res == 0 ){// 超时continue;}iPacketsum++;printf("\n ------------------------------------------------\n");// 判断数据包类型printf("数据包类型编码或长度:%.2x%.2x\n",pkt_data[12],pkt_data[13]);if(pkt_data[12] == 8 && pkt_data[13] == 0){printf("This is an ip data packet!\n");// 解析ip数据包switch( ParseIPLayer( pkt_data +14 ) ){case HI_ICMP:ParseICMPLayer( &pkt_data[nIpHeaderLen*4] );break;case HI_TCP:ParseTCPLayer( &pkt_data[nIpHeaderLen*4] );break;case HI_UDP:ParseUDPLayer( &pkt_data[nIpHeaderLen*4] );break;}}else if(pkt_data[12] == 8 && pkt_data[13] == 6){printf("This is an ARP data packet!\n");}else{printf("Other type data packet!\n");}// 捕获时间ltime = localtime(&header->ts.tv_sec);strftime( timestr, sizeof(timestr), "%H:%M:%S", ltime);printf( " No %d. 时间%s. 长度%d\n", iPacketsum,timestr, header->len );// 单行16字节显示数据包内容for(unsigned int j=1; j<header->len+1; j++){printf( " %.2x", pkt_data[j-1] );if( (j % 16) == 0 ) printf("\n");}}//! 关闭设备pcap_close( adhandle );return 0;
}// 解析IP层,获得上层协议类型
int ParseIPLayer( const u_char* cBuff )
{unsigned int usIp1(0), usIp2(0), usIp3(0), usIp4(0);unsigned int nIpHiType(0);memcpy( &usIp1, &cBuff[IP_SADDR], sizeof(char) );memcpy( &usIp2, &cBuff[IP_SADDR+1], sizeof(char) );memcpy( &usIp3, &cBuff[IP_SADDR+2], sizeof(char) );memcpy( &usIp4, &cBuff[IP_SADDR+3], sizeof(char) );printf("****** IP Layer ******\n");printf("源IP地址:%d.%d.%d.%d ", usIp1,usIp2,usIp3,usIp4);memcpy( &usIp1, &cBuff[IP_DADDR], sizeof(char) );memcpy( &usIp2, &cBuff[IP_DADDR+1], sizeof(char) );memcpy( &usIp3, &cBuff[IP_DADDR+2], sizeof(char) );memcpy( &usIp4, &cBuff[IP_DADDR+3], sizeof(char) );printf("目的IP地址:%d.%d.%d.%d ", usIp1,usIp2,usIp3,usIp4);memcpy( &nIpHiType, &cBuff[IP_HITYPE], sizeof(char) );switch ( nIpHiType){case 1:printf("IP高层协议类型:%d (ICMP)", nIpHiType);return HI_ICMP;case 2:printf("IP高层协议类型:%d (IGMP)", nIpHiType);return HI_IGMP;case 6:printf("IP高层协议类型:%d (TCP)", nIpHiType);return HI_TCP;case 17:printf("IP高层协议类型:%d (UDP)", nIpHiType);return HI_UDP;case 89:printf("IP高层协议类型:%d (OSPF)", nIpHiType);return HI_OSPF;default:printf("IP高层协议类型:%d (未知的类型)", nIpHiType);return HI_UNKNOW;}
}// 解析ICMP数据包,获得ICMP类型
void ParseICMPLayer( const u_char* cBuff )
{unsigned int nIcmpType(0);memcpy( &nIcmpType, &cBuff[ICMP_TYPE], sizeof(char) );printf("****** ICMP Layer ******\n");switch ( nIcmpType ){case 3:printf("ICMP类型:%d (终点不可达)", nIcmpType);break;case 4:printf("ICMP类型:%d (源点抑制)", nIcmpType);break;case 11:printf("ICMP类型:%d (超时)", nIcmpType);break;case 12:printf("ICMP类型:%d (参数问题)", nIcmpType);break;case 5:printf("ICMP类型:%d (改变路由)", nIcmpType);break;case 8:printf("ICMP类型:%d (回送请求)", nIcmpType);break;case 0:printf("ICMP类型:%d(回送回答)", nIcmpType);break;case 13:printf("ICMP类型:%d (时间戳请求)", nIcmpType);break;case 14:printf("ICMP类型:%d (时间戳回答)", nIcmpType);break;case 17:printf("ICMP类型:%d (地址掩码请求)", nIcmpType);break;case 18:printf("ICMP类型:%d (地址掩码回答)", nIcmpType);break;case 10:printf("ICMP类型:%d(路由器询问)", nIcmpType);break;case 9:printf("ICMP类型:%d (路由器通告)", nIcmpType);break;default:printf("ICMP类型:%d (未知的ICMP类型)", nIcmpType);}
}// 解析TCP数据包,获得源、目的端口对
void ParseTCPLayer( const u_char* cBuff )
{unsigned short usSPort(0);unsigned short usDPort(0);printf("****** TCP Layer ******\n");memcpy( &usSPort, &cBuff[TCP_SPORT], 2*sizeof(char) );usSPort = htons( usSPort );switch ( usSPort ){case 20:printf("TCP源端口:%d(FTP 数据) ",usSPort);break;case 21:printf("TCP源端口:%d(FTP 控制) ",usSPort);break;case 23:printf("TCP源端口:%d(TELNET) ",usSPort);break;case 25:printf("TCP源端口:%d(SMTP) ",usSPort);break;case 80:printf("TCP源端口:%d(HTTP) ",usSPort);break;case 110:printf("TCP源端口:%d(POP3) ",usSPort);break;case 143:printf("TCP源端口:%d(IMAP) ",usSPort);break;default:printf("TCP源端口:%d ",usSPort);break;}memcpy( &usDPort, &cBuff[TCP_DPORT], 2*sizeof(char) );usDPort = htons( usDPort );switch ( usDPort ){case 20:printf("TCP目的端口:%d(FTP 数据)\n", usDPort);break;case 21:printf("TCP目的端口:%d(FTP 控制)\n", usDPort);break;case 23:printf("TCP目的端口:%d(TELNET)\n", usDPort);break;case 25:printf("TCP目的端口:%d(SMTP)\n", usDPort);break;case 80:printf("TCP目的端口:%d(HTTP)\n", usDPort);break;case 110:printf("TCP目的端口:%d(POP3)\n", usDPort);break;case 143:printf("TCP目的端口:%d(Imap)\n", usDPort);break;default:printf("TCP目的端口:%d\n", usDPort);break;}
}// 解析UDP数据包,获得源、目的端口对
void ParseUDPLayer( const u_char* cBuff )
{unsigned short usSPort(0);unsigned short usDPort(0);printf("****** UDP Layer ******\n");memcpy( &usSPort, &cBuff[UDP_SPORT], 2*sizeof(char) );usSPort = htons( usSPort );switch ( usSPort ){case 161:printf("UDP源端口:%d(SNMP) ", usSPort);break;case 67:printf("UDP源端口:%d(DHCP) ", usSPort);break;case 68:printf("UDP源端口:%d(DHCP) ", usSPort);break;case 53:printf("UDP源端口:%d(DNS) ", usSPort);break;case 520:printf("UDP源端口:%d(RIP) ", usSPort);break;case 138:printf("UDP源端口:%d(NetBios) ", usSPort);break;case 139:printf("UDP源端口:%d(SMB) ", usSPort);break;case 137:printf("UDP源端口:%d(WINS) ", usSPort);break;default:printf("UDP源端口:%d ", usSPort);break;}memcpy( &usDPort, &cBuff[UDP_DPORT], 2*sizeof(char) );usDPort = htons( usDPort );switch ( usDPort ){case 161:printf("UDP目的端口:%d(SNMP)\n", usDPort);break;case 67:printf("UDP目的端口:%d(DHCP)\n", usDPort);break;case 68:printf("UDP目的端口:%d(DHCP)\n", usDPort);break;case 53:printf("UDP目的端口:%d(DNS)\n", usDPort);break;case 520:printf("UDP目的端口:%d(RIP)\n", usDPort);break;case 138:printf("UDP目的端口:%d(NetBios)\n", usDPort);break;case 139:printf("UDP目的端口:%d(SMB)\n", usDPort);break;case 137:printf("UDP目的端口:%d(WINS)\n", usDPort);break;default:printf("UDP目的端口:%d\n", usDPort);break;}
}
0x04 问题
给老师演示的时候,解析的ip分组再向下分析时,都是未知类型,而且ip地址看着也很奇怪,最后经过学霸指点,需要去掉前面的14个 char,为什么呢?请看下图:
前14个字节没什么用了,但是那些函数还是从头开始分析,那就比较尴尬了(对了,第12,13字节,就是判断是ip分组还是arp分组的地方,ip分组是 0800,arp分组是0806)
所以调用ParseIPLayer函数时,捕获到的数据需要向后偏移14个字节,也就是调用 ParseIPLayer( pkt_data + 14 )
没有按老师要求用winsock编程接口,就这样吧,实现了就可以
0x05 废话
唉,看了一节课,也不如学霸的一句话,差距满满的
越微小的错误越难找到,,
网络安全实验--网络嗅探器相关推荐
- 计算机网络安全之网络嗅探器
作者:shmily 实验题目 实验题目:网络嗅探器实现 实验目的:熟悉并实现网络监听的基本原理 实验环境:linux/windows 实验内容:用C/C++语言(必须用socket函数)编写一个监听网 ...
- 基于QT的网络嗅探器实现(网络安全课程设计)
在这学期的网络安全课程设计中,我们需要自己实现一个基于WinPcap编程接口的网络嗅探器,历时两周完成,主要参考资料: 1.WinPcap 中文技术文档(http://www.ferrisxu.com ...
- (网络实验)基于Jnetpcap的网络嗅探器(抓包程序)设计与实现
基于Jnetpcap的网络嗅探器(抓包程序)设计与实现 作者:程哥哥 学号:xxxx 引言: 此程序是由自己编写的个人网络嗅探器,相当于著名的包捕获软件Wireshark的简化版,界面参考至别人的博客 ...
- 计网实验c/c++、网络嗅探器的设计与实现
参照附录 4 raw socket 编程例子,设计一个可以监视网络的状态.数据流动情况以及网络上传输 的信息的网络嗅探器. 显示了流量信息,若要查看报文信息请修改注释. 自动获取ip #include ...
- 计算机网络rsa算法,计算机网络安全实验新报告--非对称密码算法RSA.doc
计算机网络安全实验新报告--非对称密码算法RSA 网络安全实验报告 学院 网络工程专业 班 学号 姓名 成绩评定_______ 教师签名 实验 2 题目 非对称密码算法RSA 课程名称 网络安全 PA ...
- 计算机网络课程设计之网络嗅探器的设计与实现
前言 本实验难点是在于Windows下的raw socket有太多的限制,因此用winpcap编程功能更加强大,但是根据指导书要求要用原始套接字,原始套接字在Linux系统下也十分强大,结尾附上Lin ...
- 计算机网络网络安全实验报告,《计算机网络安全》实验报告
<计算机网络安全>实验报告 (9页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 <计算机网络安全>实验报告■实验名称 ...
- 网络嗅探器的设计与实现 python实现 计算机网络课程设计
实验内容 设计一个可以监视网络的状态.数据流动情况以及网络上传输 的信息的网络嗅探器 代码 import socket import threading import time import logg ...
- VC++编程实现网络嗅探器
点击打开链接http://blog.csdn.net/junnan321/article/details/1736339 引言 从事网络安全的技术人员和相当一部分准黑客(指那些使用现成的黑客软件进行攻 ...
最新文章
- C语言学习趣事_之_大数运算_加法
- 最短路径(Shortest Paths)
- mysql 利用binlog增量备份,还原实例
- dataframe输出某列的数据以及统计某列的取值种数+输出某行数据
- configparser logging
- 零基础学习java必须要了解的学习路线
- python的固定有没有固定字符_python每次处理固定个数的字符的方法总结
- 4KB/2MB/1GB 4级/5级分页模式下的线性地址翻译以及CR3
- [Teamcenter 2007 开发系列] web 非空验证
- POJ 3669 简单BFS
- angular4.0 父子组建之间的相互通信
- H5 - template native模板 实现列表布局
- c# winform 浏览器调用chrome内核
- matlab 数字带圈,LaTeX - 带圈数字
- javaSE开发智能问答机器人项目
- 哈工大游戏设计复习题
- java隋唐系列游戏下载,隋唐爭霸V2.11游戏
- UIImageView做动画的坑
- 2022年化工自动化控制仪表考试资料及化工自动化控制仪表免费试题
- pc端页面右侧滑动样式修改