[转]用ARP探测网络中的混杂模式节点

    技术2022-05-11  92

    用ARP探测网络中的混杂模式节点

        由于sniffer的危害,检测网络中是否存在sniffer也非常重要。Anti-Sniff就相应地产生,来检测网络中的sniffer。

        检测sniffer的办法有很多,比如有些功能强大的sniffer会对IP地址进行解析获得机器名,那么可以通过发送畸形数据包等待sniffer进行DNS解析等等,但是这些办法局限太大了。

        根据sniffer的基本工作原理,其核心就是设置网卡模式为 promiscuous(混杂模式),如果能够检测到网络有是混杂模式的网卡,那么就可以判断可能存在一个sniffer。ARP协议在深入嗅探中很有作用,同时也可以用于进行嗅探器的侦测。

        在混杂模式中,网卡进行包过滤不同于普通模式。本来在普通模式下,只有本地地址的数据包或者广播(多播等)才会被网卡提交给系统核心,否则的话,这些数据包就直接被网卡抛弃。现在,混合模式让所有经过的数据包都传递给系统核心,然后被sniffer等程序利用。因此,如果能利用中间的“系统核心”,就能有效地进行是否混杂模式的检测。系统核心也会对一些数据包进行过滤,但是,和网卡的标准不一样的是。

        以Windows系统为例(实验可得):

    FF-FF-FF-FF-FF-FF:这个是一个正规的广播地址,不管是正常模式还是其他模式,都会被网卡接收并传递给系统核心。FF-FF-FF-FF-FF-00:这个地址对于网卡来说,不是一个广播地址,在正常模式下会被网卡抛弃,但是系统核心是认为这个地址同FF-FF-FF-FF-FF-FF是完全一样的。如果处于混杂模式,将被系统核心接收,并认为是一个广播地址。所有的Windows操作系统都是如此。FF-FF-00-00-00-00:Windows核心只对前面两字节作判断,核心认为这是一个同FF-FF-FF-FF-FF-FF一样的广播地址。这就是为什么FF-FF-FF-FF-FF-00也是广播地址的原因。FF-00-00-00-00-00:对于Win9x或WinME,则是检查前面的一个字节。因此会认为这个是一个广播地址。        而对于LINUX内核,我则不清楚,不过从一些资料得到会判断一个group bit,不清楚具体什么意思,但是基本上就是认为FF-00-00-00-00-00,是FF-FF-FF-FF-FF-FF一个类别的吧。(望熟悉LINUX者指点)

        所以,目的就要让正常模式的网卡抛弃掉探测包,而让混杂模式的系统核心能够处理探测。发送一个目的地址为:FF-FF-FF-FF-FF-FE(系统会认为属于广播地址)的ARP请求,对于普通模式(广播等)的网卡,这个地址不是广播地址,就会直接抛弃,而如果处于混杂模式,那么ARP请求就会被系统核心当作广播地址处理,然后提交给sniffer程序。系统核心就会应答这个ARP请求。

        antisniffer也采用了这样的策略进行检测。

        下面这个例子就是FF-FF-FF-FF-FF-FE的ARP请求,可以对网络中的每个节点都发送这样的ARP请求。如果有一般的sniffer存在,并设置网卡为混杂模式,那么系统核心就会作出应答,可以判断这些节点是否存在嗅探器了。这种检测办法也是有局限的,对于那些修改内核的sniffer,就没有办法了,不过这种Sniffer毕竟属于少数还有就是Win2k中一些动态加载的包捕获驱动(WinPcap就是),可能会让没有在混杂模式的网卡也作出响应。

    #include "stdafx.h"#include "Mac.h" //GetMacAddr(),我写的把字符串转换为MAC地址的函数,就不列在这里了#include <stdio.h>#include <conio.h>#include <Packet32.h>#include <Winsock2.h>#include <process.h>#include <ntddndis.h>

    #pragma comment (lib, "packet.lib")#pragma comment (lib, "ws2_32.lib")

    #define EPT_IP  0x0800   /* type: IP */#define EPT_ARP  0x0806   /* type: ARP */#define EPT_RARP 0x8035   /* type: RARP */#define ARP_HARDWARE    0x0001   /* Dummy type for 802.3 frames  */#define ARP_REQUEST 0x0001   /* ARP request */#define ARP_REPLY 0x0002   /* ARP reply */

    #define Max_Num_Adapter 10

    #pragma pack(push, 1)

    typedef struct ehhdr { unsigned char eh_dst[6];  /* destination ethernet addrress */ unsigned char eh_src[6];  /* source ethernet addresss */ unsigned short eh_type;  /* ethernet pachet type */}EHHDR, *PEHHDR;

    typedef struct arphdr{ unsigned short arp_hrd;   /* format of hardware address */ unsigned short arp_pro;   /* format of protocol address */ unsigned char arp_hln;   /* length of hardware address */ unsigned char arp_pln;   /* length of protocol address */ unsigned short arp_op;    /* ARP/RARP operation */

     unsigned char arp_sha[6];   /* sender hardware address */ unsigned long arp_spa;   /* sender protocol address */ unsigned char arp_tha[6];   /* target hardware address */ unsigned long arp_tpa;   /* target protocol address */}ARPHDR, *PARPHDR;

    typedef struct arpPacket{ EHHDR ehhdr; ARPHDR arphdr;} ARPPACKET, *PARPPACKET;

    #pragma pack(pop)

    //the thread for listeningvoid ListenThread(void* Adapter);//the function of sending packetvoid SendARPPacket(void* Adapter);BOOL DetectIsSniffer(LPPACKET lpPacket);

    char g_szMyMacAddr[] = "AAAAAAAAAAAA";char g_szMyIP[]      = "192.168.1.1";char g_szTargetIP[]  = "192.168.1.2";

    int main(int argc, char* argv[]){ static char AdapterList[Max_Num_Adapter][1024];  LPADAPTER lpAdapter; WCHAR  AdapterName[2048]; WCHAR  *temp,*temp1;

     ULONG AdapterLength = 1024;  int AdapterNum = 0; int nRetCode, i;

     //Get The list of Adapter if(PacketGetAdapterNames((char*)AdapterName, &AdapterLength) == FALSE) {  printf("Unable to retrieve the list of the adapters!/n");  return 0; }

     temp = AdapterName; temp1 = AdapterName; i = 0; while ((*temp != '/0')||(*(temp-1) != '/0')) {  if (*temp == '/0')   {   memcpy(AdapterList[i],temp1,(temp-temp1)*2);   temp1 = temp+1;   i++;  }    temp++; }  AdapterNum = i; for (i = 0; i < AdapterNum; i++)  wprintf(L"/n%d- %s/n", i+1, AdapterList[i]); printf("/n");  //Default open the 0 lpAdapter = (LPADAPTER) PacketOpenAdapter((LPTSTR) AdapterList[0]); if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE)) {  nRetCode = GetLastError();  printf("Unable to open the driver, Error Code : %lx/n", nRetCode);  return 0; }

     //begin listening _beginthread(ListenThread, 0, (void*) lpAdapter);

     Sleep(500);

     //send the packet _beginthread(SendARPPacket, 0, (void*) lpAdapter);

     Sleep(2000);

     printf ("/n/nDetecting end./n");

     // close the adapter and exit PacketCloseAdapter(lpAdapter);

     return 0;}

    void SendARPPacket(void* Adapter){ char MacAddr[6]; char szPacketBuf[600]; LPADAPTER lpAdapter = (LPADAPTER) Adapter; LPPACKET lpPacket; ARPPACKET ARPPacket;

     lpPacket = PacketAllocatePacket(); if(lpPacket == NULL) {  printf("/nError:failed to allocate the LPPACKET structure./n");  return; }

     ZeroMemory(szPacketBuf, sizeof(szPacketBuf));

     // the fake mac of multicast if (!GetMacAddr("FFFFFFFFFFFE", MacAddr)) {  printf ("Get Mac address error!/n");  goto Exit0; } memcpy(ARPPacket.ehhdr.eh_dst, MacAddr, 6);

     //the MAC of sender if (!GetMacAddr(g_szMyMacAddr, MacAddr)) {  printf ("Get Mac address error!/n");  goto Exit0; } memcpy(ARPPacket.ehhdr.eh_src, MacAddr, 6);

     ARPPacket.ehhdr.eh_type = htons(EPT_ARP);

     //arp header ARPPacket.arphdr.arp_hrd = htons(ARP_HARDWARE); ARPPacket.arphdr.arp_pro = htons(EPT_IP); ARPPacket.arphdr.arp_hln = 6; ARPPacket.arphdr.arp_pln = 4; ARPPacket.arphdr.arp_op = htons(ARP_REQUEST);

     if (!GetMacAddr(g_szMyMacAddr, MacAddr)) {  printf ("Get Mac address error!/n");  goto Exit0; } memcpy(ARPPacket.arphdr.arp_sha, MacAddr, 6); ARPPacket.arphdr.arp_spa = inet_addr(g_szMyIP);

     if (!GetMacAddr("000000000000", MacAddr)) {  printf ("Get Mac address error!/n");  goto Exit0; } memcpy(ARPPacket.arphdr.arp_tha , MacAddr, 6); ARPPacket.arphdr.arp_tpa = inet_addr(g_szTargetIP);

     memcpy(szPacketBuf, (char*)&ARPPacket, sizeof(ARPPacket)); PacketInitPacket(lpPacket, szPacketBuf, 60);

     if(PacketSetNumWrites(lpAdapter, 1)==FALSE) {  printf("warning: Unable to send more than one packet in a single write!/n"); }  if(PacketSendPacket(lpAdapter, lpPacket, TRUE)==FALSE) {  printf("Error sending the packets!/n");  goto Exit0; }

     printf ("Send ok!/n/n");

    Exit0: PacketFreePacket(lpPacket); _endthread();}

    void ListenThread(void* Adapter){ LPPACKET lpPacket; LPADAPTER lpAdapter = (LPADAPTER) Adapter; char buffer[256000];

     if((lpPacket = PacketAllocatePacket())==NULL){  printf("/nError: failed to allocate the LPPACKET structure.");  return; } PacketInitPacket(lpPacket,(char*)buffer,256000);

     // set the network adapter in promiscuous mode  if(PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_DIRECTED)==FALSE){   printf("Warning: unable to set promiscuous mode!/n"); }

     // set buffer in the driver if(PacketSetBuff(lpAdapter,512000)==FALSE){   printf("Unable to set the kernel buffer!/n");   return; }

     // set second read timeout if(PacketSetReadTimeout(lpAdapter, 200)==FALSE){   printf("Warning: unable to set the read tiemout!/n"); } //main capture loop printf("Listen..../n"); while(true) {     // capture the packets  if(PacketReceivePacket(lpAdapter, lpPacket, TRUE)==FALSE){   printf("Error: PacketReceivePacket failed");   return ;  }  //  DetectIsSniffer(lpPacket); }

     PacketFreePacket(lpPacket);

     // close the adapter and exit PacketCloseAdapter(lpAdapter); _endthread();}

    BOOL DetectIsSniffer(LPPACKET lpPacket){ BOOL bFlag = FALSE; PARPHDR pARPHeader; PARPPACKET pARPPacket; char MacAddr[6];

     GetMacAddr(g_szMyMacAddr, MacAddr); pARPPacket = (PARPPACKET) ((char*)lpPacket->Buffer + 20);

     if (pARPPacket->ehhdr.eh_type == htons(EPT_IP))  return FALSE;

     if (strcmp((char*)(pARPPacket->ehhdr.eh_dst), MacAddr) == 0  && pARPPacket->ehhdr.eh_type == htons(EPT_ARP)) {  char szTemp[10];

      pARPHeader = (PARPHDR)((char*)lpPacket->Buffer + 20 + sizeof(EHHDR));

      memcpy(szTemp, &pARPHeader->arp_spa, sizeof(pARPHeader->arp_spa));  printf ("A PROMISCUOUS NODE EXISTS!!/n");  printf ("/tIP:%s/n/n", inet_ntoa(*((struct in_addr *)(szTemp))));  return TRUE; } return FALSE;}

    Reference:

    1、Securiteam 《Detecting sniffers on your network》、  《AntiSniff - find sniffers on your local network》2、l0pht.com的Antisniffer说明书


    最新回复(0)