最近搬砖需要对libnet进行介绍在这里对知识进行汇总。

1libnet简介

在libnet出现以前,如果要构造数据包并发送到网络中,程序员要通过一些复杂的接口来处理。libnet的出现,为程序员提供了一个简单而易于使用的编程接口,可以帮助程序员方便地构造网络数据包,编写网络应用程序。

libnet是一个与libpcap类似的数据包注入器,可以用来编写有关网络测试、网络故障诊断和网络安全等方面的应用程序和工具。

许多网络工具 (如snort,Nmap)都是利用它来实现其部分功能。

libnet提供一系列的接口函数,实现和封装了数据包的构造和发送过程。利用它可以亲自构造从应用层到链路层的各层协议的数据包头,并将这些包头与有效数据有序地组合在一起发送出去。当然,它也是基于TCP/IP协议网络模型的。

全部源代码包括18,000行代码,109个导出函数,其中包括67个建包函数。这使得它支持现有的TCP/IP族的所有协议。

2libnet的特点

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

它具有以下特点:

(1)高层接口:libnet被用于提取低 层数据报转移的专用体系结构细节。

(2)低层数据报构建:libnet的一个主要特点就是它完全控制每个数据报的头 域。

(3)可移植性的接口:与具体的操作系统平台无关。libnet目前可以在Windows、Linux、OS、FreeBSD、Solaris等操作系统上运行,并且提供了统一的接口。

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

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

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

(7)libnet支持TCP/IP协议族中的所有协议。

libnet函数库提供的接口函数包含 15 种数据包生成器和两种数据包发送器(IP 层和数据链路层)。

提供的接口函数包括:

1)内存管理(分配和释放)函数

2)地址解析函数

3)各种协议类型的数据包构造函数

4)数据包发送函数(IP层和链路层)

5)一些辅助函数,如产生随机数、错误报告、端口列表管理等。

利用libnet函数库开发应用程序的基本步骤:

1)数据包内存初始化

2)构造数据包

3)发送数据

4)释放资源

以发送 UDP 数据包为例,流程图如图

常用函数介绍

以下函数的使用需要包含头文件libnet.h

1、libnet_t *libnet_init(int injection_type, char *device, char *err_buf)

功能:

数据包内存初始化及环境建立

参数:

injection_type:构造的类型

LIBNET_LINK,链路层

LIBNET_RAW4,网络接口层(网络层)

LIBNET_LINK_ADV,链路层高级版本

LIBNET_RAW4_ADV,网络层高级版本

device:网络接口,如 "eth0",或IP地址,亦可为NULL (自动查询搜索)

err_buf:存放出错的信息

返回值:

成功:一个libnet *类型的指针,后面的操作都得使用这个指针

失败:NULL

该函数初始化libnet函数库,返回一个libnet_t类型的描述符,以备随后的构造数据包和发送数据包的函数中使用。

injection_type指明了发送数据包使用的 接口类型,如数据链路层或者原始套接字等。Device是一个网络设备名称的字符串,在linux下“eth0”等。如果函数错误,返回NULL,er_buf字符串中将携带有错误的原因。

2、void libnet_destroy(libnet_t *l);

功能:

释放资源

参数:

l:libnet_init() 返回的libnet *指针

返回值:

3、char* libnet_addr2name4(u_int32_t in, u_int8_t use_name)

功能:

将网络字节序转换成点分十进制数串

参数:

in:网络字节序的ip地址

use_name:

LIBNET_RESOLVE,对应主机名

LIBNET_DONT_RESOLVE,对应点分十进制IPv4地址

返回值:

成功:点分十进制ip地址

失败:NULL

4、u_int32_t libnet_name2addr4(libnet_t *l, char *host_name, u_int8_t use_name)

功能:

将点分十进制数串转换为网络字节序ip地址

参数:

l:libnet_init()返回的libnet *指针

host_name:

LIBNET_RESOLVE,  对应主机名

LIBNET_DONT_RESOLVE,对应点分十进制 IPv4 地址

返回值:

成功:网络字节序 ip 地址

失败:-1

5、struct libnet_ether_addr* libnet_get_hwaddr(libnet_t *l)

功能:

获取接口设备硬件地址

参数:

l:libnet_init()返回的libnet *指针

返回值:

成功:指向MAC地址的指针

失败:NULL

6、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_init()返回的libnet *指针

ptag:协议标记,第一次组新的发送包时,这里写0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:

成功:协议标记

失败:-1

7、libnet_ptag_t libnet_build_tcp(u_int16_t sp, u_int16_t dp, u_int32_t seq, u_int32_t ack, u_int8_t control, u_int16_t winu_int16_t sum, u_int16_t urg, u_int16_t len, u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag );

功能:

构造 tcp 数据包

参数:

sp:源端口号

dp:目的端口号

seq:序号

ack:ack 标记

control:控制标记

win:窗口大小

sum:校验和,设为 0,libnet 自动填充

urg:紧急指针

len:tcp包长度

payload:负载,为给应用程序发送的文本内容,可设置为 NULL

payload_s:负载长度,或为 0

l:libnet_init() 返回的 libnet * 指针

ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:

成功:协议标记

失败:-1

8、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 )

功能:

构造一个 IPv4 数据包

参数:

ip_len:ip 包总长

tos:服务类型

id:ip 标识

flag:片偏移

ttl:生存时间

prot:上层协议

sum:校验和,设为 0,libnet 自动填充

src:源ip地址

dst:目的ip地址

payload:负载,可设置为 NULL(这里通常写 NULL)

payload_s:负载长度,或为 0(这里通常写 0 )

l:libnet 句柄,libnet_init()返回的libnet * 指针

ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:

成功:协议标记

失败:-1

9、libnet_ptag_t libnet_build_ethernet(u_int8_t*dst, u_int8_t *src, u_int16_ttype, u_int8_t*payload, u_int32_tpayload_s, libnet_t*l, libnet_ptag_t ptag )

功能:

构造一个以太网数据包

参数:

dst:目的mac

src:源mac

type:上层协议类型

payload:负载,即附带的数据,可设置为 NULL(这里通常写 NULL)

payload_s:负载长度,或为 0(这里通常写 0 )

l:libnet 句柄,libnet_init() 返回的 libnet * 指针

ptag:协议标记,第一次组新的发送包时,这里写0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:

成功:协议标记

失败:-1

10、int libnet_write(libnet_t * l)

功能:

发送数据包

参数:

l:libnet 句柄,libnet_init()返回的 libnet * 指针

返回值:

成功:发送数据包的长度

失败:返回 -1

libnet的使用案例

1、在Ubuntu上安装libnet

安装命令:sudo apt-get install libnet-dev,图23-2

图23-2 libnet在linux中安装

2、按照图23-1编写发送UDP数据包的代码

#include <stdio.h> 

#include <stdlib.h> 

#include <string.h> 

#include <unistd.h> 

#include <libnet.h> 

 

int main(int argc, charchar *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,0x97,0xc7,0xc1};

//发送者网卡地址00:0c:29:97:c7:c1 

    unsigned char dst_mac[6] = {0x74,0x27,0xea,0xb5,0xff,0xd8};

//接收者网卡地址74-27-EA-B5-FF-D8 

    char *src_ip_str = "192.168.31.163"; //源主机IP地址 

    char *dst_ip_str = "192.168.31.248"; //目的主机IP地址 

    unsigned long src_ip,dst_ip = 0; 

 

    lens = sprintf(send_msg, "%s", "this is for the udp test"); 

 

    lib_net = libnet_init(LIBNET_LINK_ADV, NULL, err_buf);    //初始化 

    if(NULL == lib_net) 

    { 

        perror("libnet_init"); 

        exit(-1); 

    } 

 

    src_ip = libnet_name2addr4(lib_net,src_ip_str,LIBNET_RESOLVE); 

//将字符串类型的ip转换为顺序网络字节流 

    dst_ip = libnet_name2addr4(lib_net,dst_ip_str,LIBNET_RESOLVE); 

 

    lib_t=libnet_build_udp(  //构造udp数据包

8080, 8080, 8+lens, 0, send_msg, lens, lib_net, 0); 

 

    lib_t = libnet_build_ipv4(  //构造ip数据包 

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,0x800,NULL,0,lib_net,0); 

    int res = 0; 

    res = libnet_write(lib_net);    //发送数据包 

    if(-1 == res) 

    { 

        perror("libnet_write"); 

        exit(-1); 

    } 

 

    libnet_destroy(lib_net);    //销毁资源 

     

    printf("----ok-----\n"); 

    return 0; 

 } 

编译代码时,注意需要加上 -lnet,输入命令编译源代码,生成demo可执行文件,运行可执行文件,如图23-3

图23-3 libnet在linux中安装

3、抓包分析

利用wireshark进行抓包如图23-4

23-4 libnet的抓包结果

可以看出成功的用libnet构造了一个UDP的数据包。

libnet的使用详解的更多相关文章

  1. 基于CentOS6.5或Ubuntu14.04下Suricata里搭配安装 ELK (elasticsearch, logstash, kibana)(图文详解)

    前期博客 基于CentOS6.5下Suricata(一款高性能的网络IDS.IPS和网络安全监控引擎)的搭建(图文详解)(博主推荐) 基于Ubuntu14.04下Suricata(一款高性能的网络ID ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  4. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  7. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  8. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

随机推荐

  1. .net core 和 WPF 开发升讯威在线客服系统:怎样实现拔网线也不丢消息的高可靠通信(附视频)

    本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...

  2. Byte Buddy学习笔记

    本文转载自Byte Buddy学习笔记 简介 Byte Buddy是一个JVM的运行时代码生成器,你可以利用它创建任何类,且不像JDK动态代理那样强制实现一个接口.Byte Buddy还提供了简单的A ...

  3. scala:函数作为值或参数进行传递、作为返回值进行返回

    @ 目录 函数可以作为值进行传递 函数可以作为参数进行传递 函数可以作为返回值进行返回 什么是匿名函数 函数可以作为值进行传递 语法var f = 函数名 _ 如果明确了变量的数据类型,那么下划线可以 ...

  4. 前端传数据到后台,后台用实体类接收不到引发的思考----Java bean中字段命名潜规则

    1.按照Java语法规范,通常在实体类中的属性,首字母都是小写的.这是由于JavaBean的规范导致的.一般JavaBean属性都是首字母小写,以驼峰命名格式命名,相应的 getter/setter ...

  5. 使用Mongodb设计评论系统

    1:如何设计数据存储结构 1.1:mysql 1:评论表 2:回复表(评论的评论) 1.2:mongodb 不需要两张表,一个collection 就可以搞定. 数据结构如图: 通过对象数组中的字段作 ...

  6. MYSQL 悲观锁和乐观锁简单介绍及实现

    1:悲观锁 1.1 特点: 每次查询都会进行锁行,怕"其他人"进行数据的修改. 1.2 实现步骤: 步骤1:开启事务test1,并对id=2的记录进行查询,并加锁,如:   步骤2 ...

  7. 错误信息:...\output\project.axf: error: l6218e: undefined symbol usart1_confing (referred from main.o).

    说明:此文档知识用来记录,顺便给大家作为参考,如有错误的地方请大家多多指正,在下内心定会感激不尽. 前言:关于这个问题,我曾花了一个下午在网上寻找,网上的说法五花八门,我办法试尽,但遍寻无果.由此我认 ...

  8. token、cookie和session区别以及django中的cookie,csrf

    参考:https://my.oschina.net/xianggao/blog/395675?fromerr=GC9KVenE [前言]登录时需要post的表单信息. 先跳过具体案例,讲解基础知识: ...

  9. 力扣208. 实现 Trie (前缀树)

    原题 以下是我的代码,就是简单的字符串操作,可以ac但背离了题意,我之前没接触过Trie 1 class Trie: 2 3 def __init__(self): 4 ""&qu ...

  10. 剑指 Offer 17. 打印从1到最大的n位数

    剑指 Offer 17. 打印从1到最大的n位数 Offer 17 题目解析: 暴力解法 package com.walegarrett.offer; /** * @Author WaleGarret ...