探索黑客技术攻防,实战研究与安全创新

导航菜单

使用libnet实现ARP数据包发送

libnet是一个小型接口函数库,主要用C语言写成,提供了低层网络数据包的构造、处理和发送功能。libnet的开发目的是建立一个简单统一的网络编程接口,以屏蔽不同操作系统底层网络编程的差别,使得程序员将精力集中在解决关键问题上。其主要特点如下:

高层接口:libnet主要用C语言写成。

可移植性:libnet目前可以在Linux、FreeBSD、Solaris、WindowsNT等操作系统上运行,并提供了统一的接口。

数据包构造:libnet提供了一系列的TCP/IP数据报文的构造函数,以方便用户使用。

数据包的处理:libnet提供了一系列辅助函数,利用这些辅助函数,帮助用户简化那些烦琐的事务性的编程工作。

数据包发送:libnet允许用户在两种不同的数据包发送方法中选择。

另外,libnet还允许程序获得对数据包的绝对控制,其中一些是传统的网络程序接口所不能提供的,这也是libnet的魅力之一。

libnet支持TCP/IP协议族中的多种协议,比如其上一个版本libnet1.0支持了10种协议,一些新的协议,比如对IPV6的支持还在开发之中。目前最新版本是1.1.2.1版。

Libnet的开发流程如图1和图2所示。

B1.png

B2.png

初始化由libnet_init(intinjection_type,char*device,char*err_buf)完成,injection_type表示构造的类型,device表示网络接口,err_buf用于存放出错的信息。初始化代码的示例如下:


libnet_t*libnet_init(intinjection_type,char*device,char*err_buf);
l=libnet_init(LIBNET_LINK,“eth0”,err_buf);
if(NULL==l)
{
fprintf(stderr,“libnet_init():%s”,errbuf);
}


初始化①:确定libnet类型,共7种。

LIBNET_LINK:表示构造链路层开始的数据包;

LIBNET_RAW4:表示构造IPV4原始套接字接口类型的数据包;

LIBNET_RAW6:表示构造IPV6原始套接字接口类型的数据包;

LIBNET_LINK_ADV:表示高级模式链路层接口类型;

LIBNET_RAW4_ADV:表示高级模式原始套接字接口IPv4类型;

LIBNET_RAW6_ADV:表示高级模式原始套接字接口IPv4类型;

LIBNET_ADV_MASK:用来检测是否是高级模式。

初始化②:确定网络接口。

数据包发送的接口,一种是由自己指定,可以是网络接口的名字,如以太网接口eth0等,也可以是IP地址;一种是由libnet自动查询搜索,只要在函数libnet_init()的参数device赋值null即可,此时libnet会从系统中搜索可用的网络接口。

初始化③:获取libnet的句柄,执行完后返回一个libnet句柄,这个句柄里面包含了重要的信息。


#defineLIBNET_LINK0x00
#defineLIBNET_RAW40x01
#defineLIBNET_RAW60x02
#defineLIBNET_LINK_ADV0x08
#defineLIBNET_RAW4_ADV0x09
#defineLIBNET_RAW6_ADV0x0a
#defineLIBNET_ADV_MASK0x08


地址转换可以使用如下的函数来实现。


u_int32_tlibnet_name2addr4(libnet_t*l,char*host_name,u_int8_tuse_name);
char*libnet_addr2name4(u_int32_taddress,u_int8_tuse_name);


构造数据包构造:一个数据包就是构造一系列协议块。

数据包检测:数据包的检测最主要的是计算校验和,如果不想自己计算校验和,只需要将校验和的参数赋值为0即可,libnet会自动计算校验和。

数据包发送:非常简单,只要由函数libnet_write()来完成即可。

具体构造如ARP数据包的流程如图3所示。

B3.png

完整的实现代码如下:


#if(HAVE_CONFIG_H)
#if((_WIN32)!(__CYGWIN__))
#include../include/win32/config.h
#else
#include../include/config.h
#endif
#endif
#include./libnet_test.h
int
main(intargc,char*argv[])
{
intc;
uint32_ti;
libnet_t*l;
libnet_ptag_tt;
char*device=NULL;
uint8_t*packet;
uint32_tpacket_s;
charerrbuf[LIBNET_ERRBUF_SIZE];
printf(libnet1.1packetshaping:ARP[link--autobuildingethernet]\n);
if(argc>1)
{
device=argv[1];
}
l=libnet_init(
LIBNET_LINK_ADV,
/*injectiontype*/
/*networkinterface*/
/*errbuf*/
device,
errbuf);
if(l==NULL)
{
fprintf(stderr,%s,errbuf);
exit(EXIT_FAILURE);
}
else
i=libnet_get_ipaddr4(l);
t=libnet_build_arp(
ARPHRD_ETHER,
/*hardwareaddr*/
/*protocoladdr*/
ETHERTYPE_IP,
6,
/*hardwareaddrsize*/
/*protocoladdrsize*/
/*operationtype*/
/*senderhardwareaddr*/
/*senderprotocoladdr*/
/*targethardwareaddr*/
/*targetprotocoladdr*/
/*payload*/
4,
ARPOP_REPLY,
enet_src,
(uint8_t*)i,
enet_dst,
(uint8_t*)i,
NULL,
0,
/*payloadsize*/
l,
/*libnetcontext*/
0);
/*libnetid*/
if(t==-1)
{
fprintf(stderr,CantbuildARPheader:%s\n,libnet_geterror(l));
gotobad;
}
t=libnet_autobuild_ethernet(
enet_dst,
/*ethernetdestination*/
/*protocoltype*/
ETHERTYPE_ARP,
l);
/*libnethandle*/
if(t==-1)
{
fprintf(stderr,Cantbuildethernetheader:%s\n,
libnet_geterror(l));
gotobad;
}
if(libnet_adv_cull_packet(l,packet,packet_s)==-1)
{
fprintf(stderr,%s,libnet_geterror(l));
}
else
{
fprintf(stderr,packetsize:%d\n,packet_s);
libnet_adv_free_packet(l,packet);
}
c=libnet_write(l);
if(c==-1)
{
fprintf(stderr,Writeerror:%s\n,libnet_geterror(l));
gotobad;
}
else
{
fprintf(stderr,Wrote%dbyteARPpacketfromcontext\%s\;
checkthewire.\n,c,libnet_cq_getlabel(l));
}
libnet_destroy(l);
return(EXIT_SUCCESS);
bad:
}
libnet_destroy(l);
return(EXIT_FAILURE);

相关推荐