您的位置:首页 > 理论基础 > 计算机网络

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

2005-01-04 11:58 591 查看
用ARP探测网络中的混杂模式节点

作者:Refdom

由于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 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,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);

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;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: