求libpcap抓包c语言程序,能把数据包内容显示出来的

2024-05-11 13:43

1. 求libpcap抓包c语言程序,能把数据包内容显示出来的

/*
* printPkt()函数是打印经过指定网卡的和指定类型的数据包;
 *  参数device:指定要监听的网卡数据名称;
 *  参数pname:指定打印时的content名称;
 *  参数flag:是否为混杂模式,1为混杂模式,0为非混杂模式;
 *  参数flt:是否打开过滤,1为打开过滤,0为关闭过滤;
 *  参数filterStr:过滤字符串.
 *  返回结果:0为正常,-1为失败.
 */
#include "headFile.h"
void PcallBack(unsigned char *argument,
      const struct pcap_pkthdr* pcap_header,
      const unsigned char *packet_content);
int printPkt(char *device,unsigned char *pname,int flag,int flt,char *filterStr){
 char *ebuf;
 pcap_t *t;
 bpf_u_int32 net;       // 所在IP地址
 bpf_u_int32 mask;       // 所在网络的掩码
 pcap_lookupnet(device, &net, &mask, ebuf);   //获取指定设备的信息
 long int to_ms = 0;
 t = pcap_open_live(device,snaplen,flag,to_ms,ebuf);
 if(NULL == t){
  printf ("pcap_open_live is error:%s\n",ebuf);
  return -1;
 }
 if(1==flt){                       /*打开过滤开关*/
  struct bpf_program filter;
  if (-1==pcap_compile(t, &filter, filterStr, 0, net)){
   printf ("pcap_compile is error\n");
   return -1;
  }
  if (-1==pcap_setfilter(t, &filter)){
   printf ("pcap_setfilter is error\n");
   return -1;
  }
 }
 if (-1==pcap_loop(t,-1,PcallBack,pname)){
  ebuf = pcap_geterr(t);
  printf ("pcap_loop is error:%s\n",ebuf);
  return -1;
 }
 pcap_close(t);
 return 0;
}
void PcallBack(unsigned char *argument,
      const struct pcap_pkthdr* pcap_header,
      const unsigned char *packet_content) {
 int i=0;
 printf ("packet_len=%d",pcap_header->len);
 for (i=0;ilen;i++){
  if (i%10==0)
    printf("\n%s:   ",argument);
  if((int)packet_content[i]<16)
    printf ("0%x  ",packet_content[i]);
  else
    printf ("%x  ",packet_content[i]);
  }
 printf ("\n\n");
}

求libpcap抓包c语言程序,能把数据包内容显示出来的

2. pcap_t是什么类型的意思

libpcap函数库中pcap_t及pcap_dumper_t类型的数据结构

3. 如何利用libpcap和Python嗅探数据包

一提到Python获取数据包的方式,相信很多Python爱好者会利用Linux的libpcap软件包或利用Windows下的WinPcap可移植版的方式进行抓取数据包,然后再利用dpkt软件包进行协议分析,我们这里想换一个角度去思考:
   1. Python版本的pcap存储内存数据过小,也就是说缓存不够,在高并发下容易发生丢包现象,其实C版本的也同样存在这样的问题,只不过Python版本的缓存实在是过低,让人很郁闷。
   2. dpkt协议分析并非必须,如果你对RFC 791和RFC 793等协议熟悉的话,完全可以使用struct.unpack的方式进行分析。
   如果你平常习惯使用tcpdump抓取数据包的话,完全可以使用它来代替pcap软件包,只不过我们需要利用tcpdump将抓取的数据以pcap格式进行保存,说道这里大家一定会想到Wireshark工具,具体命令如下:
  tcpdump dst 10.13.202.116 and tcp dst port 80 -s 0 -i eth1 -w ../pcap/tcpdump.pcap -C 1k -W 5
我们首先需要对pcap文件格式有所了解,具体信息大家可以参考其他资料文档,我这里只说其重要的结构体组成,如下:
sturct pcap_file_header
 {
     DWORD   magic;
     WORD    version_major;
     WORD    version_minor;
     DWORD   thiszone;
    DWORD   sigfigs;
     DWORD   snaplen;
     DWORD   linktype;
 }
 struct pcap_pkthdr
 {
     struct timeval  ts;
     DWORD           caplen;
     DWORD           len;
 }
 struct timeval
 {
     DWORD   GMTtime;
     DWORD   microTime;
 }
这里需要说明的一点是,因为在Python的世界里一切都是对象,所以往往Python在处理数据包的时候感觉让人比较麻烦。Python提供了几个libpcapbind,http://monkey.org/~dugsong/pypcap/这里有 一个最简单的。在windows平台上,你需要先安装winpcap,如果你已经安装了Ethereal非常好用。一个规范的抓包过程:
import pcap
import dpkt
pc=pcap.pcap()    #注,参数可为网卡名,如eth0
pc.setfilter('tcp port 80')    #设置监听过滤器
for ptime,pdata in pc:    #ptime为收到时间,pdata为收到数据
    print ptime,pdata    #...
对抓到的以太网V2数据包(raw packet)进行解包:
p=dpkt.ethernet.Ethernet(pdata)
if p.data.__class__.__name__=='IP':
    ip='%d.%d.%d.%d'%tuple(map(ord,list(p.data.dst)))
    if p.data.data.__class__.__name__=='TCP':
        if data.dport==80:
            print p.data.data.data
一些显示参数nrecv,ndrop,nifdrop=pc.stats()返回的元组中,第一个参数为接收到的数据包,第二个参数为被核心丢弃的数据包。
  至于对于如何监控tcpdump生成的pcap文件数据,大家可以通过pyinotify软件包来实现,如下:
class Packer(pyinotify.ProcessEvent):
     def __init__(self, product):
         self.product = product
         self.process = None
     def process_IN_CREATE(self, event):
         logger.debug("create file: %s in queue" % self.process_IF_START_THREAD(event))
     def process_IN_MODIFY(self, event):
         self.process_IF_START_THREAD(event)
         logger.debug("modify file: %s in queue" % self.process_IF_START_THREAD(event))
     def process_IN_DELETE(self, event):
         filename = os.path.join(event.path, event.name)
         logger.debug("delete file: %s" % filename)
     def process_IF_START_THREAD(self, event):
         filename = os.path.join(event.path, event.name)
         if filename != self.process:
             self.process = filename
            self.product.put(filename)
             if self.product.qsize() > 1:
                 try:
                    logger.debug("create consumer product.qsize: %s" % self.product.qsize())
                     consumer = Consumer(self.product)
                     consumer.start()
                 except Exception, errmsg:
                     logger.error("create consumer failed: %s" % errmsg)
         return filename
 class Factory(object):
     def __init__(self, product):
         self.product = product
         self.manager = pyinotify.WatchManager()
         self.mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY
    def work(self):
         try:
             try:
                 notifier = pyinotify.ThreadedNotifier(self.manager, Packer(self.product))
                 notifier.start()
                 self.manager.add_watch("../pcap", self.mask, rec = True)
                 notifier.join()
             except Exception, errmsg:
                 logger.error("create notifier failed: %s" % errmsg)
         except KeyboardInterrupt, errmsg:
             logger.error("factory has been terminated: %s" % errmsg)
在获得要分析的pcap文件数据之后,就要对其分析了,只要你足够了解pcap文件格式就可以了,对于我们来讲只需要获得TCP数据段的数据即可,如下:
class Writer(threading.Thread):
    def __init__(self, product, stack):
        threading.Thread.__init__(self)
        self.product = product
        self.stack = stack
        self.pcap_pkthdr = {}
    def run(self):
        while True:
            filename = self.product.get()
            try:
                f = open(filename, "rb")
                readlines = f.read()
                f.close()
                offset = 24
                while len(readlines) > offset:
                    self.pcap_pkthdr["len"] = readlines[offset+12:offset+16]
                    try:
                        length = struct.unpack("I", self.pcap_pkthdr["len"])[0]
                        self.stack.put(readlines[offset+16:offset+16+length])
                        offset += length + 16
                    except Exception, errmsg:
                        logger.error("unpack pcap_pkthdr failed: %s" % errmsg)
            except IOError, errmsg:
                logger.error("open file failed: %s" % errmsg)
 在获得TCP数据段的数据包之后,问题就简单多了,根据大家的具体需求就可以进行相应的分析了,我这里是想分析其HTTP协议数据,同样也借助了dpkt软件包进行分析,如下:
def worker(memcache, packet, local_address, remote_address):
     try:
         p = dpkt.ethernet.Ethernet(packet)
         if p.data.__class__.__name__ == "IP":
             srcip = "%d.%d.%d.%d" % tuple(map(ord, list(p.data.src)))
             dstip = "%d.%d.%d.%d" % tuple(map(ord, list(p.data.dst)))
             if p.data.data.__class__.__name__ == "TCP":
                 tcpacket = p.data.data
                 if tcpacket.dport == 80 and dstip == local_address:
                     srcport = tcpacket.sport
                     key = srcip + ":" + str(srcport)
                     if tcpacket.data:
                         if not memcache.has_key(key):
                             memcache[key] = {}
                         if not memcache[key].has_key("response"):
                             memcache[key]["response"] = None
                         if memcache[key].has_key("data"):
                             memcache[key]["data"] += tcpacket.data
                         else:
                             memcache[key]["data"] = tcpacket.data
                     else:
                         if memcache.has_key(key):
                             memcache[key]["response"] = dpkt.http.Request(memcache[key]["data"])
                             try:
                                 stackless.tasklet(connection)(memcache[key]["response"], local_address, remote_address)
                                 stackless.run()
                             except Exception, errmsg:
                                 logger.error("connect remote remote_address failed: %s", errmsg)
                             logger.debug("old headers(none content-length): %s", memcache[key]["response"])
                             memcache.pop(key)
     except Exception, errmsg:
         logger.error("dpkt.ethernet.Ethernet failed in worker: %s", errmsg)
如果大家只是想单纯的获取IP地址、端口、流量信息,那么问题就更简单了,这里只是抛砖引玉。另外再提供一段代码供参考:
import pcap, dpkt, struct
import binascii
def main():
    a = pcap.pcap()
    a.setfilter('udp portrange 4000-4050')
    try:
        for i,pdata in a:
            p=dpkt.ethernet.Ethernet(pdata)
            src='%d.%d.%d.%d' % tuple(map(ord,list(p.data.src)))
            dst='%d.%d.%d.%d' % tuple(map(ord,list(p.data.dst)))
            sport = p.data.data.sport
            dport = p.data.data.dport
            qq = int( binascii.hexlify(p.data.data.data[7:11]) , 16 )
            print 'QQ: %d, From: %s:%d , To: %s:%d' % (qq,src,sport,dst,dport)
    except Exception,e:
        print '%s' % e
    n = raw_input()
if __name__ == '__main__':
    main()

如何利用libpcap和Python嗅探数据包

4. 求助,求助,交叉编译libpcap

1、解压libpcap-0.9.8.tar.gz,进入目录,修改confiugre文件,把下面两段注释掉 
#if test -z "$with_pcap" && test "$cross_compiling" = yes; then 
# { { echo "$as_me:$LINENO: error: pcap type not determined when cross-compiling; use --with-pcap=..." >&5 
#echo "$as_me: error: pcap type not determined when cross-compiling; use --with-pcap=..." >&2;} 
#   { (exit 1); exit 1; }; } 
#fi 
....... 
# if test $ac_cv_linux_vers = unknown ; then 
#   { { echo "$as_me:$LINENO: error: cannot determine linux version when cross-compiling" >&5 
#echo "$as_me: error: cannot determine linux version when cross-compiling" >&2;} 
#   { (exit 1); exit 1; }; } 
# fi
 
2、./configure --host=arm-9tdmi-linux-gnu生成Makefile
3、修改Makefile中prefix=$CROSS_COMPILE_PWD
4、接下来make,make install,完成了libpcap的编译和安装
5、接着就可以编写你的抓包程序了。记得在用arm-9tdmi-linux-gnu-gcc编译时加上“-lpcap”选项。
 
注意:第一次编译的时候不知道哪一步出了问题,最后编译程序的时候总是提示出错:undefined reference to `pcap_parse',最后将arm-linux-gcc和libpcap全部重新装了一次就好了。现在可以在YC2440开发板上抓包了,呵呵,算是达到第一个小目标吧。只是utu-linux上的中文显示为乱码的问题还没有解决,再接再厉吧!

5. Ethereal这个指的什么啊,有什么功能呢

www.ethereal.com

libpcap入门 
Kxing 发表于 2006-3-3 10:24:00 



一

libpcap是一个C语言库,其功能是通过网卡抓取网络以太网中的数据包,在windows系统下有相应的winpcap库。

要想使用这个库自然先要知道它在哪里,怎么安装就不废话了。在/usr/local/lib下有libpcap.a和libpcao.so,在/usr/local/include下有pcap.h,打开手册的命令是man pcap,而不是man libpcap,如果觉得在字符模式下查看man太麻烦也可以baidu或者google一下"man pcap"会又可读性更高的手册。要写一个使用libpcap的程序只需要在代码中加上#i nclude ,然后在编译时使用-lpcap选项就可以了,例如:

$>gcc -o test1 test1.c -lpcap

二

如果能正确的编译通过使用libpcap的代码,那么便可以进入第二步了,写一个最简单的抓包程序。

先来介绍第一个类型:pcap_t。要抓包就要首先生成一个抓包的描述符(或称句柄),后来的很多操作都需要用这个描述符做参数。pcap_t就是由pcap.h定义的抓包描述符的类型,函数pcap_open_live返回指向该类型的指针:

pcap_t *pd = pcap_open_live ("eth0", 68, 0, 1000, ebuf);

其中第一个参数表示用来抓包的设备;第二个参数定义了抓包的最大字节数,如果这个值小于包的大小(如定义为68,包大于68),那么则只抓这个包的前68个字节;第三个参数把网卡设置为混杂模式,以便抓取以太网中的数据包;第四个参数是一个以毫秒为单位的读取超时时间,如果设置为0则超时时间为无限大;第五个参数为出错信息,需要这样声明(第一个简单的程序不需要出错处理,只知道这样声明就够了):

char ebuf[PCAP_ERRBUF_SIZE];

好了,现在生成了一个描述符了,现在我们可以用它来做一点什么事情了。开始一个抓包的循环,然后关闭抓包过程(释放描述符):

pcap_loop (pd, 7, printer, NULL);

pcap_close (pd);

这里的pd就是我们刚刚生成的描述符;pcap_loop的第二个参数表示抓多少个包,设置为-1表示不定义数量,抓取所有的包;第三个参数是一个回调函数,每当抓到一个数据包之后程序将自动调用这个函数;第四个参数是一个指针,可以为空,将在下面详细讲解。

下面我们来详细的实现这个回调函数,使其每抓到一个包则打印一次:

void printer()
{
printf("A packet iscaptured!");
printf(" \n");
return;
}

当程序成功编译以后执行,则每抓到一个包后输出一行"A packet iscaptured!",输出7行以后退出程序。

这样,一个最简单的抓包程序诞生了!


参考源码:


/**
libpcap test program

compile command:"$>gcc -o exe_file_name this_file_name -lpcap"

written by Kxing 
Last Modified 2006-03-02
*/


#i nclude 
#i nclude 

int main (int argc, char* argv[])
{
/*the printer running when packet have captured*/
void printer()
{
printf("A packet is captured!");
printf(" \n");
return;
}


/*the error code buf of libpcap*/
char ebuf[PCAP_ERRBUF_SIZE];
/*create capture handler of libpcap*/
pcap_t *pd = pcap_open_live ("eth0", 68, 0, 1000, ebuf);


/*start the loop of capture, loop 7 times, enter printer when capted*/
pcap_loop (pd, 7, printer, NULL);

pcap_close (pd);

return 0;
}

Ethereal这个指的什么啊,有什么功能呢

6. libpcap中pcap_dump对捕获的数据包进行数据存储。怎样只存储数据包的包头的信息?

libpcap中pcap_dump