如何控制混杂模式

如何控制混杂模式,第1张

一、在普通程序中设置网卡混杂模式

在普通程序中普遍用ioctl函数来设置,该函数很值得大家好好的了解,因为它的使用非常的广泛。下面

给出设置网卡混杂模式的实现代码:

#include

#include

#include

#include

int set_all_promisc()

{ struct ifreq ifaces[16]

struct ifconf param

int sock, i

param.ifc_len = sizeof(ifaces)

param.ifc_req = ifaces

sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)

if (sock <= 0)

return 0

if (ioctl(sock, SIOCGIFCONF, ¶m))

return 0

for (i = 0i <param.ifc_len / sizeof(struct ifreq)i++) {

if (ioctl(sock, SIOCGIFFLAGS, ifaces + i))

return 0

ifaces[i].ifr_flags |= IFF_PROMISC/*如果恢复网卡模式,把|= 改成 &=~ */

if (ioctl(sock, SIOCSIFFLAGS, ifaces + i))

return 0

}

return 1

}

二、在核心空间中设置混杂模式

1.在kernel-2.2.x 中

static struct device *sniffer_dev = NULL

static unsigned short old_flags, old_gflags

int init_module ( void ) /* 模块初始化 */

{

......

sniffer_dev = dev_get("eth0")

if ( sniffer_dev != NULL )

{

/* thanks for difeijing of whnet's Security */

old_flags = sniffer_dev->flags

old_gflags = sniffer_dev->gflags

/*

* 参看net/core/dev.c里的dev_change_flags()

* ->gflags的作用是避免多次重复设置混杂模式,没有其他特别含义

*/

/* 设置混杂模式 */

sniffer_dev->flags |= IFF_PROMISC

sniffer_dev->gflags |= IFF_PROMISC

start_bh_atomic()

/* 注意,这个回调函数还是会报告 eth0: Setting promiscuous mode. */

sniffer_dev->set_multicast_list( sniffer_dev )

end_bh_atomic()

}

......

return 0

}

void cleanup_module(void)

{

......

if (sniffer_dev != NULL)

{

/* 恢复原有模式 */

sniffer_dev>flags = old_flags

sniffer_dev>gflags = old_gflags

start_bh_atomic()

sniffer_dev>set_multicast_list( sniffer_dev )

end_bh_atomic()

}

......

}

2.在kernel-2.4.x 中

在2.4中有了许多变化,首先struct device结构改为struct net_device, 再者dev_get

功能改为测试网络设备是否存在,真正的设置网络混杂模式的函数改为

void dev_set_promiscuity(struct net_device *dev, int inc);

其中根据inc的值来设置混杂模式还是恢复原来设置模式,通过计数来恢复原来模式,这样的好处就是:不会和其他的程序冲突,不在像上述两种实现方式中恢复原来模式就全恢复了,不管还有没有其他的程序是否也设置了混杂模式。现在就通过计数来恢复原来的模式,只要当计数相加为零才设置成普通模式。

linux源代码的注释如下:

/**

* dev_set_promiscuity - update promiscuity count on a device

* @dev: device

* @inc: modifier

*

* Add or remove promsicuity from a device. While the count in the device

* remains above zero the interface remains promiscuous. Once it hits zero

* the device reverts back to normal filtering operation. A negative inc

* value is used to drop promiscuity on the device.

*/

设置网卡混杂模式的实现代码如下:

struct net_device *sniffer_dev = NULL

int dev_flags = 0

int init_module ( void ) /* 模块初始化 */

{

......

sniffer_dev = dev_get_by_name("eth0")

if (sniffer_dev != NULL)

{

dev_flags = 1

dev_set_promiscuity(sniffer_dev, 1)

dev_put(sniffer_dev)

sniffer_dev = NULL

}

......

return 0

}

void cleanup_module(void)

{

......

if (dev_flags)

{

sniffer_dev = dev_get_by_name("eth0")

if (sniffer_dev != NULL)

{

dev_flags = 0

dev_set_promiscuity(sniffer_dev, -1)/*注意此处的第二个参数*/

dev_put(sniffer_dev)

sniffer_dev = NULL

}

}

......

}

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

根据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: suchasplus

// Email: suchasplus@gmail.com

// Home Page: spaces.msn.com/suchasplus

//

// 2006/02/02

//

////////////////////////////////////////////////////////////////////////////////

#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_IP0x0800/* type: IP*/

#define EPT_ARP0x0806/* type: ARP */

#define EPT_RARP0x8035/* type: RARP */

#define ARP_HARDWARE0x0001/* Dummy type for 802.3 frames */

#defineARP_REQUEST0x0001/* ARP request */

#defineARP_REPLY0x0002/* ARP reply */

#define Max_Num_Adapter 10

#pragma pack(push, 1)

typedef struct ehhdr

{

unsigned chareh_dst[6] /* destination ethernet addrress */

unsigned chareh_src[6] /* source ethernet addresss */

unsigned shorteh_type /* ethernet pachet type*/

}EHHDR, *PEHHDR

typedef struct arphdr

{

unsigned shortarp_hrd /* format of hardware address */

unsigned shortarp_pro /* format of protocol address */

unsigned chararp_hln /* length of hardware address */

unsigned chararp_pln /* length of protocol address */

unsigned shortarp_op /* ARP/RARP operation */

unsigned chararp_sha[6] /* sender hardware address */

unsigned longarp_spa /* sender protocol address */

unsigned chararp_tha[6] /* target hardware address */

unsigned longarp_tpa /* target protocol address */

}ARPHDR, *PARPHDR

typedef struct arpPacket

{

EHHDRehhdr

ARPHDRarphdr

} 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]

LPADAPTERlpAdapter

WCHARAdapterName[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 = 0i <AdapterNumi++)

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]

LPADAPTERlpAdapter = (LPADAPTER) Adapter

LPPACKETlpPacket

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

}

拿vc6.0调试通过

Sniffer,中文可以翻译为嗅探器,是一种威胁性极大的被动攻击工具。使用这种工具,可以监视网络的状态、数据流动情况以及网络上传输的信息。当信息以明文的形式在网络上传输时,便可以使用网络监听的方式来进行攻击。将网络接口设置在监听模式,便可以将网上传输的源源不断的信息截获。黑客们常常用它来截获用户的口令。据说某个骨干网络的路由器曾经被黑客攻人,并嗅探到大量的用户口令。本文将详细介绍Sniffer的原理和应用。 一、Sniffer 原理 1.网络技术与设备简介 在讲述Sni计er的概念之前,首先需要讲述局域网设备的一些基本概念。 数据在网络上是以很小的称为帧(Frame)的单位传输的,帧由几部分组成,不同的部分执行不同的功能。帧通过特定的称为网络驱动程序的软件进行成型,然后通过网卡发送到网线上,通过网线到达它们的目的机器,在目的机器的一端执行相反的过程。接收端机器的以太网卡捕获到这些帧,并告诉 *** 作系统帧已到达,然后对其进行存储。就是在这个传输和接收的过程中,嗅探器会带来安全方面的问题。 每一个在局域网(LAN)上的工作站都有其硬件地址,这些地址惟一地表示了网络上的机器(这一点与Internet地址系统比较相似)。当用户发送一个数据包时,这些数据包就会发送到LAN上所有可用的机器。 在一般情况下,网络上所有的机器都可以“听”到通过的流量,但对不属于自己的数据包则不予响应(换句话说,工作站A不会捕获属于工作站B的数据,而是简单地忽略这些数据)。如果某个工作站的网络接口处于混杂模式(关于混杂模式的概念会在后面解释),那么它就可以捕获网络上所有的数据包和帧。 2.网络监听原理 Sniffer程序是一种利用以太网的特性把网络适配卡(NIC,一般为以太网卡)置为杂乱(promiscuous)模式状态的工具,一旦网卡设置为这种模式,它就能接收传输在网络上的每一个信息包。 普通的情况下,网卡只接收和自己的地址有关的信息包,即传输到本地主机的信息包。要使Sniffer能接收并处理这种方式的信息,系统需要支持BPF,Linux下需要支持SOCKET一PACKET。但一般情况下,网络硬件和TCP/IP堆栈不支持接收或者发送与本地计算机无关的数据包,所以,为了绕过标准的TCP/IP堆栈,网卡就必须设置为我们刚开始讲的混杂模式。一般情况下,要激活这种方式,内核必须支持这种伪设备Bpfilter,而且需要root权限来运行这种程序,所以sniffer需要root身份安装,如果只是以本地用户的身份进人了系统,那么不可能唤探到root的密码,因为不能运行Sniffer。 基于Sniffer这样的模式,可以分析各种信息包并描述出网络的结构和使用的机器,由于它接收任何一个在同一网段上传输的数据包,所以也就存在着捕获密码、各种信息、秘密文档等一些没有加密的信息的可能性。这成为黑客们常用的扩大战果的方法,用来夺取其他主机的控制权 3 Snifffer的分类 Sniffer分为软件和硬件两种,软件的Sniffer有 NetXray、Packetboy、Net monitor等,其优点是物美价廉,易于学习使用,同时也易于交流;缺点是无法抓取网络上所有的传输,某些情况下也就无法真正了解网络的故障和运行情况。硬件的Sniffer通常称为协议分析仪,一般都是商业性的,价格也比较贵。 实际上本文中所讲的Sniffer指的是软件。它把包抓取下来,然后打开并查看其中的内容,可以得到密码等。Sniffer只能抓取一个物理网段内的包,就是说,你和监听的目标中间不能有路由或其他屏蔽广播包的设备,这一点很重要。所以,对一般拨号上网的用户来说,是不可能利用Sniffer来窃听到其他人的通信内容的。 4.网络监听的目的 当一个黑客成功地攻陷了一台主机,并拿到了root权限,而且还想利用这台主机去攻击同一网段上的其他主机时,他就会在这台主机上安装Sniffer软件,对以太网设备上传送的数据包进行侦听,从而发现感兴趣的包。如果发现符合条件的包,就把它存到一个LOg文件中去。通常设置的这些条件是包含字“username”或“password”的包,这样的包里面通常有黑客感兴趣的密码之类的东西。一旦黑客截获得了某台主机的密码,他就会立刻进人这台主机。 如果Sniffer运行在路由器上或有路由功能的主机上,就能对大量的数据进行监控,因为所有进出网络的数据包都要经过路由器。 Sniffer属于第M层次的攻击。就是说,只有在攻击者已经进入了目标系统的情况下,才能使用Sniffer这种攻击手段,以便得到更多的信息。 Sniffer除了能得到口令或用户名外,还能得到更多的其他信息,比如一个重要的信息、在网上传送的金融信息等等。Sniffer几乎能得到任何在以太网上传送的数据包。 Sniffer是一种比较复杂的攻击手段,一般只有黑客老手才有能力使用它,而对于一个网络新手来说,即使在一台主机上成功地编译并运行了Sniffer,一般也不会得到什么有用的信息,因为通常网络上的信息流量是相当大的,如果不加选择地接收所有的包,然后从中找到所需要的信息非常困难;而且,如果长时间进行监听,还有可能把放置Sniffer的机器的硬盘撑爆。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/7615730.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-07
下一篇2023-04-07

发表评论

登录后才能评论

评论列表(0条)

    保存