一、概念
专业的构造和发送网络数据包的开发工具包,是个高层次的API函数库,允许开发者自己构造和发送网络数据包。
头文件:#include<libnet.h>
编译加:-lnet
二、Libnet特点
①隐藏了很多底层细节,省去了很多麻烦:如缓冲区管理、字节流顺序、校验和计算等问题,使开发者把重心放到程序的开发中。
②可以轻松、快捷的构造任何形式的网络数据包,从而开发各种各样的网络程序。
③使用非常广泛,例子著名的软件Ettercap、Firewalk、Snort、Tcpreplay等。
④在1998年就出现了,但那时候还有很多缺陷,比如计算校验和非常繁琐等;
⑤Schiffman对其进行了完善,而且功能更加强大。至此,可以谁Libnet开发包非常完美了,使用人数越来越多。
三、Libnet库的安装
sudo apt-get install libnet-dev
四、开发流程
利用libnet函数库开发应用程序的基本步骤
①数据包内存初始化
②构造数据包
③发送数据
④释放资源
libnet库主要功能
①内存管理
②地址解析
③包处理
内存管理相关函数
①初始化
libnet_t *libnet_init(int injection_type, char *device, char *err_buf);
功能:数据包内存初始化及环境建立
参数:injection_type:构造的类型(LIBNET_LINK,LIBNET_TAW4, LIBNET_LINK_ADV(推荐), LIBNET_RAW4_ADV)
device:网络接口,如"eth0"或IP地址,亦可为NULL(自动查询搜索)
err_buf:存放出错的信息
返回值:成功返回一个libnet句柄,失败返回NULL
②构建数据包
构建UDP报文
libnet_ptag_t libnet_build_udp(u_int16_t sp, u_int16_t dp,
u_int16_t len, u_int16_t sum,
u_int8_t *payload, u_int32_t payload_s,
libnet_t *l, libnet_ptag_t ptag);
功能:构造UDP数据包
参数:sp:源端口号
dp:目的端口号
len:UDP包总长度
sum:校验和,设为0,libnet自动填充
payload:负载,可设置为NULL
payload_s:负载长度,或为0
l:libnet句柄
ptag:协议标记
返回值:成功返回协议标记;失败返回-1
构建IPv4数据包
libnet_ptag_t libnet_build_ipv4(u_int16_t ip_len, u_int8_t tos,
u_int16_t id, u_int16_t flag,
u_int8_t ttl, u_int8_t port,
u_int16_t sum, u_int32_t src,
u_int32_t dst, u_int8_t *payload,
u_int32_t payload_s, libnet_t *l,
libnet_ptag_t ptag);
功能:构造一个IPv4数据包
参数:ip_len:ip包总长
tos:服务类型
id:id表示
flag:片偏移
ttl:生存时间
prot:上层协议
sum:校验和,设为0,libnet自动填充
src:源IP地址
dst:目的IP地址
payload:负载,可设置为NULL
payload_s:负载长度,或为0,
l:libnet句柄
ptag:协议标记
返回值:成功返回协议标记;失败返回-1
构建以太网数据包
libnet_ptag_t libnet_build_ethernet(u_int8_t *dst, u_int8_t *src,
u_int16_t type, u_int8_t *payload,
u_int32_t payload_s, libnet_t *l,
libnet_ptag_t ptag);
功能:构造一个以太网数据包
参数:dst:目的mac
src:源mac
type:上层协议类型
payload:负载,即附带的数据
payload_s:负载长度
l:libnet句柄
ptag:协议标记
返回值:成功返回协议标记;失败返回-1
③发送帧数据
int libnet_write(libnet_t *l);
功能:发送数据到网络
参数:l:libnet句柄
返回值:失败返回-1,成功返回其他。
④释放资源
void libnet_destroy(libnet_t *l);
功能:释放资源
参数:l:libnet句柄
返回值:无
例子:
#include <stdio.h>
#include <string.h>
#include <libnet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
//1.初始化内存
libnet_t *lib_handle = libnet_init(LIBNET_LINK_ADV,"enp0s3",NULL);
//获取键盘输入
char data[128]="";
printf("请输入数据:\n");
fgets(data,sizeof(data),stdin);
data[strlen(data-1)]=0;
int data_len = strlen(data)+strlen(data)%2; //将长度变为偶数
//2.构建数据包:从应用层--->链路层
//构建UDP数据(传输层)
libnet_ptag_t ptag_udp =libnet_build_udp(8000,9000,8+data_len,0,data,data_len,lib_handle,0);
//构建IPv4数据(网络层)
libnet_ptag_t ptag_ip = libnet_build_ipv4(20+8+data_len,0,0,0,128,17,0,inet_addr("192.168.199.208"),inet_addr("192.168.199.233"),NULL,0,lib_handle,0);
//构建以太网数据包(链路层)
unsigned char src_mac[6]={0x08,0x00,0x27,0x2d,0x9b,0x84}; //虚拟机mac
unsigned char dst_mac[6]={0x80,0xc5,0xf2,0xb9,0x8c,0x03}; //windows的mac
libnet_ptag_t ptag_mac = libnet_build_ethernet(dst_mac,src_mac,0x0800,NULL,0,lib_handle,0);
//3.发送帧数据
libnet_write(lib_handle);
//4.释放资源
libnet_destroy(lib_handle);
return 0;
}