WinPcap权威指南(一)

摘要:
WinPcap是一个开源的网络数据包捕获模块。顾名思义,它只能在Windows下工作。然而,本文中介绍的知识并不局限于任何操作系统和开发语言,因为网络协议本身没有这种差异。在阅读本指南之前,请下载WinPcap并将其安装在您的计算机上。目前,WinPcap的最新版本是4.1.3。它支持所有基于NT内核的操作系统(从NT4到Win8)。读者可以从官方网站下载WinPcaphttp://www.winpcap.org/install
  WinPcap是一个开源的网络抓包模块,顾名思义,它只能工作在Windows下,但本文介绍的知识并不局限于任何操作系统和开发语言,因为网络协议本身是没有这些区别的。阅读本指南之前,请先下载WinPcap安装到自己的电脑上,目前WinPcap的最新版本是4.1.3,支持基于NT核心的所有操作系统(从NT4一直到Win8),读者可以从官方网站http://www.winpcap.org/install/default.htm下载。
    网络其实是分层设计的,一个应用层的网络程序对外通信的时候,大概的流程如下:应用程序(调用WinSock)<--->SPI层<--->TDI层<--->NDIS层<--->MiniPort层<-->物理网卡,实际上,应用程序可以直接调用上面的某一层,例如:直接调用TDI驱动收发网络包;又例如,一般软件防火墙工作于NDIS层,如果你直接使用MiniPort HOOK进行收发数据,那么防火墙是完全不知情的,也不会有任何提示。应用层抓包的话,方法有很多:例如本机的可以使用API HOOK,截取WinSock的调用;或者直接安装一个SPI的HOOK;又或者直接使用RawSocket接口。WinPcap的驱动实际上位于NDIS层,属于NDIS过滤驱动,也就是说,它只是抓包,但不像软件防火墙的passthru模型还可以拦截。另外,它还可以发送数据包。注意:笔者曾经将它翻译为Delphi,发现在以太网环境下(例如局域网)它是通过自己的驱动发布,而对于拨号上网的PPPOE连接,它调用的是微软的NetMon接口,也就是说,如果你的电脑没有安装NetMon,那么在拨号上网的环境下WinpCap可能是无法预期工作的。
    调用WinPcap有两种方式,一种是通过packet.dll调用它的驱动npf.sys,另外一种是通过wpcap.dll再间接调用packet.dll来调用它的驱动npf.sys,可能会有人问,既然可以直接调用packet.dll,为什么还要有调用wpcap.dll这种方式?原因很简单:在Unix下(或者Linux)下有一个抓包接口叫Pcap—这也是WinPcap的名称来由,wpcap.dll对外提供了相同的接口函数,便于程序员在不同的平台下移植。本文介绍的是packet.dll调用方式,对wpcap.dll接口感兴趣的朋友可以参考韩国程序员写的一个控件包Snoop2,我将它的下载放在本文的末尾(说句题外话,WinPcap的安装程序,实际上是释放sys和dll到系统,然后安装sys为服务,具体可以参考这个Snoop2(Jingtao修改版),里面直接集成了sys和dll,所以无需先安装WinPcap了,但是由于当时这个版本时间很早,所以还支持Win98系统,读者可以将里面的sys和dll文件替换成现在的最新版本再编译)。
    要调用WinPcap,第一步当然是打开需要操作的网卡,因为有可能一台电脑上有好几张网卡。WinPcap提供了一个函数叫PacketGetAdapterNames,用于获取系统已经安装的所有网卡,函数声明如下:
TPacketGetAdapterNames = function(pStr: PAnsiChar; BufferSize: PULONG): Byte; cdecl;
 其中pStr是一个用于接收网卡名称的缓冲区,BufferSize是该缓冲区的大小,如果函数成功,则返回非0值。需要注意的是,网络的名称有多种形式,一种是设备名称,一种是友好名称,这个函数返回的格式是:设备名称+两个0+网卡名称,在WinPcap里面打开某块网卡,需要提供的是设备名称,packet.dll的源代码里面大概的实现如下:
function PacketGetAdaptersNPF(): Byte;
var
  LinkageKey, AdapKey, OneAdapKey: HKEY;
  RegKeySize: DWORD;
  Status: Longint;
  i: Integer;
  dim: DWORD;
  RegType: DWORD;
  TName: array[0..255] of AnsiChar;
  TAName: array[0..255] of AnsiChar;
  AdapName: array[0..255] of AnsiChar;
  TcpBindingsMultiString: PAnsiChar;
  FireWireFlag: UINT;
  //
  //    Old registry based WinPcap names
  //
  //    CHAR        npfCompleteDriverPrefix[MAX_WINPCAP_KEY_CHARS];
  //    UINT        RegQueryLen;

  npfCompleteDriverPrefix: array[0..MAX_WINPCAP_KEY_CHARS - 1] of AnsiChar; // = NPF_DRIVER_COMPLETE_DEVICE_PREFIX;
  DeviceGuidName: array[0..255] of AnsiChar;
label tcpip_linkage;
begin
  RegKeySize := 0;
  FillChar(npfCompleteDriverPrefix, sizeof(npfCompleteDriverPrefix), #0);
  StrCopy(npfCompleteDriverPrefix, NPF_DRIVER_COMPLETE_DEVICE_PREFIX);
  //TRACE_ENTER("PacketGetAdaptersNPF");

 //
 // Old registry based WinPcap names
 //
 // Get device prefixes from the registry

  Status := RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    'SYSTEMCurrentControlSetControlClass{4D36E972-E325-11CE-BFC1-08002BE10318}',
    0,
    KEY_READ,
    AdapKey);

  if (Status <> ERROR_SUCCESS) then
  begin
    //TRACE_PRINT("PacketGetAdaptersNPF: RegOpenKeyEx ( Class{networkclassguid} ) Failed");
    goto tcpip_linkage;
  end;

  i := 0;

  //TRACE_PRINT("PacketGetAdaptersNPF: RegOpenKeyEx ( Class{networkclassguid} ) was successful");
  //TRACE_PRINT("PacketGetAdaptersNPF: Cycling through the adapters in the registry:");

  //
  // Cycle through the entries inside the {4D36E972-E325-11CE-BFC1-08002BE10318} key
  // To get the names of the adapters
  //
  //while((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS)
  while ((RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName) div 2)) = ERROR_SUCCESS) do
  begin
    Inc(i);
    FireWireFlag := 0;
    //
    // Get the adapter name from the registry key
    //
    Status := RegOpenKeyEx(AdapKey, AdapName, 0, KEY_READ, OneAdapKey);
    if (Status <> ERROR_SUCCESS) then
    begin
      //TRACE_PRINT1("%d) RegOpenKey( OneAdapKey ) Failed, skipping the adapter.",i);
      continue;
    end;

    //
    //
    // Check if this is a FireWire adapter, looking for "1394" in its ComponentId string.
    // We prevent listing FireWire adapters because winpcap can open them, but their interface
    // with the OS is broken and they can cause blue screens.
    //
    dim := sizeof(TName);
    Status := RegQueryValueEx(OneAdapKey,
      'ComponentId',
      nil,
      nil,
      PBYTE(@TName[0]),
      @dim);

    if (Status = ERROR_SUCCESS) then
    begin
      if (IsFireWire(TName) <> 0) then
      begin
        FireWireFlag := INFO_FLAG_DONT_EXPORT;
      end;
    end;

    Status := RegOpenKeyEx(OneAdapKey, 'Linkage', 0, KEY_READ, LinkageKey);
    if (Status <> ERROR_SUCCESS) then
    begin
      RegCloseKey(OneAdapKey);
      //TRACE_PRINT1("%d) RegOpenKeyEx ( LinkageKey ) Failed, skipping the adapter",i);
      continue;
    end;

    dim := sizeof(DeviceGuidName);
    Status := RegQueryValueExA(LinkageKey,
      'Export',
      nil,
      nil,
      PBYTE(@DeviceGuidName[0]),
      @dim);

    if (Status <> ERROR_SUCCESS) then
    begin
      RegCloseKey(OneAdapKey);
      RegCloseKey(LinkageKey);
      //TRACE_PRINT1("%d) Name = SKIPPED (error reading the key)", i);
      continue;
    end;

    if (strlen(DeviceGuidName) >= strlen('Device')) then
    begin
      // Put the DeviceNPF_ string at the beginning of the name
      StrPCopy(TAName, Format('%s%s', [npfCompleteDriverPrefix,
        DeviceGuidName + strlen('Device')]));
    end
    else
      continue;

    //terminate the string, just in case
    TAName[sizeof(TAName) - 1] := #0;
    //TRACE_PRINT2("%d) Successfully retrieved info for adapter %s, trying to add it to the global list...", i, TAName);
    // If the adapter is valid, add it to the list.


    PacketAddAdapterNPF(TAName, FireWireFlag);

    RegCloseKey(OneAdapKey);
    RegCloseKey(LinkageKey);

  end; // while enum reg keys

  RegCloseKey(AdapKey);

  tcpip_linkage:
  //
  // no adapters were found under {4D36E972-E325-11CE-BFC1-08002BE10318}. This means with great probability
  // that we are under Windows NT 4, so we try to look under the tcpip bindings.
  //

  //TRACE_PRINT("Adapters not found under SYSTEMCurrentControlSetControlClass. Using the TCP/IP bindings.");

  Status := RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    'SYSTEMCurrentControlSetServicesTcpipLinkage',
    0,
    KEY_READ,
    LinkageKey);

  if (Status = ERROR_SUCCESS) then
  begin
    // Retrieve the length of th binde key
    // This key contains the name of the devices as devicefoo
    //in ASCII, separated by a single '

免责声明:内容来源于网络,仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇NetCore 中 后台任务利器之Hangfire 的使用添加samba用户,并设置密码下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

使用WinPcap编程(1)——获取网络设备信息

pcap_if_t是一个interface数据结构,表明网络接口的信息。网络接口就是interface,就是我们用来上网的设备,一般为网卡,还有一些虚拟网卡也算作这样的接口。它的结构如下: struct pcap_if { struct pcap_if *next; char *name; char *descr...

NetAnalyzer笔记 之 十三 NetAnalyzer 6.0 的使用方法 -- 2.抓包与数据选择

1.  NetAnalyzer使用方法 1.1.数据获取 通过上面的说明,我们已经可以很快的获取到网络数据了,但是,仅仅知道上面内容却远远不够。 在NetAnalyzer中将数据加载到软件有三种方式。   数据文件   字节字符串录入   网卡采集   抓包开始菜单 在开始标签中数据包组合数据采集组包含了这三种功能点 数据文件,很多的数据采集软件都具备...

Winpcap网络编程九之Winpcap实战,ARP协议获得MAC表及主机通信

大家好,本次我们须要完毕的任务是:  完毕两台主机之间的数据通信(数据链路层) 仿真ARP协议获得网段内主机的MAC表 使用帧完毕两台主机的通信(Hello! I’m …)         声明:本文章的目的是为大家的Winpcap编程带来一定的借鉴,希望对大家的课程设计有一定的帮助。总之,我相信,大家看了前几篇 Winpcap 编程基础知识,再加...

网络安全开发包介绍

网络安全开发包介绍 引言:网络安全领域的许多网络安全技术,如防火墙、入侵检测、安全扫描、网络嗅探、协议分析、流量统计、网络管理、蜜罐等,其设计和实现都离不开一些网络安全操作,其中一些基本操作都在底层进行,使用频繁,如网络地址的操作、网络接口的操作、数据包的捕获、数据包的构造和发送、网络入侵检测等;还有一些比较复杂的操作,如流量的统计、路由的管理,ARP缓存...

Libnids---编写网络应用程序的利器

一.前言 Libnids是一个用于网络入侵检测开发的专业编程接口,它使用Libpcap进行数据包的捕获。同时,Libnids提供了TCP/IP数据流重组功能,因此省去了应用层自己考虑数据分片、重传等情况的麻烦。它是模仿了Linux 2.0.x的IP协议栈进行数据处理,因此非常稳定可靠。当然,libnids还有一项非常实用的功能,那就是:TCP端口扫描检测和...

使用WinPcap(SharpPcap)实现ARP抓包以实现设备IP搜索功能

在监控摄像机安装后,往往需要设置IP等信息,在IP不知道的情况下,IP搜索是一个很常见也必须的功能。 考虑到设备IP和当前局域网可能不在同一个网段,ARP是一个不错的选择。 首先安装WinPcap软件 使用C#开发还需要以下dll: SharpPcap.dll PacketDotNet.dll 请自己百度下载。 设计逻辑: 用户电脑开始搜索IP时,首先发送...