网络嗅探器.docx
《网络嗅探器.docx》由会员分享,可在线阅读,更多相关《网络嗅探器.docx(18页珍藏版)》请在冰豆网上搜索。
网络嗅探器
四川大学计算机学院、软件学院
实验报告
课程名称
信息安全产品开发实践
实验课时
5
实验项目
网络嗅探器
实验时间
2011年11月11号
实验目的
1)继续了解Linux下C语言程序开发的过程
2)了解嗅探器
3)了解Libpcap简介、安装与程序编译
4)掌握Libpcap进行网络嗅探的工作流程
5)了解Libpcap的主要函数
6)完成一个简单的网络嗅探器的编写
实验环境
VMware5.0,
RedHatLinux9.0
实验内容(算法、程序、步骤和方法)
试验题目
使用Libpcap库捕获局域网中的IP包,要求:
1.打印数据包的源与目的物理地址;
2.打印源IP与目的IP地址;
3.打印出上层协议类型;
4.如果上层协议为TCP或UDP协议,打印目的与源端口信息;
5.如果上层协议为TCP或UDP协议,将数据以16进制与ASCII的两种方式同时打印出来,不可打印字符以‘.’代替;
00000474554202f20485454502f312e310d0aGET/HTTP/1.1..
实验:
一:
嗅探器概述
定义与作用
定义:
网络嗅探也叫网络侦听,指的是使用特定的网络协议来分解捕获到的数据包,并根据对应的网络协议识别对应数据片断。
作用:
1.管理员可以用来监听网络的流量情况
2.开发网络应用的程序员可以监视程序的网络情况
3.黑客可以用来刺探网络情报
数据包的处理流程
实现机制
二:
使用Libpcap编写程序流程
三:
打印数据流程图
四:
具体实现
1.打开虚拟机,利用gedit编辑器编写服务器端mysniffer.c程序
2.保存mysniffer.c,使用命令gcc–omysniffermysniffer.c–lpcap命令编译程序。
3.执行./mysniffer命令,程序运行,输出结果
从输出的结果来看,程序打印出了设备的名字,网络的网关地址,子网掩码等信息,在捕获一个数据报后,计算出了它的长度并且打印出了捕获它的时间,然后打印出了它的源物理地,目的物理地址,源IP地址,目的IP地址;经过程序分析之后,这个数据报的上层协议是UDP协议,然后打印出它的源端口号和目的端口号,并且将它的数据按照16进制以及ASCII码两种形式打印出来。
其他捕获的数据报的输出格式类似。
附试验源代码(附部分注释):
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//处理劫获的数据包的函数
voidmy_callback(u_char*useless,conststructpcap_pkthdr*pkthdr,constu_char*packet);
//主函数
intmain(intargc,char*argv[])
{
char*dev;//设备名
charerrbuf[PCAP_ERRBUF_SIZE];//错误缓冲区
bpf_u_int32mask;//BPF(伯克利包过滤器)格式的网络掩码
bpf_u_int32net;//BPF格式的网络地址
structin_addraddr;//用来表示一个32位的IPv4地址
char*net_c;//字符串形式网络地址,用于打印输出
char*mask_c;//字符串形式的网络掩码地址
structpcap_pkthdrheader;//libpcap包头结构,包含捕获时间,捕获长度与数据包实际长度
constu_char*packet;//捕获到的实际数据包内容
pcap_t*handle;//libpcap设备描述符号
structtm*now_tm;//时间结构体
time_tnow;
structbpf_programfp;//过滤器
charfilter_exp[]="ip";//设置过滤规则为ip
/*获取活动的网络设备名,通常为eth0*/
dev=pcap_lookupdev(errbuf);
if(dev==NULL)
{
fprintf(stderr,"Couldn'tfinddefaultdevice:
%s\n",errbuf);
return
(2);
}
printf("Device:
%s\n",dev);
/*获取设备的网络地址与网络掩码地址,并将其打印出来*/
if(pcap_lookupnet(dev,&net,&mask,errbuf)==-1)
{
fprintf(stderr,"Can'tgetnetmaskfordevice%s\n",dev);
net_c=0;
mask_c=0;
return
(2);
}
addr.s_addr=net;
net_c=inet_ntoa(addr);
printf("Net:
%s\n",net_c);
addr.s_addr=mask;
mask_c=inet_ntoa(addr);
printf("Mask:
%s\n",mask_c);
printf("==================================================\n");
/*获取Libpcapbpf过滤设备*/
/*设备最大捕获包的字节数为1518(针对以太网)*/
/*将NIC设为混在模式,可以侦听局域网的所有内容*/
handle=pcap_open_live(dev,BUFSIZ,1,0,errbuf);
if(handle==NULL)
{
fprintf(stderr,"Couldn'topendevice%s:
%s\n",dev,errbuf);
return
(2);
}
/*将过滤规则添加到过滤器上*/
if(pcap_compile(handle,&fp,filter_exp,0,net)==-1)
{
fprintf(stderr,"Couldn'tparsefilter%s:
%s\n",filter_exp,pcap_geterr(handle));
return
(2);
}
/*在BPF过滤器上启动数据过滤*/
if(pcap_setfilter(handle,&fp)==-1)
{
fprintf(stderr,"Couldn'tinstallfilter%s:
%s\n",filter_exp,pcap_geterr(handle));
return
(2);
}
/*捕获一个数据包*/
packet=pcap_next(handle,&header);
printf("Jackedonepacketat%s\n",filter_exp);
/*
*Eachpacketinthedumpfileisprependedwiththisgenericheader.
*Thisgetsaroundtheproblemofdifferentheadersfordifferent
*packetinterfaces.
*structpcap_pkthdr{
*structtimevalts;*timestamp*
*bpf_u_int32caplen;*lengthofportionpresent*
*bpf_u_int32len;*lengththispacket(offwire)*
*};
*/
/*打印数据包的长度*/
printf("Lengthofthispacketis[%d]bytes\n",header.len);
now=header.ts.tv_sec;
now_tm=localtime(&now);
printf("TimeStampofthispacketis[%d/%2d/%2d%2d:
%2d:
%2d]\n",
now_tm->tm_year+1900,now_tm->tm_mon+1,now_tm->tm_mday,
now_tm->tm_hour,now_tm->tm_min,now_tm->tm_sec);
/*打印数据包的捕获时间*/
printf("Recievedat.....%s\n",ctime((consttime_t*)&header.ts.tv_sec));
//调用my_callback函数
if(pcap_loop(handle,-1,my_callback,NULL)==-1)
{
fprintf(stderr,"error\n");
return
(2);
}
/*关闭bpf过滤器*/
pcap_close(handle);
return(0);
}
voidmy_callback(u_char*useless,conststructpcap_pkthdr*pkthdr,constu_char*packet)
{
intcount=0;//计数
intotherPart_len;//数据报的其他信息的长度
intIPlength;//IP数据报的长度
intn;//临时变量
structether_header*frame;//以太网地址结构
structiphdr*IPpacket;//ip头部
structtcphdr*TCPpacket;//tcp头部
structudphdr*UDPpacket;//udp头部
structin_addrsrcIP,destIP;//用来表示一个32位的IPv4地址
//转换成帧数据报
frame=(structether_header*)packet;
//转换为IP数据报
IPpacket=(structiphdr*)(packet+sizeof(structether_header));
//转换为TCP数据报
TCPpacket=(structtcphdr*)(packet+sizeof(structether_header)+sizeof(structiphdr));
//转换为UDP数据报
UDPpacket=(structudphdr*)(packet+sizeof(structether_header)+sizeof(structiphdr));
//打印源物理地址和目的物理地址,每个物理地址占6个字节
printf("theDestMacis:
%02X:
%02X:
%02X:
%02X:
%02X:
%02XtheSrcMacis:
%02X:
%02X:
%02X:
%02X:
%02X:
%02X\n",frame->ether_dhost[0],frame->ether_dhost[1],frame->ether_dhost[2],frame->ether_dhost[3],frame->ether_dhost[4],frame->ether_dhost[5],frame->ether_shost[0],frame->ether_shost[1],frame->ether_shost[2],frame->ether_shost[3],frame->ether_shost[4],frame->ether_shost[5]);
//打印源IP地址和目的IP地址
memcpy(&srcIP,&IPpacket->saddr,sizeof(IPpacket->saddr));
memcpy(&destIP,&IPpacket->daddr,sizeof(IPpacket->daddr));
IPlength=ntohs(IPpacket->tot_len);
printf("thesrcIPis:
%sthedestIPis:
%s\n",inet_ntoa(srcIP),inet_ntoa(destIP));
//打印协议类型(TCP)
if(IPpacket->protocol==IPPROTO_TCP)
{
printf("theprotocolofthepacketisTCP:
\n");
printf("srcport:
%ddestport:
%d\n",ntohs(TCPpacket->source),ntohs(TCPpacket->dest));
otherPart_len=IPlength-sizeof(structiphdr)-sizeof(structtcphdr);
constu_char*data=packet+sizeof(structether_header)+sizeof(structiphdr)+sizeof(structtcphdr);
//打印数据信息(以16进制和ASCII码两种形式)
while(otherPart_len>0)
{
if(otherPart_len<16)
{
printf("%5d",count);
for(n=0;n{
printf("%02X",data[count+n]);
if((n+1)%8==0)
printf("");
}
printf("");
for(n=0;nif(isprint(data[count+n]))
printf("%c",data[count+n]);
else
printf(".",data[count+n]);
printf("\n");
otherPart_len=0;
}
else
{
printf("%5d",count);
for(n=0;n<16;n++)
{
printf("%02X",data[count+n]);
if((n+1)%8==0)
printf("");
}
printf("");
for(n=0;n<16;n++)
{
if(isprint(data[count+n]))
printf("%c",data[count+n]);
else
printf(".",data[count+n]);
}
printf("\n");
otherPart_len=otherPart_len-16;
count=count+16;
}
}
}
//打印协议信息(UDP)
elseif(IPpacket->protocol==IPPROTO_UDP)
{
printf("theprotocolofthepacketisUDP:
\n");
printf("srcport:
%ddestport:
%d\n",ntohs(UDPpacket->source),ntohs(UDPpacket->dest));
otherPart_len=IPlength-sizeof(structiphdr)-sizeof(structudphdr);
constu_char*data=packet+sizeof(structether_header)+sizeof(structiphdr)+sizeof(structudphdr);
//打印数据信息(以16进制和ASCII码两种形式)
while(otherPart_len>0)
{
if(otherPart_len<16)
{
printf("%5d",count);
for(n=0;n{
printf("%02X",data[count+n]);
if((n+1)%8==0)
printf("");
}
printf("");
for(n=0;nif(isprint(data[count+n]))
printf("%c",data[count+n]);
else
printf(".",data[count+n]);
printf("\n");
otherPart_len=0;
}
else
{
printf("%5d",count);
for(n=0;n<16;n++)
{
printf("%02X",data[count+n]);
if((n+1)%8==0)
printf("");
}
printf("");
for(n=0;n<16;n++)
{
if(isprint(data[count+n]))
printf("%c",data[count+n]);
else
printf(".",data[count+n]);
}
printf("\n");
otherPart_len=otherPart_len-16;
count=count+16;
}
}
}
else
{
printf("theprotocolofthepacketisothers:
\n");
}
}
(接上)
实验内容(算法、程序、步骤和方法)
数据记录
和计算
详细见上面
结论
(结果)
利用Libpcap函数库能很好的实现一个网络嗅探器,从而能对网络中的数据报进行捕获,然后进行分析,方便我们掌握网络中的流量等一些信息,更好的控制网络行为。
小结
通过本实验,我掌握了:
1)进一步熟悉了Linux下C语言程序开发的过程;
2)继续了解Linux下C语言程序开发的过程
3)了解了什么是嗅探器
4)掌握了Libpcap安装与程序编译
5)了解了Libpcap进行网络嗅探的工作流程
6)了解Libpcap的一些主要函数
目前我存在的问题有:
对一些Libpcap函数掌握的不是很熟练。
指导老师评议
成绩评定:
指导教师签名:
实验报告说明
专业实验中心
实验名称要用最简练的语言反映实验的内容。
如验证某程序、定律、算法,可写成“验证×××”;分析×××。
实验目的目的要明确,要抓住重点,可以从理论和实践两个方面考虑。
在理论上,验证定理、公式、算法,并使实验者获得深刻和系统的理解,在实践上,掌握使用实验设备的技能技巧和程序的调试方法。
一般需说明是验证型实验还是设计型实验,是创新型实验还是综合型实验。
实验环境实验用的软硬件环境(配置)。
实验内容(算法、程序、步骤和方法)这是实验报告极其重要的内容。
这部分要写明依据何种原理、定律算法、或操作方法进行实验,要写明经过哪几个步骤。
还应该画出流程图(实验装置的结构示意图),再配以相应的文字说明,这样既可以节省许多文字说明,又能使实验报告简明扼要,清楚明白。
数据记录和计算指从实验中测出的数据以及计算结果。
结论(结果)即根据实验过程中所见到的现象和测得的数据,作出结论。
小结 对本次实验的体会、思考和建议。
备注或说明可写上实验成功或失败的原因,实验后的心得体会、建议等。
注意:
∙实验报告将记入实验成绩;
∙每次实验开始时,交上一次的实验报告,否则将扣除此次实验成绩。