sniffer技术原理及应用,包括编程方法和工具使用

Bertha 。 2022-08-24 01:30 120阅读 0赞

sniffer技术原理及应用,包括编程方法和工具使用

http://www.hacker.com.cn/ 2008-11-2 0:03:46 黑客防线















sniffer技术原理及应用,包括编程方法和工具使用


sniffer中文翻译过来就是嗅探器,在当前网络技术中使用得非常得广泛。sniffer既可以做为网络故 

障的诊断工具,也可以作为黑客嗅探和监听的工具。最近两年,网络监听(sniffer)技术出现了新的 

重要特征。传统的sniffer技术是被动地监听网络通信、用户名和口令。而新的sniffer技术出现了主 

动地控制通信数据的特点,把sniffer技术扩展到了一个新的领域。Sniffer 技术除了目前在传统的 

网络侦测管理外,也开始被应用在资讯保全的领域。可以这样说,sniffer技术是一把双刃剑,如何 

更好的利用它,了解它的一些特性,将能使这项技术更好的为我们带来便利。 

sniffer的编程方法比较通用的有以下几种,1.winpcap 这是一个比较通用的库,相信做过抓包的 

工具大多数人都不会太陌生 2.raw socket 在2000以后的版本都支持此项功能,2000 server有个网络监视器就是基于raw socket 3.tdi,ndis,spi,hook socket技术,这种技术比较大的不同是可以将包截取而不是仅仅获得包的一份拷贝。总的说来,一般以前两者居多。 

我这里提的都还比较片面,更多的需要大家来补充。我办这个专题的目的是希望大家共同来了解,讨论sniffer技术,让更多的人参与进来,让大家知道,这个板块能够给大家带来真正想要的东西。 

warton: 

libpcap是个好东西,linux,windows下都能用,很多入侵检测之类的安全系统都是以这为核心。不 

过我一直没用过它,不知道它的跨平台性如何? 

要用spi的话,看看xfilter的代码和书,特别是那本书上讲得不错,可惜一直没用它做出什么东西来。 

raw socket写的sniffer比较多,网上代码也很多! 

昨天见csdn首页有几篇关于sniffer的文章,保存了,还没来得及看… 

俺明天来说说目前常用的sniffer类工具和它们的技术实现! 



csdn首页的两篇文章,大家可以看看,里面好像还有几篇,暂时找不到了 



http://www.csdn.net/develop/article/21/21363.shtm 



http://www.csdn.net/develop/article/21/21352.shtm 



http://www.csdn.net/develop/article/15/15919.shtm 



netsys2: 



一)winpcap驱动简介 

  winpcap(windows packet capture)是windows平台下一个免费,公共的网络访问系统。开 



发winpcap这个项目的目的在于为win32应用程序提供访问网络底层的能力。它提供了以下的各项 



功能: 

  1> 捕获原始数据报,包括在共享网络上各主机发送/接收的以及相互之间交换的数据报; 

  2> 在数据报发往应用程序之前,按照自定义的规则将某些特殊的数据报过滤掉; 

  3> 在网络上发送原始的数据报; 

  4> 收集网络通信过程中的统计信息。 



   



winpcap的主要功能在于独立于主机协议(如TCP-IP)而发送和接收原始数据报。也就是说,winp 



cap不能阻塞,过滤或控制其他应用程序数据报的发收,它仅仅只是监听共享网络上传送的数据报。因此,它不能用于QoS调度程序或个人防火墙。 



  目前,winpcap开发的主要对象是windows NT/2000/XP,这主要是因为在使用winpcap的 



用户中只有一小部分是仅使用windows 95/98/Me,并且M$也已经放弃了对win9x的开发。因 



此本文相关的程序T-ARP也是面向NT/2000/XP用户的。其实winpcap中的面向9x系统的概念和 



NT系统的非常相似,只是在某些实现上有点差异,比如说9x只支持ANSI编码,而NT系统则提倡使 



用Unicode编码。 



zzhong2: 

有个软件叫sniffer pro.可以作网管软件用,有很多功能,可监视网络运行情况,每台网内机器的数据 



流量,实时反映每台机器所访问IP以及它们之间的数据流通情况,可以抓包,可对过滤器进行设置,以便 



只抓取想要的包,比如POP3包,smtp包,ftp包等,并可从中找到邮箱用户名和密码,还有ftp用户名和 



密码.它还可以在使用交换机的网络上监听,不过要在交换机上装它的一个软件. 

还有一个简单的监听软件叫 Passwordsniffer,可截获邮箱用户名和密码,还有ftp用户名和密码,它 



只能用在用HUB网络上 

以上两个软件都可在小凤居上下载到

http://www.chinesehack.org/ 





warton: 

libpcap的最新版本是0.7.2,下载很多(基于linux/unix) 

winpcap的最新版本是3.0 

这里有winpcap的源代码

http://download.pchome.net/php/dl.php?sid=11474 

著名软件tcpdump及ids snort都是基于libpcap编写的,此外Nmap扫描器也是基于libpcap来捕 



获目标主机返回的数据包的。 

winpcap提供给用户两个不同级别的编程接口:一个基于libpcap的wpcap.dl,另一个是较底层的 



packet.dll。对于一般的要与unix平台上libpcap兼容的开发来说,使用pacap.dll是当然的选择。 

下面几个库是与lipcap相关的: 

libnet1.0.2:数据包的发送个构造过程 

libnids:实现了ids的一些 框架 

libicmp:icmp数据包处理 









一些著名的嗅探器: 

tcpdump/windump:支持多种unix,后者支持windows。基于libpcap 

Sniffit:unix,windows,libpcap 

Ngrep:libpcap,unixwindows.可以用规则表达式,识别PPP,SLIP及FDDI数据包 

Sniffer pro/NetXray:专业的协议分析工具,是NAI提供的网络分析方案中的一部分 

其它: 

Iris 

LanExplorer 

NetMOnitor 

CommView 



单一用途的噢探器 

口令嗅:winsniffer,典型的黑客工具,嗅探并解析ftp,pop3,http,icq,smtp,telnet,IMAP,NNTP 



等口令 

password sniffer for NetHackerIII 



专用 嗅探器: 

SMB嗅探器:L0phtcrack,SMPRelay 

TCP连接会话嗅探器:CommView ,Iris,Juggernaut 

SSL嗅探器:SSLDump—sslv3/tls网络协议分析工具 

RIDIUS嗅控器:一个基于udp的论证记账协议,Radiusniff是其代表 

PPTP嗅 控器:Anger,PPTP-sniff(solaris) 

SNMP嗅探器:Snmpsniff 



交换网络嗅探器:Ettercap 

综合:Dsniff 

其它交换网络嗅探器: 

snarp,parasite 



嗅探对策……… 



netsys2: 



网络上流传的GUNIFFER是个基本的原型: 





http://asp.6to23.com/nowcan/code/guniffer.zip 



void main(int argc, char * argv) 







int iErrorCode; 



char RecvBuf[MAX_PACK_LEN] = {0}; 



usage(); 



if(GetCmdLine(argc, argv)==CMD_PARAM_HELP) exit(0); 



//初始化SOCKET 



WSADATA wsaData; 



iErrorCode = WSAStartup(MAKEWORD(2,1),&wsaData); 



CheckSockError(iErrorCode, “WSAStartup”); 



SockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP); 



CheckSockError(SockRaw, “socket”); 



//获取本机IP地址 



char FAR name[MAX_HOSTNAME_LAN]; 



iErrorCode = gethostname(name, MAX_HOSTNAME_LAN); 



CheckSockError(iErrorCode, “gethostname”); 



struct hostent FAR
pHostent; //注意下面这三句,这里先对pHostent分配了一块 



pHostent = (struct hostent )malloc(sizeof(struct hostent)); 



//内存,然后有让它等于gethostbyname函数的返回 



pHostent = gethostbyname(name); //值,但gethostbyname函数是自己在函数内部分配内 



存的,因此上一句根本就是多余,把上一句删除后一切正常。但此程序用VC6编译运行都没有问题 



,不知为何?也许是VC6的编译器优化在起作用。 



SOCKADDR_IN sa; 



sa.sin_family = AF_INET; 



sa.sin_port = htons(6000); 



memcpy(&sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length); 



free(pHostent); //由于前面分配内存的语句已经删除,所以这一句也要去掉,否则出错。感谢网 



友 Heyuming 发现这个问题。 



iErrorCode = bind(SockRaw, (PSOCKADDR)&sa, sizeof(sa)); 



CheckSockError(iErrorCode, “bind”); 



//设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包 



DWORD dwBufferLen[10] ; 



DWORD dwBufferInLen = 1 ; 



DWORD dwBytesReturned = 0 ; 



iErrorCode=WSAIoctl(SockRaw, SIO_RCVALL,&dwBufferInLen, 



sizeof(dwBufferInLen), 



&dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL ); 



CheckSockError(iErrorCode, “Ioctl”); 



//侦听IP报文 



while(1) 







memset(RecvBuf, 0, sizeof(RecvBuf)); 



iErrorCode = recv(SockRaw, RecvBuf, sizeof(RecvBuf), 0); 



CheckSockError(iErrorCode, “recv”); 



iErrorCode = DecodeIpPack(RecvBuf, iErrorCode); 



CheckSockError(iErrorCode, “Decode”); 











它有2个不方便之处: 

1)不能选择网卡 

2)采用死循环方式读数据,改编到WINDOWS窗口模式下时有死机的感觉。 



sevencat(): 

上次找了一些资料整理了一下,不过人气不旺,而且最近比较忙,暂时还没继续下去。 



http://expert.csdn.net/Expert/topic/2299/2299615.xml?temp=.2761499 

WINDOWS网络包过滤技术 

                    (原文

http://www.ndis.com/papers/winpktfilter.htm) 

一、user-mode网络包过滤 

1、winsock分层service provider 

参照Microsoft Platform SDK上有关文档和例子 



http://www.microsoft.com/msdownload/platformsdk/sdkupdate/) 

这里有好几个microsoft lsp 例子,最新(可能最bug-free)的经常在这里能找到。需要知道的是 



可以通过TDI调用核心TCPIP驱动,而且可以完全绕开WINSOCK,在大多数情况下这不是一个问 



题。例如:QOS的实现可以在WINSOCK LSP上。 

然而,这样做的话,程序必须察看和操作每个包,而不能依靠WINSOCK LSP,他们要以一种接 



近核心态的方法来实现。 

2、win2000包过滤接口 

  WIN2000包过滤接口提供了一种机制,这种机制允许用户态程序或者服务指定一系列的”过滤 



原则”,这些过滤原则会被低层的TCPIP实现用来过滤包。这种过滤工主要是对IP原地址、目标地址、端口号(或者端口号范围)进行pass或者drop操作。 

Windows Developer’s Journal 

《用iphlpapi.dll进行包过滤》作者:Ton plooy,October,2000,Volume 11, Number 10。 

  WIN2000提供了一个较好对TCPIP的可编程控制,其中包括包过滤。不幸的是,有关这个新 



的API的文档并不是很容易能找到。这篇文章向你演示了怎样对特定IP地址或者特定TCP端口的包 



进行阻塞的编程。 

链接:www.wdj.com 

上面这个例子的下载:ftp://ftp.wdj.com/pub/webzip/1110/plooy.zip 

Hollis 的解决方案: 

  HTS W2K IpHook例子演示了IP过滤和它的HOOK API,包含原文件,而且是免费的, 



需要HtsCpp运行时库(免费),下载地址

http://www.hollistech.com/ 

3、winsock替代DLL 

  在使用WINSOCK LSP之前,唯一的办法是用自己的DLL取代微软的WINSOCK DLL,假 



如实现顺利的话,自己的DLL会接收用户的WINSOCK调用请求,然后还可以调用原来的WINSOC 



K DLL来处理。 

  不过这样的实现是比较费力的,其中有个困难就是微软的WINSOCK DLL里面经常有一些未 



公开的内部使用的函数,一个WINSOCK代替DLL至少要处理其中的一些未公开函数。 

  随着WINDOWS系统结构的变化,有些方面得到了加强,比如系统文件保护,这使得这种技术 



变得不太可行。总的说来,使用WINSOCK DLL替换不是一个坏主意。(Xfilter就是用的这种技 



术,原代码可能在网上有流传,我以前看到过的) 

二、kernel-mode网络包过滤 

1、Transport Data Interface (TDI) 

  这主要是一个直接在核心TCPIP驱动上面的一层过滤驱动。在WINXP上TDI驱动是一种传统的 



NT风格的驱动,使用了基于IRP的API,这里有两种方法来实现。 

A、使用核心模式服务的IoAttachDeviceXYZ函数族在TDI上实现一个过滤。 

B、对TDI驱动IRP DISPATCH表进行过滤。 

  IoAttachDeviceXYZ函数在许多WINNT驱动开发的书上提到。这两种技术都需要对WINNT驱 



动开发编程技术十分了解,对TDI函数也要相当的了解。 

2、NDIS中间层(IM) 

具体请看NDIS IM FAQ

http://www.pcausa.com/resources/ndisimfaq.htm 

3、WIN2000 FILTER-HOOK 

  请参照有关DDK文档,系统中只能有一个活动的Filter-Hook存在,这点使这种技术的使用有 



严重的限制。(平时所见的drvipflt就是用的这个) 

4、WIN2000 FIREWALL-HOOK  

  Firewall-Hook Driver函数在文档里介绍得很少,而且在有些win2000版本中不可用。请参 



照微软有关文档

http://msdn.microsoft.com/library/default.asp?url=/library/en-us 



/network/hh/network/firewall_3wfb.asp 

5、NDIS-HOOKING  (费尔防火墙就是用的这种技术吧,据我所知,虽然我没看过原码。) 

NDIS-Hooking驱动拦截或者叫”HOOK”一些由NDIS封装程序导出的函数。虽然从实现手段上来 



说有些不正规,但一个有系统的NDIS-Hooking过滤会非常有效。 

另外:NDIS-Hooking过滤驱动有下面的好处: 

A、容易安装(可以动态装卸,不过有时候会出问题,里面有些情况现在还未知。) 

B、支持拨号-ppp适配器。 

  Ndis-Hooking技术在98和ME系统下非常有效和实用。在这些平台上,DDK文档和provide 



d services都能很有用的帮你HOOK由Ndis wrapper导出的函数。 

  Ndis-Hooking技术在NT,2000和XP上同样有效和实用。这种技术很像核心模式的调试器。 



文档支持较少,而且基本上不会被WHQL认证。 

PCAUSA提供了一套NDIS PIM驱动例子,这些例子能在现有的WIN平台上运行成功(从95到X 



P)。地址

http://www.pcausa.com/ndispim/Default.htm 



其他: 

Network操作和进程信息: 

  有许多人想知道网络上的操作和WIN进程(就是应用程序啦)之间怎样联系起来,举例来说, 



可能会想知道是哪个进程在一个特定的IP端口上发送或接收数据。 

  先不考虑这种技术是否有用,或者是否可靠,我们认为核心模式TCPIP驱动上层的过滤程序可 



以处理这个问题。而TCPIP驱动下层的过滤程序根本看不到进程信息。特别要注意的是有些网络服 



务操作生成一个新的进程attach到系统进程上的。在这种情况下进程信息并不能告诉我们原先是哪 



个进程生成的。特别是单独在核心模式下的WIN服务(TDI客户) 

  最后,有必要看看下面的资料United States Patent 5,987,611; “System and 



methodology for managing internet access on a per application basis for client 



computers connected to the internet “ 

  我们并不知道这项专利的价值,也不知道他是否能用在包过滤上。详情请参阅

http://www. 



uspto.gov/patft/index.html 

www.pcausa.com 



============================================ 

drvipflt具体解析,就是上面所提到的吧(2-3就是说的这东东)。 

假定大家对驱动框架已经有了一定的理解。IRP分配程序如下: 

NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) 



… 

  switch (irpStack->MajorFunction) 

  { 

… 

  case IRP_MJ_DEVICE_CONTROL: 

    ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; 



    switch (ioControlCode) 

    { 

  // ioctl code to start filtering 

  //这里可以从用户模式程序发送这样的请求。 

  //直接用DeviceIoControl这个函数,就像下面这样调用就可 



以了吧,我想。 

   



//DeviceIoControl(drivehandle,START_IP_HOOK,NULL,0,NULL,0,&bytereturned,NU 



LL) 

  case START_IP_HOOK: 

  { 

  //这个应该是最主要的函数了。 

        SetFilterFunction(cbFilterFunction); 



  break; 

  } 



  // ioctl to stop filtering 

  case STOP_IP_HOOK: 

  { 

  SetFilterFunction(NULL); 

         

  break; 

  } 



        // ioctl to add a filter rule 

  case ADD_FILTER: 

  { 

  if(inputBufferLength == sizeof(IPFilter)) 

  { 

  IPFilter
nf; 



  nf = (IPFilter )ioBuffer; 

   

  AddFilterToList(nf); 

  } 



  break; 

  } 



  // ioctl to free filter rule list 

  case CLEAR_FILTER: 

  { 

  ClearFilterList(); 



  break; 

  } 



  default: 

  Irp->IoStatus.Status = 



STATUS_INVALID_PARAMETER; 





  break; 

    } 



    break; 

… 



SetFilterFunction(cbFilterFunction)可能是最重要的一个程序了。具体如下: 

实际上这个做法相当在系统中注册了一个回调函数。 

NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFunction) 



NTSTATUS status = STATUS_SUCCESS, waitStatus=STATUS_SUCCESS; 

UNICODE_STRING filterName; 

PDEVICE_OBJECT ipDeviceObject=NULL; 

PFILE_OBJECT ipFileObject=NULL; 



PF_SET_EXTENSION_HOOK_INFO filterData; 



KEVENT event; 

IO_STATUS_BLOCK ioStatus; 

PIRP irp; 



//首先获得一个设备指针。 

//first of all, we have to get a pointer to IpFilterDriver Device 

RtlInitUnicodeString(&filterName, DD_IPFLTRDRVR_DEVICE_NAME); 

status = IoGetDeviceObjectPointer(&filterName,STANDARD_RIGHTS_ALL, 



&ipFileObject, &ipDeviceObject); 

if(NT_SUCCESS(status)) 



//一些初始化工作,填充filterData。 

//initialize the struct with functions parameters 

filterData.ExtensionPointer = filterFunction; 



//we need initialize the event used later by the IpFilterDriver to 



signal us 

//when it finished its work 

KeInitializeEvent(&event, NotificationEvent, FALSE); 



//这个就是最重要的注册回调函数过程。DDK中具体讲述是这样的 

//IOCTL_PF_SET_EXTENSION_POINTER registers filter-hook callback functions to 



the IP filter driver 

//to inform the IP filter driver to call those filter hook callbacks for every IP packet 

//that is received or transmitted. Also, IOCTL_PF_SET_EXTENSION_POINTER 



clears filter-hook 

//callback functions from the IP filter driver. (看到了吧,最后一句话,注册新的回调函 



数,就将原先的清除掉了, 

//所以说系统中只存在一个这样的驱动有用。) 

//we build the irp needed to establish fitler function这个地方仅 



仅是生成这样的IRP,并没有注册 

irp = 



IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER, 

       



  ipDeviceObject, 

       



(PVOID) &filterData, 

       



sizeof(PF_SET_EXTENSION_HOOK_INFO), 

       



NULL, 

       



0, 

       



FALSE, 

       



&event, 

       



&ioStatus); 





if(irp != NULL) 



  // we send the IRP 

  //这个地方才是真正的注册呀。 

  status = IoCallDriver(ipDeviceObject, irp); 



  //and finally, we wait for “acknowledge” of 



IpDriverFilter 

  if (status == STATUS_PENDING) 

  { 

  waitStatus = KeWaitForSingleObject(&event, 



Executive, KernelMode, FALSE, NULL); 



  if (waitStatus != STATUS_SUCCESS ) 



{} 

  } 



  status = ioStatus.Status; 



  if(!NT_SUCCESS(status)){} 





else 



  //if we cant allocate the space, we return the 



corresponding code error 

  status = STATUS_INSUFFICIENT_RESOURCES; 







if(ipFileObject != NULL) 

  ObDereferenceObject(ipFileObject); 



ipFileObject = NULL; 

ipDeviceObject = NULL; 





else 



return status; 



//真正的过滤函数是这个,在最早的IRPdispatch里面传递的这个函数。 

//这个函数就是系统传递了一个包头和包内容和包长度之类的东西,你可以在里面进行一些处理, 

//假如你想让这个包通过的话,就返回PF_FORWARD,或者你不想让包通过的话,就返回PF_D 



ROP就拦住了。是不是 

//听起来很简单, 

PF_FORWARD_ACTION cbFilterFunction(IN unsigned char
PacketHeader,IN 



unsigned char Packet, IN unsigned int PacketLength, IN unsigned int 



RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN unsigned long 



RecvLinkNextHop, IN unsigned long SendLinkNextHop) 



IPPacket
ipp; 

TCPHeader tcph; 

UDPHeader
udph; 



int countRule=0; 



struct filterList aux = first; 



//we “extract” the ip Header 

ipp=(IPPacket
)PacketHeader; 



// dprintf(“Source: %x/nDestination: %x/nProtocol: %d”, ipp->ipSource, 



ipp->ipDestination, ipp->ipProtocol); 



//TCP -> protocol = 6 

//we accept all packets of established connections 

if(ipp->ipProtocol == 6) 



tcph=(TCPHeader )Packet; 



// dprintf(“FLAGS: %x/n”, tcph->flags); 



//if we havent the bit SYN activate, we pass the packets 

if(!(tcph->flags & 0x02)) 

  return PF_FORWARD; 





//otherwise, we compare the packet with our rules 

while(aux != NULL) 



// dprintf(“Comparing with Rule %d”, countRule); 



//if protocol is the same…. 

if(aux->ipf.protocol == 0 || ipp->ipProtocol == 



aux->ipf.protocol) 



  //we look in source Address 

  if(aux->ipf.sourceIp != 0 && (ipp->ipSource & 



aux->ipf.sourceMask) != aux->ipf.sourceIp) 

  { 

  aux=aux->next; 

   

  countRule++; 

  continue; 

  } 

       

  // we look in destination address 

  if(aux->ipf.destinationIp != 0 && (ipp->ipDestination 



& aux->ipf.destinationMask) != aux->ipf.destinationIp) 

  { 

  aux=aux->next; 



  countRule++; 

  continue; 

  } 

   

  //if we have a tcp packet, we look in ports 

  //tcp, protocol = 6 

  if(ipp->ipProtocol == 6) 

  { 

  if(aux->ipf.sourcePort == 0 || 



tcph->sourcePort == aux->ipf.sourcePort) 

  { 

  if(aux->ipf.destinationPort == 0 



|| tcph->destinationPort == aux->ipf.destinationPort) //puerto tcp destino 

  { 

    //now we decided what 



to do with the packet 

    if(aux->ipf.drop) 

       



return PF_DROP; 

    else 

     



return PF_FORWARD; 

  } 

  } 

  } 

   

  //udp, protocol = 17 

  else if(ipp->ipProtocol == 17) 

  { 

  udph=(UDPHeader
)Packet; 



  if(aux->ipf.sourcePort == 0 || 



udph->sourcePort == aux->ipf.sourcePort) 

  { 

  if(aux->ipf.destinationPort == 0 



|| udph->destinationPort == aux->ipf.destinationPort) 

  { 

    //now we decided what 



to do with the packet 

    if(aux->ipf.drop) 

    return 



PF_DROP; 

     

    else 

    return 



PF_FORWARD; 

  } 

  } 

  } 

   

  else 

  { 

  //for other packet we dont look more and 



…. 

  //now we decided what to do with the 



packet 

  if(aux->ipf.drop) 

  return PF_DROP; 

  else 

  return PF_FORWARD; 

  } 





//compare with the next rule 

countRule++; 

aux=aux->next; 





//we accept all not registered 

return PF_FORWARD; 





winpcap也是用的NDIS,将自己注册为一个协议处理驱动。(在原代码的driverentry里面能看到) 



又:上面这个drvipflt这个代码的过滤部分不知道大家是不是看起来很熟悉,是的,是抄的那个nu 



mege的驱动开发包里面的一个包过滤程序里的,看来老外也是喜欢到处抄的。 



ruike: 

读研的时候专门搞过nids,因此对winpcap可以说是情有独钟,这个东东确实好用,但也确实很烦 



人,它有一个致命的缺陷就是只适用于共享式以太网络,对于交换式网络下的数据则无能为力,我 



专门做过测试,在使用交换机连接的局域网下,只能监听到本网段内的数据,而对于来自其他网段 



的数据则无法监听,除非你把probe接到交换机之前或者接到交换机的console口上,不过那样的 



弊端是显而易见的。 

所以,winpcap的应用还是很有局限性的! 



kingzai: 

实现交换网络的嗅探也有不少方法的 

1.将你的抓包程序放在网关或代理服务器上,这样抓到整个局域网的包。 

2.对交换机实行端口映射,将该端口的数据包全部映射到某个监控机器上。 

3.在交换机和路由器之间连接一个HUB,这样数据将以广播的方式发送。 

4.实行ARP欺骗,即在你的机器上实现整个包的转发,不过会降低整个局域网的效率。 



warton: 

嗅探对策: 

光说嗅探了,我说说反嗅探吧:) 

1.检查网内的主机上是否将网卡设置为混合模式(有很多工具可以做到,AntiSniff,Promiscan,S 



entinel等) 

2.对EtterCap这样的交换网络嗅探器(进行ARP欺骗),可以采用防止ARP欺骗的方法来对待 

3.SSH加密通道 

4.SSL 

5.VPN 

6.PGP等 



目前这用利用网卡混合模式来进行sniffer的软件看来作用不太大了,所以应该多考虑交换网络的可 



行办法: 



MAC Flooding,MAC Duplicating,ARP欺骗等等 

这些方法实现起来就不怎么容易了,欢迎有兴趣的朋友提供相关的资料,呵呵! 



netsys: 

难道没人用过RAW SOCKET 吗? 

虽然WINPCP功能很大,但RAW SOCKET可以让你直接了SOCKET的原生机制。 

实际上我提的那两个问题是很容易解决的。。 



netsys2: 

对于一些混合模式的SNIFFER,大多采用发送特殊ARP包的方式,正确的网卡不会响应,而处于 



混合模式的网卡则会响应。 



当然,ARP与IP处于同层,因此你不能用RAW SOCKET完成,你需WinPcap支持工作。 



下面是部分代码 



AnsiString msgStatus; 

extern TArpFuncParam wParams; 



int BuildARPPacket(PArpPacket ArpPacket, unsigned char dst_etheraddr, 

  unsigned char
src_etheraddr, int ar_op, unsigned 



char ar_sha, 

  unsigned char
ar_sip, unsigned char ar_tha, 

                unsigned char
ar_tip,unsigned short int ar_hw) 



memcpy(&(ArpPacket->eth_dst_addr), dst_etheraddr, ETH_ADD_LEN); 

memcpy(&(ArpPacket->eth_src_addr), src_etheraddr, ETH_ADD_LEN); 

ArpPacket->eth_type = htons(ETH_TYPE_ARP); 

ArpPacket->ar_hrd = htons(ar_hw); 

ArpPacket->ar_pro = htons(ARP_PRO_IP); 

ArpPacket->ar_hln = ARP_ETH_ADD_SPACE; 

ArpPacket->ar_pln = ARP_IP_ADD_SPACE; 

ArpPacket->ar_op = htons(ar_op); 

memcpy(&(ArpPacket->ar_sha), ar_sha, ARP_ETH_ADD_SPACE); 

memcpy(&(ArpPacket->ar_spa), ar_sip, ARP_IP_ADD_SPACE); 

memcpy(&(ArpPacket->ar_tha), ar_tha, ARP_ETH_ADD_SPACE); 

memcpy(&(ArpPacket->ar_tpa), ar_tip, ARP_IP_ADD_SPACE); 

memset(ArpPacket->eth_pad, 32, ETH_PADDING_ARP); 

return(EXIT_SUCCESS); 



int OpenAdapter(LPADAPTER lpAdapter) 



lpAdapter = 



PacketOpenAdapter(wParams.AdapterList[wParams.SelectedAdapter]); 



if(!(lpAdapter) || ((lpAdapter)->hFile == INVALID_HANDLE_VALUE)) 



  msgStatus = “Error : unable to open the driver.”; 

  SHOWSTAT(msgStatus); 

  return(EXIT_FAILURE); 



return(EXIT_SUCCESS); 



void CloseAdapter(LPADAPTER lpAdapter) 



PacketCloseAdapter(lpAdapter); 





void GetLocalMAC(LPADAPTER lpAdapter, unsigned char ether_addr) 





ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA) + sizeof(ULONG) - 1); 

PPACKET_OID_DATA OidData; 



OidData = (struct _PACKET_OID_DATA
)malloc(IoCtlBufferLength); 

OidData->Oid = OID_802_3_CURRENT_ADDRESS; 

OidData->Length = 6; 

if(PacketRequest(lpAdapter, FALSE, OidData) == FALSE) 

    memcpy(ether_addr, 0, 6); 

else 

    memcpy(ether_addr, OidData->Data, 6); 

free(OidData); 



int GetARPReply(LPPACKET lpPacket, unsigned char iptarget, unsigned char 



result) 



unsigned short int ether_type; 

unsigned char     ipsender[4];   

unsigned int     off=0; 

unsigned int     tlen; 

struct bpf_hdr   hdr; 

char        
pChar; 

char         buf; 



buf = (char
)lpPacket->Buffer; 

hdr = (struct bpf_hdr )(buf + off); 

tlen = hdr->bh_caplen; 

off += hdr->bh_hdrlen;   

pChar = (char
)(buf + off); 

off = Packet_WORDALIGN(off + tlen); 

memcpy(ðer_type, pChar + 12, 2); 

ether_type = ntohs(ether_type); 

if(ether_type == ETH_TYPE_ARP) 



  memcpy(ipsender, pChar + 28, 4); 

  if((iptarget[0] == ipsender[0])&&(iptarget[1] == ipsender[1])&& 

    (iptarget[2] == ipsender[2])&&(iptarget[3] == ipsender[3])) 

    memcpy(result, pChar + 22, 6); 

  else 

    return(EXIT_FAILURE); 



else 

    return(EXIT_FAILURE); 

return(EXIT_SUCCESS); 



int CheckPROMode(LPADAPTER lpAdapter, unsigned char iptarget, unsigned char 



remotemac) 





LPPACKET lpPacketRequest; 

LPPACKET lpPacketReply; 

char   buffer[256000]; 



TArpPacket ArpPacket; 

unsigned char magicpack[ETH_ADD_LEN]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFE}; 

unsigned char mactarget[ARP_ETH_ADD_SPACE]; 



DWORD timestamp = 0; 

int numPacks = 0; 

/ Init fields

memset(mactarget, 0, 6); 

/ Allocate PACKET structure for ARP Request packet

if((lpPacketRequest = PacketAllocatePacket()) == NULL) 



  msgStatus = “Error : failed to allocate the LPPACKET structure..”; 

  SHOWSTAT(msgStatus); 

  return(EXIT_FAILURE); 





/ Init packet structure

memset(&ArpPacket, 0, sizeof(TArpPacket)); 



/ Build ARP Request packet

BuildARPPacket(&ArpPacket, magicpack, wParams.srcMAC, ARP_OP_REQUEST, 



wParams.srcMAC, wParams.srcIPAdd, mactarget, iptarget,wParams.ar_hw); 



/ Init ARP Request packet

PacketInitPacket(lpPacketRequest, &ArpPacket, sizeof(ArpPacket)); 



/ Set number of ARP Request packets to send

if(PacketSetNumWrites(lpAdapter, 1) == FALSE) 



  msgStatus = “Warning : unable to send more than one packet in a single write..”; 

  SHOWSTAT(msgStatus); 



/ Set hardware filter to directed mode

if(PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_DIRECTED) == FALSE) 



  msgStatus =”Warning: unable to set directed mode..”; 

  SHOWSTAT(msgStatus); 



/ Set a 512K buffer in the driver

if(PacketSetBuff(lpAdapter, 512000) == FALSE) 



  msgStatus = “Error: unable to set the kernel buffer..”; 

  SHOWSTAT(msgStatus); 

  PacketFreePacket(lpPacketRequest); 

  return(EXIT_FAILURE); 



/ Set a 1 second read timeout

if(PacketSetReadTimeout(lpAdapter, -1) == FALSE) 



  msgStatus = “Warning: unable to set the read tiemout..”; 

  SHOWSTAT(msgStatus); 





/ Allocate PACKET structure for ARP Reply packet

if((lpPacketReply = PacketAllocatePacket()) == NULL) 



  msgStatus = “Error: failed to allocate the LPPACKET structure..”; 

  SHOWSTAT(msgStatus); 

  PacketFreePacket(lpPacketRequest); 

  return(EXIT_FAILURE); 



/ Init ARP Reply packet

PacketInitPacket(lpPacketReply, (char)buffer, 256000); 

/
Allocate memory for remote MAC address

timestamp = GetTickCount(); 



/
Main capture loop

for(;;) 



  if(numPacks < wParams.numPacks) 

  { 

  /
Send packet

    if(PacketSendPacket(lpAdapter, lpPacketRequest, TRUE) == FALSE) 

    { 

    msgStatus =”Error : unable to send the packets..”; 

    SHOWSTAT(msgStatus); 

    PacketFreePacket(lpPacketRequest); 

    PacketFreePacket(lpPacketReply); 

    return(EXIT_FAILURE); 

    } 

    /
Free packet

    PacketFreePacket(lpPacketRequest); 

    numPacks += 1; 

  } 

  /
Capture the packets

  if(PacketReceivePacket(lpAdapter, lpPacketReply, TRUE) == FALSE) 

  { 

    msgStatus = “Error: PacketReceivePacket failed..”; 

    SHOWSTAT(msgStatus); 

PacketFreePacket(lpPacketReply); 

  return(EXIT_FAILURE); 

  } 

  if(lpPacketReply->ulBytesReceived > 0) 

  if(GetARPReply(lpPacketReply, iptarget, remotemac) == EXIT_SUCCESS) 

      break; 

  if((GetTickCount() - timestamp) > wParams.delay) 

  { 

    PacketFreePacket(lpPacketReply); 

    return(EXIT_FAILURE); 

  } 



/
Free packet */ 

PacketFreePacket(lpPacketReply); 

return(EXIT_SUCCESS); 



sunxufei: 

哦,交换机是以MAC地址进行交换的,不是IP那一层的,要IP已经路由器了 

现在交换机便宜了,因此以后你想用sniffer抓密码概率不大了,不过还能多公司仍然是交换机和H 



UB一起用的,这样小范围内是有效地,至于ADSL CABLE FTTB,我的FTTB是用华为设计的设备 



,呵呵,不仅仅工网IP,只有我和交换机两个MAC(这次中国人干的不错),没希望找到第三者,很安全,但 



不都这样安全,很多人的网络还是很糟糕的. 

很多加密协议可以用来提高安全性,但老的POP3,SMTP,HTTP,FTP这种协议应用广泛,不可能在短 



时间内完全取代,而且加密也是有待价的,所以对于要求较高的场合,才会加密. 

不过sniffer不是给大家偷密码用的,我当初用来学习网络,看看包的样子,后来就用来当作网管工具, 



分析网络的健康与否,其实这样的话,你知道,很有可能sniffer就是接在我需要探测的网络上,听诊器 



吗,到处都听听,呵呵,因此即使用了交换机,sniffer仍然是有用处的,但不是抓密码!! 

Wincap很简单,大3的学生不要怕,去他的网站看看,有例子的,VC6编译,BCB也行的,把lib的格式转 



换一下,不过写这种程序,你最好先熟悉协议,很多协议在linux里有现成的源代码,主要是一些struct 



吧,移植时注意VC可不是gcc,有些c的高级语法,编译选项要注意,否则差一个byte你就得不到正确的 



结果. 

如果你搞不到sniffer,Win2000 Server也有网络包查看器的,不比sniffer强大,但简单的东西入

所属分类: 内网渗透 所属专题:

发表评论

表情:
评论列表 (有 0 条评论,120人围观)

还没有评论,来说两句吧...

相关阅读

    相关 arp欺骗的技术原理应用

    最近要完成一个发送arp包的功能,以前没做过封包发送的内容,查找了写资料。不过看代码,arp包的结构搞懂了,不知道为啥还要个头,呵呵原来还要个以太网包头。看来基础知识还要加强啊