当前位置:  编程语言>python

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

 
    发布时间:2013-7-18  


    本文导语:  一提到Python获取数据包的方式,相信很多Python爱好者会利用Linux的libpcap软件包或利用Windows下的WinPcap可移植版的方式进行抓取数据包,然后再利用dpkt软件包进行协议分析,我们这里想换一个角度去思考: 1. Python版...

 一提到Python获取数据包的方式,相信很多Python爱好者会利用Linuxlibpcap软件包或利用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=/article/&/index.html % 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()


  • 本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载,整理或搜集自网络.欢迎任何形式的转载,转载请注明出处.
    转载请注明:文章转载自:[169IT-IT技术资讯]
    本文标题:如何利用libpcap和Python嗅探数据包
相关文章推荐:
  • 怎样利用JAVABEAN将JSP页面提交的数据保存到数据库,请给代码好吗?谢谢!
  • uboot中利用串口抓取工具得到的第一个数据为什么是0a 0d?
  • 如何利用Applet访问数据库?
  • 哪位有java通信方面的经验,谈谈如何利用java编写服务器程序来接受unix主机发送的数据信息?
  • 利用Java 技术,怎样把JSP页面中的表格数据导入到microsoft Excel中
  • mysql利用group_concat()合并多行数据到一行
  • JS、replace利用正则表达式替换SQL所有参数为指定格式的数据
  • 急急急!!利用jdbc-odbc bridge 连接远程数据库
  • 怎样利用html中的超链接来执行一个servlet或者提交该页面上的数据给一个JSP
  • html下利用javascript连数据库
  • 大家好,我有一586 32m内存的计算机希望能够利用,不必图形界面但需要通过局域网上Internet接收数据,能够安全稳定占用较少的资源。
  • 嵌入式中,利用C语言操作SQLite数据库,查询没有数据返回,请大家帮忙看看哈
  • 利用可更新ResultSet的updateBinaryStream()可以把图片存到mySql数据库,却不能存到Oracle数据库,怎么办?
  • 利用shell删除数据表中指定信息和字段对应的文件
  • WinPcap iis7站长之家
  • 巧妙利用PARTITION分组排名递增特性解决合并连续相同数据行
  • C#利用Openxml读取Excel数据实例
  • C#利用ODP.net连接Oracle数据库的操作方法
  • Oracle 低权限数据库账户得到 OS 访问权限 提权利用
  • c#利用Excel直接读取数据到DataGridView


  • 站内导航:


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

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

    浙ICP备11055608号-3