当前位置:  编程语言>c/c++

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

 
    发布时间:2013-9-12  


    本文导语: 基于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一直工作到它接收了所有我们想要的包为止。每当它收到一个包就调用另一个已经定义好的函数,这个函数可以做我们想要的任何工作,它可以剖析所部获的包并给用户打印出结果,它可以将结果保存为一个php iis7站长之家,或者什么也不作。

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

编程实现过程:

(1)设置设备

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

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

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

用户通过传递给程序的第一个参数来指定设备。字符串“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);
}

(2)打开设备进行嗅探

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

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()来编译它,其原型是这样定义的:  

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()的原型:  

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()来嗅探一个包的例子:  

/*
http://www. 发布
*/
#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);
}

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


  • 本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载,整理或搜集自网络.欢迎任何形式的转载,转载请注明出处.
    转载请注明:文章转载自:[169IT-IT技术资讯]
    本文标题:c语言基于libpcap实现一个抓包程序过程
相关文章推荐:
  • 2013年7月和2013年8月编程语言排行榜
  • 如何在GTK2.0下实现国际化(语言选择根据自己设置的语言,不用系统的语言)
  • 2017 年热门编程语言排行榜出炉,你的语言上榜没?
  • C语言中有指针,因此C语言可以创建链表,那么Java语言没有指针,那Java是否可以创建链表呢?
  • 苹果OS X和IOS下最新编程语言swift介绍
  • linux如何根据当前的语言环境,分别写不同的语言到文件
  • c语言判断某一年是否为闰年的各种实现程序代码
  • 求助,在linux下,c语言和汇编语言的接口是什么?
  • PHP编程语言介绍及安装测试方法
  • C语言中间语言 CIL
  • Linux下C语言strstr()查找子字符串位置函数详细介绍(strstr原型、实现及用法)
  • 最近学JSP,苦于HTML语言和JAVA语言太差,请教推荐几本书,thanks.
  • c语言实现MD5算法完整代码示例
  • C语言如何改变当前语言环境
  • 以NetBeans IDE为例介绍如何使用XML中Schema语言
  • 如何在VIM中使汇编语言和C语言自动缩进?
  • HTML超文本标记语言教程及实例
  • 动态编程语言 LIME编程语言
  • MD5算法的C语言实现
  • 我安装的linux时默认语言选择的是中文,又乱码,怎么可以解决?怎么更改默认语言成英文?
  • HTML 脚本语言介绍及<script>标签用法
  • Redhat9安装时语言只选择了中文,现在还能再增加其它语言的支持吗?如英文


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3