大作业2IP包的截获和解析资料Word格式.docx
- 文档编号:22727374
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:30
- 大小:131.89KB
大作业2IP包的截获和解析资料Word格式.docx
《大作业2IP包的截获和解析资料Word格式.docx》由会员分享,可在线阅读,更多相关《大作业2IP包的截获和解析资料Word格式.docx(30页珍藏版)》请在冰豆网上搜索。
IP数据包的第一个字段是版本字段,其度是4位,表示所使用的IP协议的版本。
本程序主要针对版本是IPV4的数据包的解析。
报头标长字段为4位,它定义了以4B为一个单位的IP包的报文长度.报头中除了选项字段和填充域字段外,其他各字段是定长的。
因此,IP数据包的头长度在20—40B之间,是可变的。
服务类型字段共8位,用于指示路由器如何处理该数据包。
总长度字段为2B,它定义了以字节为单位的数据包的总长度,IP数据包的最大长度为65535B。
标识字段的长度为16位,用于识别IP数据包的编号,每批数据都要有一个标识值,用于让目的主机判断新来的数据属于哪个分组。
标志字段共3位,最高位是0.禁止分片标志DF(donotfragment)字段的值若为1,表示不能对数据包分片;
若DF值为0,则表明可以分片。
分片标志MF(morefragment)的值为1,表示接收到的不是最后一个分片;
若MF值为0,表示接收到的是最后一个分片。
片偏移字段共13位,说明分片在整个数据包中的相对位置,片偏移值是以8B为单位来记数的,因此选择的分片长度应该是8B的整数倍。
生存时间(TTL)字段为8位,用来设置数据包在互联网络的传输过程的寿命,通常是用一个数据包可以经过的最多的路由器跳步数来限定的。
协议字段为8位,表示使用此IP数据包的高层协议类型,常用的协议号如下表所示.
序号
协议名称
1
2
4
6
8
ICMP
IGMP
IPinIP
TCP
EGP
17
41
46
89
UDP
IPV6
RSVP
OSPFA
头校验和字段为16位,用于存放检查报头错误的校验码,检验的范围是整个IP包的报头。
校验和为0,说明数据报报头没有出错。
地址字段包括源地址和目的地址。
源地址和目的地址的长度都是32位,分别表示发送数据包的源主机和目的主机的IP地址。
选项字段的长度范围为0~40B,主要用于控制和测试。
在使用选项字段的过程中,有可能出现报头部分的长度不是32位的整数倍的情况。
如果出现这种情况,就需要通过填充位来凑齐。
因此,IP数据报的头部定义如下:
typedefstructip_header{
u_charver_ihl;
//4bit的版本信息+4bits的头长
u_chartos;
//TOS类型
u_shorttlen;
//总长度
u_shortidentification;
//Identification
u_shortflags_fo;
//Flags(3bits)+Fragmentoffset(13bits)
u_charttl;
//生存期
u_charproto;
//后面的协议信息
u_shortcrc;
//校验和
ip_addresssaddr;
//源IP
ip_addressdaddr;
//目的IP
ip_addressselection;
//选项
}ip_header;
3、各类报头TCP/UDP/ICMP/IP结构
当我们使用RawSocket的时候,可以完全自定义IP包,一切形式的包都可以"
制造"
出来。
因此,本文事先必须对TCP/IP所涉及IP包结构进行必要的交待。
目前,IPv4的报头结构为常用的ICMP报文包括ECHO-REQUEST(响应请求消息)、ECHO-REPLY(响应应答消息)、DestinationUnreachable(目标不可到达消息)、TimeExceeded(超时消息)、ParameterProblems(参数错误消息)、SourceQuenchs(源抑制消息)、Redirects(重定向消息)、Timestamps(时间戳消息)、TimestampReplies(时间戳响应消息)、AddressMasks(地址掩码请求消息)、AddressMaskReplies(地址掩码响应消息)等,是Internet上十分重要的消息。
后面章节中所涉及到的ping命令、ICMP拒绝服务攻击、路由欺骗都与ICMP协议息息相关。
TCP报头结构为:
对应数据结构:
typedefstructpsd_hdr//定义TCP伪报头
{
unsignedlongsaddr;
//源地址
unsignedlongdaddr;
//目的地址
charmbz;
charptcl;
//协议类型
unsignedshorttcpl;
//TCP长度
}PSD_HEADER;
typedefstruct_tcphdr//定义TCP报头
unsignedshortth_sport;
//16位源端口
unsignedshortth_dport;
//16位目的端口
unsignedintth_seq;
//32位序列号
unsignedintth_ack;
//32位确认号
unsignedcharth_lenres;
//4位首部长度/4位保留字
unsignedcharth_flag;
//6位标志位
unsignedshortth_win;
//16位窗口大小
unsignedshortth_sum;
//16位校验和
unsignedshortth_urp;
//16位紧急数据偏移量
}TCP_HEADER;
UDP报头为:
对应的数据结构为:
typedefstruct_udphdr//定义UDP报头
unsignedshortuh_sport;
//16位源端口
unsignedshortuh_dport;
//16位目的端口
unsignedshortuh_len;
//16位长度
unsignedshortuh_sum;
//16位校验和
}UDP_HEADER;
ICMP协议是网络层中一个非常重要的协议,其全称为InternetControlMessageProtocol(因特网控制报文协议),ICMP协议弥补了IP的缺限,它使用IP协议进行信息传递,向数据包中的源端节点提供发生在网络层的错误信息反馈。
ICMP报头为:
常用的回送与或回送响应ICMP消息对应数据结构为:
typedefstruct_icmphdr//定义ICMP报头(回送与或回送响应)
unsignedchari_type;
//8位类型
unsignedchari_code;
//8位代码
unsignedshorti_cksum;
unsignedshorti_id;
//识别号(一般用进程号作为识别号)
unsignedshorti_seq;
//报文序列号
unsignedinttimestamp;
//时间戳
}ICMP_HEADER;
四.程序设计分析
为了获取网络中的IP数据包,必须对网卡进行编程,在这里我们觊觎winpcap提供的库函数进行编程。
但是,在通常情况下,网络通信只能响应与自己硬件地址相匹配的数据包或是以广播形式出发的数据包。
对于其他形式的数据包,如已到达网络接口但却不是发送到此地址的数据包,网络接口在验证投递地址并非自身地址之后将不引起响应,也就是说应用程序无法收取与自己无关的数据包。
我们要想获取流经网络设备的所有数据包,就需要将网卡设置为混杂模式。
1、获取所有存在的网络设备的链表。
Pcap_if_t*alldevs;
//网络设备结构链表
Charerrbuf[PCAP_ERRBUF_SIZE];
//错误信息
/*所有网络设备的信息以链表形式存在alldevs中*/
pcap_findalldevs(&
alldevs,errbuf);
2、从链表中选择物理Ethernet卡后,用混杂模式打开。
if((adhandle=pcap_open_live(d->
name,//设备名称
65536,//portionofthepackettocapture.
1,//采用混杂模式
1000,//读超时为1秒
errbuf//errorbuffer
))==NULL)
{
fprintf(stderr,"
\nUnabletoopentheadapter.%sisnotsupportedbyWinPcap\n"
);
pcap_freealldevs(alldevs);
return-1;
}
在这个函数中,第一个参数为要打开的设备名称,这里是Ethernet卡,可以从设备链表alldevs中选出。
第二个参数应为捕获的数据包长度,填入65535以保证在链路层的整个数据包都被捕获。
第三个参数为打开模式,填入1表明用混杂模式打开网卡。
最后两个参数本别为读入超时的时间和保存错误信息。
最后返回一个网卡描述符adhandle.
3、捕获数据包。
res=pcap_next_ex(adhandle,&
header,&
pkt_data))
adhandle是由pcap_open_live()返回的所打开网卡的指,header是pcap_pkthdr型的结构体,存储时间,包的长度,pkt_data存储数据包的内容,为一个char型数组。
返回值res
等于1时成功;
等于0时超时;
等于-1时说明发生错误。
对于捕获的数据包,去掉数据链路层的14B的头部后才是真正的IP包信息。
5.参考程序流程图
五.结果分析
1、选择网卡
2.捕获的IP数据包
********************************************************************
数据包5
抓包信息:
时间:
10:
03:
32编号:
751530数据包长度:
67捕获的数据包长度:
67
DLC帧分析:
MAC地址:
00000052506a->
000000525064以太网协议类型:
0x0800(IP包)
IP报头分析:
IP42005323213不分01UDP2b65192.168.146.1->
224.0.0.252
UDP报头分析:
端口:
eb->
b821报文长:
46409校验和:
96
根据IP报头结构:
IP协议的版本号|包头长度|服务类型|总长|ID|Flag|片偏移|生存时间|协议类型|包头校验和|源IP|目的IP|
可以知道这个IP数据报是从192.168.146.1(本机)发给224.0.0.252(默认网关)的,包头长度为20字节,总长度为53字节,不分片,片偏移为0,生存时间为1,协议类型为UDP,包头校验和为2b65。
还可以进一步对封装的UDP数据报进行分析。
3.捕获的其他数据包
*****************************************************************************
数据包2
750418数据包长度:
87捕获的数据包长度:
87
000000524f3a->
000000524f34以太网上协议类型:
34304未知包丢弃
******************************************************************************
根据协议类型为34304,可知这是一个未知,丢弃。
六.主程序源代码
#include<
stdio.h>
#include<
stdlib.h>
iostream>
#include"
fstream"
time.h>
iomanip>
//流操作符,主要是对cin,cout之类的一些操纵运算子,比如setfill,setw,setbase,setprecision等等
conio.h"
//运用getch()函数
Header.h"
winsock2.h>
#pragmacomment(lib,"
ws2_32.lib"
)//链接至库
pcap.h"
wpcap.lib"
usingnamespacestd;
intSwitchAgreement(u_charproto,constu_char*pkt_data);
//对IP数据包数据部分进行解析
DWORDWINAPIFun1Proc(LPVOIDlpParameter);
intk1=1;
//抓包个数
intk2=1;
//一次显示的数据包个数
intk3;
//日志变量
time_tt;
//时间变量,长整型
char*s;
stringp;
charbuffer[100];
intmain()
pcap_if_t*alldevs;
//网卡描述符列表,包含各网卡信息、型号、名字、地址等的结构体
pcap_if_t*d;
pcap_t*adhandle;
charerrbuf[PCAP_ERRBUF_SIZE];
//错误信息
structpcap_pkthdr*header;
ip_header*ih;
constu_char*pkt_data;
intinum;
inti=0;
intnum=0;
intres;
structtm*ltime;
chartimestr[16];
char*logname=newchar[20];
cout<
<
"
请输入日志名称(.log):
\n"
;
cin>
>
logname;
if(logname==NULL)logname="
默认日志.log"
ofstreamofs(logname,ios:
:
app);
//以追加方式打开日志文件
time(&
t);
//获取系统时间
p="
p+=ctime(&
//把系统时间转换为字符串
p+="
用户运行程序\n"
s=&
p[0];
ofs.write(s,strlen(s));
//系统时间写入日志文件
ofs.flush();
//获得网卡的列表
if(pcap_findalldevs(&
alldevs,errbuf)==-1)
Errorinpcap_findalldevs:
%s\n"
errbuf);
exit
(1);
}
ofs.write("
获得网卡的列表\n"
strlen("
));
打印网卡信息\n"
//打印网卡信息
本机虚拟网卡列表:
p="
for(d=alldevs;
d;
d=d->
next)
//网卡列表写入日志文件
i++;
_itoa(i,buffer,10);
//将i转换为10进制的字符串
p+=buffer;
p+="
."
p+=d->
name;
if(d->
description)
{
p+="
\t("
p+=d->
description;
)\n"
}
else
(Nodescriptionavailable)\n"
s=&
ofs.write(s,strlen(s));
ofs.flush();
p;
p="
if(i==0)//找不到设备
cout<
endl<
Nointerfacesfound!
MakesureWinPcapisinstalled."
endl;
HANDLEhThread1;
//线程句柄
if(hThread1)
TerminateThread(hThread1,NULL);
输入要监听的网卡号(1-"
i<
):
inum;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
//这个线程用来控制退出
CloseHandle(hThread1);
选择网卡号为:
_itoa(inum,buffer,10);
p+=buffer;
p="
if(inum<
1||inum>
i)//判断号的合法性
Interfacenumberoutofrange."
输入网卡号无效\n"
else
检测网卡号有效\n"
//找到要选择的网卡结构
for(d=alldevs,i=0;
i<
inum-1;
d=d->
next,i++);
找到了要打开的网卡地址\n"
s=&
//打开选择的网卡
if((adhandle=pcap_open_live(d->
//Freethedevicelist
if(pcap_datalink(adhandle)!
=DLT_EN10MB)//只考虑以太网数据
\nThisprogramworksonlyonEthernetnetworks.\n"
该网卡设置为了混乱模式\n开始捕获数据包\n"
listeningon"
d->
name<
..."
开始捕获IP包,输入Ctrl+C退出程序,输入Ctrl+Z重新选择网卡......"
pcap_freealldevs(alldevs);
IP报头结构:
***********************************************************************************\n"
|时间|IP协议的版本号|包头长度|服务类型|总长|ID|Flag|片偏移|生存时间|协议类型|包头校验和|源IP|目的IP|\n"
***********************************************************************************\n\n"
DLCHEADER*ik;
//物理帧头
while((res=pcap_next_ex(adhandle,&
pkt_data))>
=0&
&
k1)//开始捕获数据包,eader是pcap_pkthdr结构,pkt_header是接收数据的缓冲区
ltime=l
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 作业 IP 截获 解析 资料