您的位置:首页 > 其它

手把手教你玩转ARP包(三)【数据包的游戏系列之一】

2011-11-01 23:21 381 查看
作者:
CSDN VC/MFC 网络编程
PiggyXP ^_^

目录:

二。发送数据包的编程实现
1. 填充数据包
2. 发送数据包
三。一些附加步骤及说明
1. 如果在VC中使用winpcap
2. 获得网卡信息列表
3. 获得系统ARP信息列表

................紧接上文................

1. 填充数据包

下面我举个填充包头的例子,我首先定义个了一个转换字符的函数,如下

[align=left]/****************************************************************************[/align]
[align=left] * Name & Params::[/align]
[align=left] * formatStrToMAC[/align]
[align=left] * ([/align]
[align=left] * const LPSTR lpHWAddrStr : 用户输入的MAC地址字符串[/align]
[align=left] * unsigned char *HWAddr : 返回的MAC地址字符串(赋给数据包结构体)[/align]
[align=left] * )[/align]
[align=left] * Purpose:[/align]
[align=left] * 将用户输入的MAC地址字符转成数据包结构体需要的格式[/align]
[align=left] ****************************************************************************/[/align]
[align=left]void formatStrToMAC(const LPSTR lpHWAddrStr, unsigned char *HWAddr)[/align]
[align=left]{[/align]
[align=left] unsigned int i, index = 0, value, temp;[/align]
[align=left] unsigned char c;[/align]
[align=left] [/align]
[align=left] _strlwr(lpHWAddrStr); // 转换成小写[/align]
[align=left] [/align]
[align=left] for (i = 0; i < strlen(lpHWAddrStr); i++)[/align]
[align=left] {[/align]
[align=left] c = *(lpHWAddrStr + i);[/align]
[align=left] if (( c>='0' && c<='9' ) || ( c>='a' && c<='f' ))[/align]
[align=left] {[/align]
[align=left] if (c>='0' && c<='9') temp = c - '0'; // 数字[/align]
[align=left] if (c>='a' && c<='f') temp = c - 'a' + 0xa; // 字母[/align]
[align=left] if ( (index % 2) == 1 )[/align]
[align=left] {[/align]
[align=left] value = value*0x10 + temp;[/align]
[align=left] HWAddr[index/2] = value;[/align]
[align=left] }[/align]
[align=left] else value = temp;[/align]
[align=left] index++;[/align]
[align=left] }[/align]
[align=left] if (index == 12) break;[/align]
[align=left] }[/align]
}

// 开始填充各个字段
ARPPACKET ARPPacket; // 定义ARPPACKET结构体变量

memset(&ARPPacket, 0, sizeof(ARPPACKET)); // 数据包初始化
[align=left] [/align]
[align=left] formatStrToMAC(“DLC源MAC字符串”,ARPPacket.dlcHeader.SrcMAC); // DLC帧头[/align]
[align=left] formatStrToMAC(“DLC目的MAC字符串”,ARPPacket.dlcHeader.DesMAC);[/align]
[align=left] [/align]
[align=left] formatStrToMAC(“ARP源MAC字符串”,ARPPacket.arpFrame.Send_HW_Addr); // 源MAC[/align]
[align=left] ARPPacket.arpFrame.Send_Prot_Addr = inet_addr(srcIP); // 源IP[/align]
[align=left] formatStrToMAC(“ARP目的MAC字符串”,ARPPacket.arpFrame.Targ_HW_Addr); // 目的MAC[/align]
[align=left] ARPPacket.arpFrame.Targ_Prot_Addr = inet_addr(desIP); // 目的IP[/align]
[align=left] [/align]
[align=left] ARPPacket.arpFrame.Opcode = htons((unsigned short)arpType); // arp包类型[/align]
[align=left] [/align]
[align=left] // 自动填充的常量[/align]
[align=left] ARPPacket.dlcHeader.Ethertype = htons((unsigned short)0x0806); // DLC Header的以太网类型[/align]
[align=left] ARPPacket.arpFrame.HW_Type = htons((unsigned short)1); // 硬件类型[/align]
[align=left] ARPPacket.arpFrame.Prot_Type = htons((unsigned short)0x0800); // 上层协议类型[/align]
[align=left] ARPPacket.arpFrame.HW_Addr_Len = (unsigned char)6; // MAC地址长度[/align]
ARPPacket.arpFrame.Prot_Addr_Len = (unsigned char)4; // IP地址长度

That’s all ! ^_^
填充完毕之后,我们需要做的就是把我们的ARPPACKET结构体发送出去

2.发送ARP数据包:

我们发送ARP包就要用到winpcap的api了,具体步骤及函数是这样的,为了简单易懂,我把错误处理的地方都去掉了,详见代码
[align=left]/**********************************************************************[/align]
[align=left]* Name & Params::[/align]
[align=left]* SendARPPacket()[/align]
[align=left]* Purpose:[/align]
[align=left]* 发送ARP数据包[/align]
[align=left]* Remarks:[/align]
[align=left]* 用的是winpcap的api函数[/align]
[align=left]***********************************************************************/[/align]
[align=left]void SendARPPacket()[/align]
[align=left]{[/align]
[align=left] char *AdapterDeviceName =GetCurAdapterName(); // 首先获得获得网卡名字[/align]
[align=left] [/align]
[align=left] lpAdapter = PacketOpenAdapter(AdapterDeviceName); // 根据网卡名字打开网卡[/align]
[align=left] [/align]
[align=left] lpPacket = PacketAllocatePacket(); // 给PACKET结构指针分配内存[/align]
[align=left] [/align]
[align=left] PacketInitPacket(lpPacket, &ARPPacket, sizeof(ARPPacket)); //初始化PACKET结构指针[/align]
// 其中的ARPPacket就是我们先前填充的ARP包
[align=left] [/align]
[align=left] PacketSetNumWrites(lpAdapter, 1); // 每次只发送一个包[/align]
[align=left] [/align]
[align=left] PacketSendPacket(lpAdapter, lpPacket, true) // Send !!!!! ^_^[/align]
[align=left] [/align]
[align=left] PacketFreePacket(lpPacket); // 释放资源[/align]
[align=left] PacketCloseAdapter(lpAdapter);[/align]
}

呵呵,至此,关于ARP包最关键的部分就讲完了,你现在就可以来随心所欲的发送自己的ARP包了

既然作为一篇“科普文章”,接下来我再讲一讲与整个项目有关的附加步骤以及说明

三.附加步骤以及说明
1.
如何在VC中使用winpcap驱动

虽然winpcap开发包使用起来非常简便,但是前期准备工作还是要费一番功夫的,缺一不可。^_^
首先就是要安装它的驱动程序了,可以到它的主页下载,更新很快的
http://winpcap.polito.it/install/default.htm
下载WinPcap auto-installer (driver +DLLs),直接安装就好了,或者我提供的代码包里面也有。
希望以后用winpcap作开发的朋友,还需要下载 Developer's pack,解压即可。

然后,需要设置我们工程的附加包含目录为我们下载Developer's pack开发包的Inclulde目录,连接器的附加依赖库设置为Developer's pack的lib目录。
当然,因为我们的工作比较简单,就是借用winpcap发送数据包而已,所以只用从
winpcap开发包的include文件夹中,拷贝Packet32.h,到我们的工程来,并且包含它就可
以,但是要注意,Packet32.h本身还要包含一个Devioctl.h,也要一并拷贝进来,当然还有运
行库Packet.lib,一共就是需要拷贝3个文件了,如果加入库不用我多说了吧,在工程里面设
置,或者是在需要它的地方加入#pragma comment(lib, "Packet.lib")了。

整个项目其实可以分为四个部分,填充数据包、发送数据包、枚举系统网卡列表
相关信息以及枚举系统ARP缓存列表,下面我再讲一下如何获得系统的网卡以及ARP列
表,这两个部分都要用到IP Helper的api,所以要包含<Iphlpapi.h>以及库文件Iphlpapi.lib,
其实都是很简单的,只用寥寥几行就OK了
2.
枚举系统网卡以及信息
最好是先定义关于网卡信息的一个结构体,这样显得结构比较清晰
[align=left]// 网卡信息[/align]
typedef struct tagAdapterInfo

[align=left]{[/align]
[align=left] char szDeviceName[128]; // 名字[/align]
[align=left] char szIPAddrStr[16]; // IP[/align]
[align=left] char szHWAddrStr[18]; // MAC[/align]
DWORD dwIndex; // 编号

}INFO_ADAPTER, *PINFO_ADAPTER;

[align=left]/*********************************************************************[/align]
[align=left]* Name & Params::[/align]
[align=left]* AddAdapInfoToList[/align]
[align=left]* ([/align]
[align=left]* CListCtrl& list : CARPPlayerDlg传入的list句柄[/align]
[align=left]* )[/align]
[align=left]* Purpose:[/align]
[align=left]* 获得系统的网卡信息,并将其添加到list控件中[/align]
[align=left]* Remarks:[/align]
[align=left]* 获得网卡IP及MAC用到了IpHelper api GetAdaptersInfo[/align]
[align=left]******************************************************************/[/align]
[align=left]void AddAdapInfoToList(CListCtrl& list)[/align]
[align=left]{[/align]
[align=left] char tempChar;[/align]
[align=left] ULONG uListSize=1;[/align]
[align=left] PIP_ADAPTER_INFO pAdapter; // 定义PIP_ADAPTER_INFO结构存储网卡信息[/align]
[align=left] int nAdapterIndex = 0;[/align]
[align=left] [/align]
[align=left] DWORD dwRet = GetAdaptersInfo((PIP_ADAPTER_INFO)&tempChar, &uListSize);//关键函数[/align]
[align=left] [/align]
[align=left] if (dwRet == ERROR_BUFFER_OVERFLOW)[/align]
[align=left] {[/align]
[align=left] PIP_ADAPTER_INFO pAdapterListBuffer = (PIP_ADAPTER_INFO)new(char[uListSize]);[/align]
[align=left] dwRet = GetAdaptersInfo(pAdapterListBuffer, &uListSize);[/align]
[align=left] if (dwRet == ERROR_SUCCESS)[/align]
[align=left] {[/align]
[align=left] pAdapter = pAdapterListBuffer;[/align]
[align=left] while (pAdapter) // 枚举网卡然后将相关条目添加到List中[/align]
[align=left] {[/align]
[align=left] // 网卡名字[/align]
CString strTemp = pAdapter->AdapterName;

strTemp = "//Device//NPF_" + strTemp; // 加上前缀

list.InsertItem(nAdapterIndex,strTemp);

[align=left] strcpy(AdapterList[nAdapterIndex].szDeviceName,strTemp);[/align]
[align=left] // IP[/align]
[align=left] strcpy(AdapterList[nAdapterIndex].szIPAddrStr,[/align]
[align=left] pAdapter->IpAddressList.IpAddress.String );[/align]
[align=left] list.SetItemText(nAdapterIndex,1,AdapterList[nAdapterIndex].szIPAddrStr);[/align]
[align=left] // MAC[/align]
[align=left] formatMACToStr( AdapterList[nAdapterIndex].szHWAddrStr, pAdapter->Address );[/align]
[align=left] list.SetItemText(nAdapterIndex,2,AdapterLis[nAdapterIndex].szHWAddrStr);[/align]
[align=left] // 网卡编号[/align]
AdapterList[nAdapterIndex].dwIndex = pAdapter->Index;

[align=left] [/align]
[align=left] pAdapter = pAdapter->Next;[/align]
[align=left] nAdapterIndex ++;[/align]
[align=left] }[/align]
[align=left] delete pAdapterListBuffer;[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]}[/align]
[align=left] [/align]

[align=left]2)获取ARP条目列表[/align]
[align=left]// ARP条目信息[/align]
typedef struct tagARPInfo

[align=left]{[/align]
char szIPAddrStr[16]; // IP

[align=left] char szHWAddrStr[18]; // MAC[/align]
[align=left] DWORD dwType; // 类型[/align]
[align=left]}INFO_ARP, *PINFO_ARP;[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]/**********************************************************************[/align]
[align=left]* Name & Params::[/align]
[align=left]* AddARPInfoToList[/align]
[align=left]* ([/align]
[align=left]* CListCtrl& list : CARPPlayerDlg传入的list句柄[/align]
[align=left]* const short nAdapterIndex : 用户选中的网卡编号[/align]
[align=left]* )[/align]
[align=left]* Purpose:[/align]
[align=left]* 读入系统的ARP缓存列表,.并添加到对话框中[/align]
[align=left]* Remarks:[/align]
[align=left]* 用到了IpHelper api GetIpNetTable[/align]
[align=left]* 而且用到了WinSock的api,所以要包含<WinSock2.h>[/align]
[align=left]*****************************************************************/[/align]
[align=left]void AddARPInfoToList(CListCtrl& list,const short nAdapterIndex)[/align]
[align=left]{[/align]
[align=left] char tempChar;[/align]
[align=left] DWORD dwListSize = 1;[/align]
[align=left] DWORD dwRet;[/align]
[align=left] in_addr inaddr;[/align]
[align=left] list.DeleteAllItems();[/align]
[align=left] [/align]
[align=left] dwRet = GetIpNetTable((PMIB_IPNETTABLE)&tempChar, &dwListSize, TRUE); // 关键函数[/align]
[align=left] if (dwRet == ERROR_INSUFFICIENT_BUFFER)[/align]
[align=left] {[/align]
[align=left] PMIB_IPNETTABLE pIpNetTable = (PMIB_IPNETTABLE)new(char[dwListSize]);[/align]
[align=left] dwRet = GetIpNetTable(pIpNetTable, &dwListSize, TRUE);[/align]
[align=left] if (dwRet == ERROR_SUCCESS)[/align]
[align=left] {[/align]
[align=left] for (int i=0; i<(int)pIpNetTable->dwNumEntries; i++)[/align]
[align=left] {[/align]
[align=left] // IP[/align]
[align=left] inaddr.S_un.S_addr = pIpNetTable->table[i].dwAddr;[/align]
strcpy( ARPList[i].szIPAddrStr, inet_ntoa(inaddr) );

[align=left] // MAC[/align]
formatMACToStr( ARPList[i].szHWAddrStr, pIpNetTable->table[i].bPhysAddr );

// Type

ARPList[i].dwType = pIpNetTable->table[i].dwType;

[align=left] [/align]
[align=left] if (AdapterList[nAdapterIndex].dwIndex != pIpNetTable->table[i].dwIndex) continue;[/align]
[align=left] [/align]
[align=left] list.InsertItem(i,ARPList[i].szIPAddrStr);[/align]
[align=left] list.SetItemText(i,1,ARPList[i].szHWAddrStr);[/align]
[align=left] switch(ARPList[i].dwType) { // 根据type的值来转换成字符显示[/align]
[align=left] case 3:[/align]
[align=left] list.SetItemText(i,2,"Dynamic");[/align]
[align=left] break;[/align]
[align=left] case 4:[/align]
[align=left] list.SetItemText(i,2,"Static");[/align]
[align=left] break;[/align]
[align=left] case 1:[/align]
[align=left] list.SetItemText(i,2,"Invalid");[/align]
[align=left] default:[/align]
[align=left] list.SetItemText(i,2,"Other");[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] delete pIpNetTable;[/align]
[align=left] }[/align]
[align=left]}[/align]
这样一来,我们基本上大功告成了,其他还有一些东西在这里就不讲了,大家可以下载我的代码看看就好了。
下面我们来用ARP包玩一些小把戏 ^_^。
(未完待续)
。。。。。。。。。。。。。。。。
=======================================================================
本篇前两部分地址:
手把手教你玩转ARP包(上)
http://www.csdn.net/Develop/read_article.asp?id=28419
手把手教你玩转ARP包(中上)
http://www.csdn.net/develop/article/28/28421.shtm

------ Finished at 2004-05-30 14:41
------- Made In DLUT | DIP
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐