|
<%=(int(rnd()*1)+1)%>您当前的位置:中国安全在线cnsafer.com 请进入[技术论坛]发表评论 阅读提示:
1、 用户在命令行指定定监听的网络接口:
#include <stdio.h> #include <pcap.h> int main(int argc, char *argv[]) { char *dev = argv[1]; printf("Device: %s\n", dev); return(0); }
用户通过命令行参数传入监听接口。 译注:在实际的项目开发中务必对命令行参数进行判断:
if (argc < 2) {
printf(“Usage: %s <option>\n”, argv[0]);
exit(1);
}
2、 通过pcap引擎设定监听的网络接口:
#include <stdio.h> #include <pcap.h> int main() { char *dev, errbuf[PCAP_ERRBUF_SIZE]; dev = pcap_lookupdev(errbuf); printf("Device: %s\n", dev); return(0); }
在这种情况下,pcap引擎自己设置用来监听的接口。但是errbuf字符串用来做什么呢?大多数的pcap函数允许我们传递这样一个字符串作为其参数。这个字符串参数用来在pcap函数调用失败以后用来设置出错信息。在上面的例子中,如果pcap_lookup函数调用失败,出错信息将被保存在errbuf中。 译注:增加的错误检查的代码如下:
if (NULL == (dev = pcap_lookupdev(errbuf))) {
fprintf(stderr, “pcap_lookupdev() error: %s\n”, errbuf);
exit(-1);
}
printf(“Device: %s\n”, dev);
Opening the device for sniffing 创建sniff会话的任务非常简单。我们使用pcap_open_live()创建sniff会话。函数原型:
pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
device:上节中我们制定的监听设备接口;
snaplen:制定pcap捕获的最大数目的网络数据包;
promisc:>0指定device接口工作在混杂模式(promiscous Mode);
to_ms:制定经过特定时间(ms)后读超时;0表示遇到错误退出,-1指定永不超时;
ebuf:制定用来存储出错信息的字符串
pcap_t:返回值为用于监听的pcap会话。
示例代码:
#include <pcap.h> ... pcap_t *handle; handle = pcap_open_live(somedev, BUFSIZ, 1, 0, errbuf); 上面的代码打开somedev指定的设备并读取(捕获)BUFSIZ字节,同时我们设置接口工作在混杂模式,一直监听到有任何错误发生则退出,并将出错信息保存在errbuf指定的字符串中。 关于混杂模式vs.非混杂模式:通常情况在非混杂模式下仅监听直接发往主机的数据包:发往、源自或通过主机路由的数据包都将被pcap捕获;混杂模式下,所有发送到物理链路上的数据包都将被捕获。在一个共享式的网络环境中,这将导致整个网络的数据流被监听。混合监听模式是可以被检测的:可以通过测试强可靠性来发现网络中是否有主机正在以混合模式监听,另外混杂工作模式仅仅在非交换式的网络中有效,而且在一个高负载的网络环境中,混杂模式将消耗大量的系统资源。 Filter traffic 通常我们只对特定网络通信感兴趣。比如我们只打算监听Telnet服务(port 23)以捕获用户名和口令信息。获知对FTP(port 21)或DNS(UDP port 53)数据流感兴趣。可以通过pcap_compile()和pcap_setfilter来设置数据流过滤规则(filter) 函数原型: int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask) p:表示pcap会话句柄; fp:存放编译以后的规则; str:规则表达式格式的过滤规则(filter),同tcpdump中的filter;
optimize:制定优化选项:0 false, 1 true;
netmask:监听接口的网络掩码; 返回值:-1表示操作失败,其他值表成功。
int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
p:表示pcap的会话句柄;
fp:表示经过编译后的过滤规则;
返回值:-1表示操作失败,其他值表成功。 示例代码:
#include <pcap.h> ... pcap_t *handle; /* Session handle */ char dev[] = "rl0"; /* Device to sniff on */ char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */ struct bpf_program filter; /* The compiled filter expression */ char filter_app[] = "port 23"; /* The filter expression */ bpf_u_int32 mask; /* The netmask of our sniffing device */ bpf_u_int32 net; /* The IP of our sniffing device */ 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); 上面的代码设备rl0上以混杂模式监听所有发往或源自端口23的数据包。Pcap_lookupnet()函数返回给定接口的IP地址和子网掩码。 The actual sniffing 现在我们开始准备捕获数据包:有两种方法可以用来捕获数据包。要么一次捕获一个满足条件的数据包,要么进入一个循环过程捕获指定数量数据包然后退出。首先来了解使用pcap_next()一次捕获单一数据包。 函数原型:
u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
p:pcap会话句柄;
h:指向pcap_pkthdr接口的指针,在此结构中保存了所捕获的数据包的通用信息。包括:时间信息、数据包的长度和包头部分的长度(结构定义在后面定义)。
返回值:返回指向实际捕获的数据包的u_char *型指针。
代码示例:
#include <pcap.h> #include <stdio.h> int main() { pcap_t *handle; /* Session handle */ char *dev; /* The device to sniff on */ char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */ struct bpf_program filter; /* The compiled filter */ char filter_app[] = "port 23"; /* The filter expression */ bpf_u_int32 mask; /* Our netmask */ bpf_u_int32 net; /* Our IP */ struct pcap_pkthdr header; /* The header that pcap gives us */ const u_char *packet; /* The actual packet */ /* Define the device */ dev = pcap_lookupdev(errbuf); /* Find the properties for the device */ pcap_lookupnet(dev, &net, &mask, errbuf); /* Open the session in promiscuous mode */ handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf); /* Compile and apply the filter */ pcap_compile(handle, &filter, filter_app, 0, net); pcap_setfilter(handle, &filter); /* Grab a packet */ packet = pcap_next(handle, &header); /* Print its length */ printf("Jacked a packet with length of [%d]\n", header.len); /* And close the session */ pcap_close(handle); return(0); }
上面的代码将所有从pcap_lookupdev()返回的接口置于混杂模式监听状态。Pcap捕获端口23的一个数据包并打印该包的长度。然后调用pcap_close()关闭pcap会话。
当然我们可以使用更复杂和更强大的功能pcap_loop和pcap_dispatch。通常很少有sniffer使用pcap_next,他们更通常的使用pcap_loop或pcap_dispatch。为便于理解这两个函数,需要现了解回调函数的概念。 回调函数并不是一个新概念,在很多的API中都使用了回调函数的概念。可以通过pcap_loop或pcap_dispatch定义用户自己的回调函数。事实上pcap_loop和pcap_dispatch的功能非常相似,当pcap捕获的满足规则的数据包时,着两个函数将调用我们自己定义的回调函数执行我们自己的处理。 函数原型:
int pcap_loop(pcap_t *p, int cnt [1] [2] 下一页
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力 |