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

来源:互联网 发布:php 反序列化 编辑:程序博客网 时间:2024/04/30 20:14
由于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就是),可能会让没有在混杂模式的网卡也作出响应。


///////////////////////////////////////////////////////////////////////////////
//
//Detect Promiscuous Node In Network
//
// Author: Refdom
// Email:refdom@263.net
// Home Page:www.opengram.com
//
// 2002/4/14
//
////////////////////////////////////////////////////////////////////////////////

#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 listening
void ListenThread(void* Adapter);
//the function of sending packet
void 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("00E04C6A21DF", 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说明书
原创粉丝点击