迟馨
级别:新手上路 威望:0 经验:0 货币:67 体力: 来源:202.98.20.* 总发帖数:5 注册日期:2002-05-13
|
|
查看 邮件 主页 QQ 消息 引用 复制 下载
用ARP探测网络中的混杂模式节点
原创:refdom(refdom) 来源:www.opengram.com
Author: Refdom
Email: refdom@263.net HomePage: www.opengram.com
2002/4/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说明书
|