隨筆-17  評論-64  文章-79  trackbacks-1
          作者:
          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 Helperapi,所以要包含<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包玩一些小把戲 ^_^。
          posted on 2007-02-16 15:45 飛鳥 閱讀(456) 評論(0)  編輯  收藏 所屬分類: VC
          主站蜘蛛池模板: 新源县| 商都县| 吐鲁番市| 灯塔市| 武宁县| 新宾| 石柱| 昆山市| 临海市| 深水埗区| 三门峡市| 固安县| 泊头市| 长海县| 松阳县| 湾仔区| 车险| 荃湾区| 奎屯市| 日土县| 合川市| 武城县| 盐城市| 三原县| 十堰市| 大化| 醴陵市| 隆德县| 孟州市| 萨嘎县| 城市| 祥云县| 怀柔区| 祁阳县| 阜南县| 炉霍县| 宜君县| 秦安县| 永和县| 双辽市| 镇江市|