📄 arpparse.cpp
字号:
/*解析ARP数据包*/
#include <WINSOCK2.H>
#pragma comment(lib,"Ws2_32.lib") //用到ntohs()
//等同于点击"Project->settings->link"打开Object/library modules编辑框后加入lib文件
#pragma comment(lib,"wpcap.lib")
#include "pcap.h" /*winpcap包中的头文件,需要将其导入到VC中*/
#include <fstream.h>
#include <iomanip.h>
#include <conio.h>
/*
注意到接收的数据包头中代表类型,数据长度的字段采用的是big-endian
所以对于2B/4B的数据要用ntohs()转换为本机形式
*/
/*arp包结构*/
struct arppkt{
unsigned short hdtyp; /* 硬件类型。值0001表示其为Ehternet */
unsigned short protyp; /*协议类型。值0800表示上层协议为IP */
unsigned char hdsize; /* 硬件地址长度,值为06 */
unsigned char prosize; /* 协议地址长度,值为04 */
unsigned short op; /* 操作值:0001/0002,分别表示ARP请求/回答 */
u_char smac[6]; /* 源MAC地址,6B */
u_char sip[4]; /* 源IP地址,4B */
u_char dmac[6]; /* 目的MAC地址 */
u_char dip[4]; /* 目的IP地址 */
};
/*
自定义处理包的函数
pcap_pkthdr结构是堆文件中数据包的头,是winpcap加入的
pkt_data表示MAC帧的起始位置
out是输出流
*/
void packet_handler(const pcap_pkthdr *header,const u_char *pkt_data,ostream& out);
void main(int argc,char *argv[])
{
if (argc!=2)
{
cout<<"Usage:arpparse logfilename"<<endl;
cout<<"Press any key to continue."<<endl;
_getch();
return;
}
pcap_if_t *alldevs; /*网络设备结构*/
pcap_if_t *d;
pcap_t *adhandle; /*网卡描述符*/
char errbuf[PCAP_BUF_SIZE]; /*错误信息*/
u_int netmask; /*子网掩码*/
char packet_filter[]="ether proto \\arp"; /*过滤,选择ARP协议*/
struct bpf_program fcode;
struct pcap_pkthdr *header;
const u_char *pkt_data;
/*获取网络设备列表*/
if (pcap_findalldevs(&alldevs,errbuf) ==-1 )
{
cout<<"Error in pcap_findalldevs:"<<errbuf;
return;
}
/*选择一个ethernet卡 */
for (d=alldevs;d;d=d->next)
{
/*以混杂模式打开网卡,以接收所有的帧*/
if ((adhandle=pcap_open_live(d->name,1000,1,300,errbuf)) == NULL)
{
cout<<"\nUnable to open the adapter.";
pcap_freealldevs(alldevs);
return;
}
if (pcap_datalink(adhandle)==DLT_EN10MB && d->addresses != NULL)
{
/*检查数据链路是否为Ethernet(DLT_EN10MB) */
break;
}
if (d==NULL)
{
cout<<"\nNo interface found!Make sure Winpcap is installed.\n";
return;
}
/*获得子网掩码*/
if (d->addresses!=NULL)
{
netmask=((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
}
else
/*没有地址则假设为C类地址*/
netmask=0xffffff;
/*编译过滤器,只捕获ARP包*/
if ( pcap_compile(adhandle,&fcode,packet_filter,1,netmask)<0 )
{
cout<<"\nUnable to compile the packet filter.Check the syntax.\n";
pcap_freealldevs(alldevs);
return;
}
/*设置过滤器*/
if (pcap_setfilter(adhandle,&fcode)<0)
{
cout<<"\nError setting the filter.\n";
pcap_freealldevs(alldevs);
return;
}
/*显示提示信息和每项含义*/
cout<<"\t\tListening on"<<d->description<<"..."<<endl<<endl;
ofstream fout(argv[1],ios::app); /*日志记录文件*/
/*为查看日志时的方便其中加入了日期记录*/
time_t t;
time(&t);
fout.seekp(0,ios::end);
if (fout.tellp()!=0)
{
fout<<endl;
}
fout<<"\t\tARP request(1)/reply(2) on"<<ctime(&t);
cout<<"Sour IP Addr"<<" "<<"Sour Mac Address"
<<" "<<"Des IP Addr"<<" "<<"Des Mac Address"
<<" "<<"OP"<<" "<<"Time"<<endl;
fout<<"Sour IP Addr"<<" "<<"Sour Mac Address"
<<" "<<"Des IP Addr"<<" "<<"Des Mac Address"
<<" "<<"OP"<<" "<<"Time"<<endl;
/*释放设备列表*/
pcap_freealldevs(alldevs);
/*开始捕获MAC帧*/
int result; /*时间到返回结果*/
while ((result=pcap_next_ex(adhandle,&header,&pkt_data))>=0)
{
if (result==0)
{
continue; /*超时返回*/
}
packet_handler(header,pkt_data,cout); /*解析ARP包,将结果输出到屏幕*/
packet_handler(header,pkt_data,fout); /*输出到文件*/
}
}
}
void packet_handler(const pcap_pkthdr *header,const u_char *pkt_data,ostream& out)
{
/*从截获的数据帧中ARP头的位置*/
arppkt* arph=(arppkt *)(pkt_data + 14);
/*14为Ethernet的帧头长度,源和目的地址长度均为12B 数据长度为2B */
/*输出源IP*/
for (int i=0;i<3;i++)
{
cout<<int(arph->sip[i])<<'.';
}
out.setf(ios::left);
out<<setw(3)<<int(arph->sip[3])<<" ";
out.unsetf(ios::left);
/*输出源MAC地址*/
char oldfillchar=out.fill('0');
out.setf(ios::uppercase);
for (i=0;i<5;i++)
{
out<<hex<<setw(2)<<int(arph->smac[i])<<'-';
}
out<<hex<<setw(2)<<int(arph->smac[5])<<" ";
out.fill(oldfillchar);
/*输出目的IP*/
out.unsetf(ios::hex | ios::uppercase);
for (i=0;i<3;i++)
{
cout<<int(arph->dip[i])<<'.';
}
out.setf(ios::left);
out<<setw(3)<<int(arph->dip[3])<<" ";
out.unsetf(ios::left);
/*输出目的MAC地址*/
out.fill('0');
out.setf(ios::uppercase);
//char oldfillchar=out.fill('0');
out.setf(ios::uppercase);
for (i=0;i<5;i++)
{
out<<hex<<setw(2)<<int(arph->dmac[i])<<'-';
}
out<<hex<<setw(2)<<int(arph->dmac[5])<<" ";
out.fill(oldfillchar);
out.unsetf(ios::hex | ios::uppercase);
out<<ntohs(arph->op)<<" "; /*输出操作类型,注意网络字节顺序的转换*/
struct tm *ltime;
ltime=localtime(&header->ts.tv_sec);
out.fill('0');
out<<ltime->tm_hour<<':'<<setw(2)<<ltime->tm_min<<':'<<setw(2)<<ltime->tm_sec;
out.fill(oldfillchar);
out<<endl;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -