c语言基于Linux下用libpcap实现抓包程序

c语言基于libpcap实现一个抓包程序过程

基于pcap的嗅探器程序的总体架构,其流程如下:(1)首先要决定用哪一个接口进行嗅探开始。在Linux中,这可能是eth0,而在BSD系统中则可能是xl1等等。我们也可以用一个字符串来定义这个设备,或者采用pcap提供的接口名来工作。(...

基于pcap的嗅探器程序的总体架构,其流程如下:

(1)首先要决定用哪一个接口进行嗅探开始。在Linux中,这可能是eth0,而在BSD系统中则可能是xl1等等。我们也可以用一个字符串来定义这个设备,或者采用pcap提供的接口名来工作。

(2)初始化pcap。在这里需要告诉pcap对什么设备进行嗅探。假如愿意的话,我们还可以嗅探多个设备。怎样区分它们呢?使用 文件句柄。就像打开一个文件进行读写一样,必须命名我们的嗅探“会话”,以此使它们各自区别开来。

(3)如果只想嗅探特定的传输(如TCP/IP包,发往端口23的包等等),我们必须创建一个规则集合,编译并且使用它。这个过程分为三个相互紧密关联的阶段。 规则集合被置于一个字符串内,并且被转换成能被pcap读的格式(因此编译它)。编译实际上就是在我们的程序里调用一个不被外部程序使用的函数。接下来我们要告诉 pcap使用它来过滤出我们想要的那一个会话。(此步骤可选)

(4)最后,我们告诉pcap进入它的主体执行循环。在这个阶段内pcap一直工作到它接收了所有我们想要的包为止。每当它收到一个包就调用另一个已经定义好的函数,这个函数可以做我们想要的任何工作,它可以剖析所部获的包并给用户打印出结果,它可以将结果保存为一个文件,或者什么也不作。

(5)在嗅探到所需的数据后,我们要关闭会话并结束。

编程实现过程:

(1)设置设备

这是很简单的。有两种方法设置想要嗅探的设备。

第一种,我们可以简单的让用户告诉我们。考察下面的程序:  

#include <stdio.h>
#include <pcap.h>
int main(int argc, char *argv[])
{
char *dev = argv[1];
printf("Device: %s", dev);
return(0);
}

运行:

[email protected] /h/jiabei# vim a1.c

[email protected] /h/jiabei# gcc a1.c -lpcap

[email protected] /h/jiabei# ./a.out

Device : (null)                             (输出)

用户通过传递给程序的第一个参数来指定设备。字符串“dev”以pcap能“理解”的格式保存了我们要嗅探的接口的名字(当然,用户必须给了我们一个真正存在的接口)。

另一种也是同样的简单。来看这段程序:  

#include <stdio.h>
#include <pcap.h>
int main()
{
char *dev, errbuf[PCAP_ERRBUF_SIZE];
dev = pcap_lookupdev(errbuf);
printf("Device: %s", dev);
return(0);
}

运行:

[email protected] /h/jiabei# vim a2.c

[email protected] /h/jiabei# gcc a2.c -lpcap

error :‘errbuf‘ undeclared ....                (输出)

我们发现 errbuf[]数组未定义。

于是:

#include <stdio.h>
#include <pcap.h>
char errbuf[PCAP_ERRBUF_SIZE];
int main()
{
char *dev, errbuf[PCAP_ERRBUF_SIZE];
dev = pcap_lookupdev(errbuf);
printf("Device: %s", dev);
return(0);
}

再次运行:

[email protected] /h/jiabei# vim a2.c

[email protected] /h/jiabei# gcc a2.c -lpcap

Device: eth0                                   (输出,即Linux 下默认为eth0端口)

(2)打开设备进行嗅探

创建一个嗅探会话的任务真的非常简单。为此,我们使用pcap_open_live()函数。此函数的原型(根据pcap的手册页)如下:  


1

pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)

其第一个参数是我们在上一节中指定的设备,snaplen是整形的,它定义了将被pcap捕捉的最大字节数。当promisc设为true时将置指定接口为混杂模式(然而,当它置为false时接口仍处于混杂模式的非凡情况也是有可能的)。to_ms是读取时的超时值,单位是毫秒(假如为0则一直嗅探直到错误发生,为-1则不确定)。最后,ebuf是一个我们可以存入任何错误信息的字符串(就像上面的errbuf)。此函数返回其会话句柄。

混杂模式与非混杂模式的区别:这两种方式区别很大。一般来说,非混杂模式的嗅探器中,主机仅嗅探那些跟它直接有关的通信,如发向它的,从它发出的,或经它路由的等都会被嗅探器捕捉。而在混杂模式中则嗅探传输线路上的所有通信。在非交换式网络中,这将是整个网络的通信。这样做最明显的优点就是使更多的包被嗅探到,它们因你嗅探网络的原因或者对你有帮助,或者没有。但是,混杂模式是可被探测到的。一个主机可以通过高强度的测试判定另一台主机是否正在进行混杂模式的嗅探。其次,它仅在非交换式的网络环境中有效工作(如集线器,或者交换中的ARP层面)。再次,在高负荷的网络中,主机的系统资源将消耗的非常严重。

(3)过滤通信

实现这一过程由pcap_compile()与pcap_setfilter()这两个函数完成。

在使用我们自己的过滤器前必须编译它。过滤表达式被保存在一个字符串中(字符数组)。其句法在tcpdump的手册页中被证实非常好。我建议你亲自阅读它。但是我们将使用简单的测试表达式,这样你可能很轻易理解我的例子。

我们调用pcap_compile()来编译它,其原型是这样定义的:  


1

int pcap_compile(pcap_t
*p, strUCt bpf_program *fp, char *str, int optimize,
bpf_u_int32 netmask)

第一个参数是会话句柄。接下来的是我们存储被编译的过滤器版本的地址的引用。再接下来的则是表达式本身,存储在规定的字符串格式里。再下边是一个定义表达式是否被优化的整形量(0为false,1为true,标准规定)。最后,我们必须指定应用此过滤器的网络掩码。函数返回-1为失败,其他的任何值都表明是成功的。

表达式被编译之后就可以使用了。现在进入pcap_setfilter()。仿照我们介绍pcap的格式,先来看一看pcap_setfilter()的原型:  


1

int pcap_setfilter(pcap_t
*p, struct bpf_program
*fp)

这非常直观,第一个参数是会话句柄,第二个参数是被编译表达式版本的引用(可推测出它与pcap_compile()的第二个参数相同)。

下面的代码示例可能能使你更好的理解:  

#include <pcap.h>
int main()
{
pcap_t *handle; /* 会话的句柄 */
char dev[] = "eth0"; /* 执行嗅探的设备 */
char errbuf[PCAP_ERRBUF_SIZE]; /* 存储错误 信息的字符串 */
struct bpf_program filter; /*已经编译好的过滤表达式*/
char filter_app[] = "port 23"; /* 过滤表达式*/
bpf_u_int32 mask; /* 执行嗅探的设备的网络掩码 */
bpf_u_int32 net; /* 执行嗅探的设备的IP地址 */
pcap_lookupnet(dev, &net, &mask, errbuf);
handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
pcap_compile(handle, &filter, filter_app, 0, net);
pcap_setfilter(handle, &filter);
}

这个程序使嗅探器嗅探经由端口23的所有通信,使用混杂模式,设备是eth0。

(4)实际的嗅探

有两种手段捕捉包。我们可以一次只捕捉一个包,也可以进入一个循环,等捕捉到多个包再进行处理。我们将先看看怎样去捕捉单个包,然后再看看使用循环的方法。为此,我们使用函数pcap_next()。

pcap_next()的原型及其简单:

   u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)

第一个参数是会话句柄,第二个参数是指向一个包括了当前数据包总体信息(被捕捉时的时间,包的长度,其被指定的部分长度)的结构体的指针(在这里只有一个片断,只作为一个示例)。pcap_next()返回一个u_char指针给被这个结构体描述的包。我们将稍后讨论这种实际读取包本身的手段。

   这里有一个演示怎样使用pcap_next()来嗅探一个包的例子:  

#include <pcap.h>
#include <stdio.h>
int main()
{
pcap_t *handle; /* 会话句柄 */
char *dev; /* 执行嗅探的设备 */
char errbuf[PCAP_ERRBUF_SIZE]; /* 存储错误信息的字符串 */
struct bpf_program filter; /* 已经编译好的过滤器 */
char filter_app[] = "port 23"; /* 过滤表达式 */
bpf_u_int32 mask; /* 所在网络的掩码 */
bpf_u_int32 net; /* 主机的IP地址 */
struct pcap_pkthdr header; /* 由pcap.h定义 */
const u_char *packet; /* 实际的包 */
/* Define the device */
dev = pcap_lookupdev(errbuf);
/* 探查设备属性 */
pcap_lookupnet(dev, &net, &mask, errbuf);
/* 以混杂模式打开会话 */
handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
/* 编译并应用过滤器 */
pcap_compile(handle, &filter, filter_app, 0, net);
pcap_setfilter(handle, &filter);
/* 截获一个包 */
packet = pcap_next(handle, &header);
/* 打印它的长度 */
printf("Jacked a packet with length of [%d]
", header.len);
/* 关闭会话 */
pcap_close(handle);
return(0);
}

运行:

[email protected] /h/jiabei# vim a3.c

[email protected] /h/jiabei# gcc a3.c -lpcap

Jacked a packet with length of [1]

(输出)

这个程序嗅探被pcap_lookupdev()返回的设备并将它置为混杂模式。它发现第一个包经过端口23(telnet)并且告诉用户此包的大小(以字节为单位)。

时间: 2024-10-12 23:02:55

c语言基于Linux下用libpcap实现抓包程序的相关文章

基于libpcap实现抓包程序

前言 原创文章欢迎转载,请保留出处. 若有任何疑问建议,欢迎回复. 邮箱:[email protected] 紧接着上一篇,成功通过tcpdump和wireshark抓包后,试试自己写一个抓包器.这里我们使用libpcap库开发. 创建配置工程 这里我们使用Eclipse for C/C++开发,安装的话只需要到eclipse官方下载解压就可以运行了,这里要注意的是,Eclipse要以root权限启动不然无法抓包. 首先创建一个空白的C语言项目,工具链选择Linux GCC 添加源文件,起名ma

基于HTTP访问特定URL的抓包程序该怎么写

抓包是一个简单易行的事,它可以帮你分析网络的行为.我记得早在2004年的时候,老师就讲过抓包有多么重要.        作为程序员而言,除了抓包几乎没有任何手段探测网络行为,程序员没有机会触摸网络设备,也就没有能力洞悉网络细节,程序员唯一能触摸到的就是自己的终端,在这个终端上唯一能做的就是抓包.我是半个程序员,所以不管站在谁的立场上,我都认为抓包是一个重要的事,虽然在我内心看来,抓包和分析数据包解决不了大多数的问题....        在一台承载大量业务的机器上怎么抓包成了一个问题.因为虚拟主

基于Linux下Nagios的安装与配置说明介绍[图]

本篇文章小编为大家介绍,基于Linux下Nagios的安装与配置说明介绍[图].需要的朋友参考下 一.Nagios简介 Nagios是一款开源的电脑系统和网络监视工具,能有效监控Windows.Linux和Unix的主机状态,交换机路由器等网络设置,打印机等.在系统或服务状态异常时发出邮件或短信报警第一时间通知网站运维人员,在状态恢复后发出正常的邮件或短信通知. Nagios原名为NetSaint,由Ethan Galstad开发并维护至今.NAGIOS是一个缩写形式: "Nagios Ain'

基于linux下的NIST数字测试(下)——测试过程

基于linux下的NIST数字测试(下)--测试过程 1.下载安装Matlab--来自微信公众号,软件安装管家 利用Matlab生成随机数x = randsrc(1,32e3,[0,1]) 把数据复制到txt文本中 然后把随机数矩阵的文本suijishu.txt复制到ubuntu 的NIST数字测试目录下 2.准备环境,进行测试 按着提示进行选择,并且输入文件名 选择测试类型 分别对应以下15种测试类型 1.频率(单比特)测试 2.块内频数测试(Frequency Test within a B

Linux下简单的取点阵字模程序

源:Linux下简单的取点阵字模程序 Linux操作系统下进行简单的图形开发,经常会用到取字模的软件,但是Linux并没有像Windows下的小工具可用,我们也并不希望为了取字模而频繁地切换操作系统.(由于是完全由C语言编写,所以不需要任何修改,这个字库同样可以用在嵌入式环境的Windows操作系统下面) 本人结合网上的资料,对这个问题进行了总结,整理了代码,供有需要的朋友使用我参考.转载请注明出处:http://blog.csdn.net/weiwang876253631/article/de

Linux下使用pdb简单调试python程序

python自带调试工具库:pdb # -*- coding:utf-8 -*- def func(num): s = num * 10 return s if __name__ == '__main__': print 'debug starting...' print '*' * 10 print 'debug ending-' num = 100 s = func(num) print s 在python文件中不引用pdb库,可以在执行python文件的时候,加上参数: python -m

基于Linux C的socket抓包程序和Package分析 (一)

 测试运行平台:CentOS 6.5发行版,内核版本3.11 1. Linux抓包源程序 在OSI七层模型中,网卡工作在物理层和数据链路层的MAC子层. 进行网络通信时,源主机通过socket(或其它)应用程序产生IP报文,经过各个OSI层层封装,数据包以Ethernet帧的形式进入物理层.Ethernet帧包含源主机地址.IP报文.目标地址(IP地址.端口号或映射的6字节MAC地址)和需要传送到目标主机的其它信息. 目标的MAC地址是哪里来的呢?这牵扯到一个ARP协议(介乎于网络层和数据链

在linux下安装eclipse以及运行c++程序的安装步骤

1.       下载jre,eclipse,cdt 其中jre是java运行环境,eclipse需要先装jre,才可能运行,cdt是在eclipse中运行c\c++程序的插件. 下载jre 网址是:http://www.oracle.com/technetwork/java/javase/downloads/index.html,点击JRE下载(如下图) 选择"Aceept License Argeement" (如上图) 点击"jre-7u21-linux-i586.bi

Linux下通过源码编译安装程序

ASK: Linux下通过源码编译安装程序(configure/make/make install的作用) configure Linux 平台有各种不同的配置,安装时需要通过 configure 来确定,如:编译器用的是 cc 还是 gcc.不同库文件所在目录等.执行 configure 后会生成 Makefile,Makefile 规定了用什么编译器.编译参数等信息. make 根据 Makefile 中规定的内容进行编译,生成的可执行文件放在当前目录或某个子目录. make install