作者:CSDN  VC/MFC 网络编程 PiggyXP  ^_^

 
  目录:

二。发送数据包的编程实现
   1.  填充数据包
   2.  发送数据包
三。一些附加步骤及说明
   1.  如果在VC中使用winpcap
   2.  获得网卡信息列表
   3.  获得系统ARP信息列表
 
         ................紧接上文................
 
1.        填充数据包
 
下面我举个填充包头的例子,我首先定义个了一个转换字符的函数,如下

 
/****************************************************************************
 *   Name & Params::
 *             formatStrToMAC
 *             (
 *                 const LPSTR lpHWAddrStr : 用户输入的MAC地址字符串
 *                 unsigned char *HWAddr :   返回的MAC地址字符串(赋给数据包结构体)
 *             )
 *   Purpose:
 *             将用户输入的MAC地址字符转成数据包结构体需要的格式
 ****************************************************************************/
void formatStrToMAC(const LPSTR lpHWAddrStr, unsigned char *HWAddr)
{
       unsigned int i, index = 0, value, temp;
      unsigned char c;
 
      _strlwr(lpHWAddrStr);                                                   // 转换成小写
 
      for (i = 0; i < strlen(lpHWAddrStr); i++)
     {
           c = *(lpHWAddrStr + i);
            if (( c>='0' && c<='9' ) || ( c>='a' && c<='f' ))
           {
               if (c>='0' && c<='9')  temp = c - '0';                         // 数字
               if (c>='a' && c<='f')  temp = c - 'a' + 0xa;               // 字母
               if ( (index % 2) == 1 )
              {
                   value = value*0x10 + temp;
                   HWAddr[index/2] = value;
              }
              else value = temp;
              index++;
         }
               if (index == 12) break;
        }
}
 
// 开始填充各个字段
ARPPACKET ARPPacket;                                                  // 定义ARPPACKET结构体变量
 
    memset(&ARPPacket, 0, sizeof(ARPPACKET));                      // 数据包初始化
 
     formatStrToMAC(“DLC源MAC字符串”,ARPPacket.dlcHeader.SrcMAC);       // DLC帧头
     formatStrToMAC(“DLC目的MAC字符串”,ARPPacket.dlcHeader.DesMAC);
 
     formatStrToMAC(“ARP源MAC字符串”,ARPPacket.arpFrame.Send_HW_Addr);  // 源MAC
     ARPPacket.arpFrame.Send_Prot_Addr = inet_addr(srcIP);              // 源IP
     formatStrToMAC(“ARP目的MAC字符串”,ARPPacket.arpFrame.Targ_HW_Addr); // 目的MAC
     ARPPacket.arpFrame.Targ_Prot_Addr = inet_addr(desIP);               // 目的IP
    
     ARPPacket.arpFrame.Opcode = htons((unsigned short)arpType);        // arp包类型
    
     // 自动填充的常量
     ARPPacket.dlcHeader.Ethertype = htons((unsigned short)0x0806); // DLC Header的以太网类型
     ARPPacket.arpFrame.HW_Type = htons((unsigned short)1);           // 硬件类型
     ARPPacket.arpFrame.Prot_Type = htons((unsigned short)0x0800);    // 上层协议类型
     ARPPacket.arpFrame.HW_Addr_Len = (unsigned char)6;                 // MAC地址长度
     ARPPacket.arpFrame.Prot_Addr_Len = (unsigned char)4;               // IP地址长度
 
That’s all ! ^_^
填充完毕之后,我们需要做的就是把我们的ARPPACKET结构体发送出去
 
2.发送ARP数据包:
 
我们发送ARP包就要用到winpcap的api了,具体步骤及函数是这样的,为了简单易懂,我把错误处理的地方都去掉了,详见代码
/**********************************************************************
*    Name & Params::
*             SendARPPacket()
*    Purpose:
*             发送ARP数据包
*    Remarks:
*             用的是winpcap的api函数
***********************************************************************/
void SendARPPacket()
{
     char *AdapterDeviceName =GetCurAdapterName();     // 首先获得获得网卡名字
 
     lpAdapter = PacketOpenAdapter(AdapterDeviceName);     // 根据网卡名字打开网卡
 
     lpPacket = PacketAllocatePacket();               // 给PACKET结构指针分配内存
 
     PacketInitPacket(lpPacket, &ARPPacket, sizeof(ARPPacket)); //初始化PACKET结构指针
                                             // 其中的ARPPacket就是我们先前填充的ARP包
 
     PacketSetNumWrites(lpAdapter, 1);               // 每次只发送一个包
 
     PacketSendPacket(lpAdapter, lpPacket, true)       // Send !!!!! ^_^
 
     PacketFreePacket(lpPacket);                     // 释放资源
     PacketCloseAdapter(lpAdapter);
}
 
呵呵,至此,关于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.     枚举系统网卡以及信息
最好是先定义关于网卡信息的一个结构体,这样显得结构比较清晰
// 网卡信息
typedef struct tagAdapterInfo         
{
              char szDeviceName[128];           // 名字
              char szIPAddrStr[16];             // IP
              char szHWAddrStr[18];             // MAC
              DWORD dwIndex;                    // 编号         
}INFO_ADAPTER, *PINFO_ADAPTER;
 
/*********************************************************************
*    Name & Params::
*             AddAdapInfoToList
*             (
*                  CListCtrl& list :  CARPPlayerDlg传入的list句柄
*             )
*    Purpose:
*             获得系统的网卡信息,并将其添加到list控件中
*    Remarks:
*             获得网卡IP及MAC用到了IpHelper api GetAdaptersInfo
******************************************************************/
void AddAdapInfoToList(CListCtrl& list)
{
     char tempChar;
     ULONG uListSize=1;
     PIP_ADAPTER_INFO pAdapter;           // 定义PIP_ADAPTER_INFO结构存储网卡信息
     int nAdapterIndex = 0;
 
     DWORD dwRet = GetAdaptersInfo((PIP_ADAPTER_INFO)&tempChar, &uListSize);//关键函数
 
     if (dwRet == ERROR_BUFFER_OVERFLOW)
     {
  PIP_ADAPTER_INFO pAdapterListBuffer = (PIP_ADAPTER_INFO)new(char[uListSize]);
  dwRet = GetAdaptersInfo(pAdapterListBuffer, &uListSize);
  if (dwRet == ERROR_SUCCESS)
  {
     pAdapter = pAdapterListBuffer;
     while (pAdapter)                                              // 枚举网卡然后将相关条目添加到List中
     {
        // 网卡名字
          CString strTemp = pAdapter->AdapterName;                    
          strTemp = "//Device//NPF_" + strTemp;                        // 加上前缀
          list.InsertItem(nAdapterIndex,strTemp);                 
          strcpy(AdapterList[nAdapterIndex].szDeviceName,strTemp);
          // IP
          strcpy(AdapterList[nAdapterIndex].szIPAddrStr,
                                                 pAdapter->IpAddressList.IpAddress.String );
          list.SetItemText(nAdapterIndex,1,AdapterList[nAdapterIndex].szIPAddrStr);
          // MAC
          formatMACToStr( AdapterList[nAdapterIndex].szHWAddrStr, pAdapter->Address );
          list.SetItemText(nAdapterIndex,2,AdapterLis[nAdapterIndex].szHWAddrStr);
          // 网卡编号
          AdapterList[nAdapterIndex].dwIndex = pAdapter->Index;         
 
          pAdapter = pAdapter->Next;
          nAdapterIndex ++;
          }
     delete pAdapterListBuffer;
     }
}
}
 
2)获取ARP条目列表
// ARP条目信息
typedef struct tagARPInfo            
{
     char szIPAddrStr[16];              // IP
     char szHWAddrStr[18];             // MAC
     DWORD dwType;                     // 类型
}INFO_ARP, *PINFO_ARP;
 
 
/**********************************************************************
*    Name & Params::
*             AddARPInfoToList
*             (
*                  CListCtrl& list :             CARPPlayerDlg传入的list句柄
*                  const short nAdapterIndex :   用户选中的网卡编号
*             )
*    Purpose:
*             读入系统的ARP缓存列表,.并添加到对话框中
*    Remarks:
*             用到了IpHelper api GetIpNetTable
*             而且用到了WinSock的api,所以要包含<WinSock2.h>
*****************************************************************/
void AddARPInfoToList(CListCtrl& list,const short nAdapterIndex)
{
     char tempChar;
     DWORD dwListSize = 1;
     DWORD dwRet;
     in_addr inaddr;
     list.DeleteAllItems();
 
     dwRet = GetIpNetTable((PMIB_IPNETTABLE)&tempChar, &dwListSize, TRUE);  // 关键函数
     if (dwRet == ERROR_INSUFFICIENT_BUFFER)
     {
         PMIB_IPNETTABLE pIpNetTable = (PMIB_IPNETTABLE)new(char[dwListSize]);
         dwRet = GetIpNetTable(pIpNetTable, &dwListSize, TRUE);
         if (dwRet == ERROR_SUCCESS)
         {
              for (int i=0; i<(int)pIpNetTable->dwNumEntries; i++)
              {
                  // IP
                   inaddr.S_un.S_addr = pIpNetTable->table[i].dwAddr;
                   strcpy( ARPList[i].szIPAddrStr, inet_ntoa(inaddr) );  
                   // MAC
                   formatMACToStr( ARPList[i].szHWAddrStr, pIpNetTable->table[i].bPhysAddr );
                   // Type
                   ARPList[i].dwType = pIpNetTable->table[i].dwType;        
 
                   if (AdapterList[nAdapterIndex].dwIndex != pIpNetTable->table[i].dwIndex)                                                       continue;
 
                   list.InsertItem(i,ARPList[i].szIPAddrStr);
                   list.SetItemText(i,1,ARPList[i].szHWAddrStr);
                   switch(ARPList[i].dwType) {           // 根据type的值来转换成字符显示
                   case 3:
                       list.SetItemText(i,2,"Dynamic");
                       break;
                   case 4:
                       list.SetItemText(i,2,"Static");
                       break;
                   case 1:
                       list.SetItemText(i,2,"Invalid");
                   default:
                       list.SetItemText(i,2,"Other");
                   }
              }
         }
         delete pIpNetTable;
     }
}
        这样一来,我们基本上大功告成了,其他还有一些东西在这里就不讲了,大家可以下载我的代码看看就好了。
        下面我们来用ARP包玩一些小把戏 ^_^。
        (未完待续)
       。。。。。。。。。。。。。。。。

手把手教你玩转ARP包(三)相关推荐

  1. 手把手教你玩转ARP包(一)

    原文地址:http://blog.csdn.net/piggyxp/article/details/19606 前   言 首先要感谢网络安全资深专家卢湖川博士以及VC网络版的limin朋友提供的资料 ...

  2. 手把手教你玩转ARP包(四)

    原文链接:http://blog.csdn.net/piggyxp/article/details/19609 作者: CSDN  VC/MFC 网络编程 PiggyXP  ^_^ 本篇目录:     ...

  3. 手把手教你玩转ARP包(二)

    原文链接:http://blog.csdn.net/piggyxp/article/details/19607 作者:    CSDN  VC/MFC 网络编程 PiggyXP  ^_^   目录: ...

  4. 手把手教你玩转SOCKET模型:完成端口(Completion Port)详解

    这篇文档我非常详细并且图文并茂的介绍了关于网络编程模型中完成端口的方方面面的信息,从API的用法到使用的步骤,从完成端口的实现机理到实际使用的注意事项,都有所涉及,并且为了让朋友们更直观的体会完成端口 ...

  5. 手把手教你玩转SOCKET模型之重叠I/O篇(下)

    http://blog.csdn.net/PiggyXP/archive/2004/09/23/114908.aspx 四.     实现重叠模型的步骤 作了这么多的准备工作,费了这么多的笔墨,我们终 ...

  6. 手把手教你玩转SOCKET模型:完成例程(Completion Routine)篇

    本文假设你已经对重叠I/O的机制已有了解,否则请先参考本系列的前一篇<手把手教你玩转SOCKET模型之重叠I/O篇>: 目录: 1.完成例程的优点 2.完成例程的基本原理 3.关于完成例程 ...

  7. 手把手教你玩转网络编程模型之完成例程(Completion Routine)

    前  言 记得写这个系列的上一篇文章的时候已经是四年前了,准确的说是四年半以前了,翻开我尘封已久的IO模型里面的"完成例程"的实现方式及示例代码. 本文凝聚着笔者心血,如要转载,请 ...

  8. 手把手教你玩转网络编程模型之完成例程(Completion Routine)篇(下)-转

    续 手把手教你玩转网络编程模型之完成例程(Completion Routine)篇(上) 四.         完成例程的实现步骤 基础知识方面需要知道的就是这么多,下面我们配合代码,来一步步的讲解如 ...

  9. 手把手教你玩转CSS3 3D技术

    手把手教你玩转 CSS3 3D 技术 要玩转css3的3d,就必须了解几个词汇,便是透视(perspective).旋转(rotate)和移动(translate).透视即是以现实的视角来看屏幕上的2 ...

最新文章

  1. 深入理解:RabbitMQ的前世今生
  2. c语言求婚代码大全,这是我见过最浪漫的程序员求婚方式
  3. jQuery的.bind()、.live()和.delegate()之间区别
  4. SQLServer数据库的备份/恢复的3中策略实例
  5. 如何在Ubuntu中安装java jdk
  6. 夯实“茄克”核心竞争力,高端新国货谋图百年基业
  7. OpenGL HDR高动态光照渲染的实例
  8. 关于IIS 7.5 限制连接数与流量限制模块
  9. 走台阶 OR 台阶走——《狂人C》习题解答14(第三章习题4)
  10. C++ 公有继承、保护继承和私有继承中类成员的访问权限的控制
  11. C#里枚举类型以及值引用和地址引用差别演示代码
  12. postman上传多个文件_不要只会使用 postman,你还需掌握 curl 的使用!
  13. Android 联系人信息的获取
  14. ajax编辑教程,今天手动编写了一个简易的 ajax 发起器(JavaScript)
  15. 第四章 软件项目进度管理
  16. 基于stm32的智能风扇设计
  17. vc++datamatrix二维码识别
  18. kubernetes 的 滚动升级和回滚(rollout)
  19. I2P和TOR 有趣网络精灵
  20. 朱清时——物理学步入禅境:缘起性空-(技术工作者上升到哲学思维)

热门文章

  1. hadoop的安装-配置文件修改
  2. html5无意义标签,无意义的div和span标签
  3. =在php中,PHPExcel在PHP7中,save(‘php://output’)出现ERR_INVALID_RESPONSE错误的解决方法...
  4. 单链表之无头和有头--逆序
  5. 图解系列之垃圾收集标记整理算法
  6. JavaScript进行UTF-8编码与解码
  7. 关于Web报表FineReport打印的开发应用案例
  8. linux+tomcat+apache
  9. 偏见为什么是数据科学领域的一个大问题
  10. CSS+DIV定位分析(relative,absolute,static,fixed)