Windows下使用scapy+python2.7实现对pcap文件的读写操作

scapy在linux环境中对pcap文件进行操作非常方便,但在windows下,特别是在python2.7环境下却会碰到各种各样的依赖包无法使用的问题,最明显的可能就属dnet和pcap的python依赖包了,因为scapy的conf.use_pcap和conf.use_dnet在windows环境下无法进行配置,在scapyarchwindows\__init__.py中都被强行置为1了,也就是必须使用pcap和dnet依赖包。具体代码如下所示

from scapy.sendrecv import debug, srp1
from scapy.layers.l2 import Ether, ARP
from scapy.data import MTU, ETHER_BROADCAST, ETH_P_ARP

conf.use_pcap = 1
conf.use_dnet = 1
from scapy.arch import pcapdnet
from scapy.arch.pcapdnet import *

LOOPBACK_NAME="lo0"
WINDOWS = True

google了一遍,基本都是在Windos+python2.6的环境下使用scapy的,很少有使用Windows+python2.7的,几经周折,又cygwin又是MinGW的总算搞定dnet和pcap在Windows+python2.7的包。

具体下载地址为:

pcap http://files.cnblogs.com/Jerryshome/pcap-1.1.win32-py2.7.rar

dnet http://files.cnblogs.com/Jerryshome/dnet-1.12.win32-py2.7.rar

以下代码对如何使用scapy完成pcap的读写做了展示,同时为解决部分scapy解析出来的Packet无法序列化的问题提供一个PicklablePacket类,具体代码如下:

import scapy
from scapy.all import *

from scapy.utils import PcapReader, PcapWriter
import gzip,zlib,cPickle

class PicklablePacket:
    '''
    A container for scapy packets that can be pickled
    (in contrast to scapy pakcets themselves)
    '''
    def __init__(self, pkt):
        self.contents = str(pkt)
        self.time = pkt.time
    def __call__(self):
        '''
        Get the original scapy packet
        '''
        pkt = scapy.layers.l2.Ether(self.contents)
        pkt.time = self.time
        return pkt
    def dumps(self):
        '''use cpickle to dump'''
        return gzip.zlib.compress(cPickle.dumps(self)).encode('base64')
    @staticmethod
    def loads(string):
        '''
        load object from string
        ''' 
        p = cPickle.loads(gzip.zlib.decompress(string.decode('base64')))
        return p()


        

def read(file_name, start, count):
    '''
    read packets from pcap according to the start packet number and total count 
    '''
    reader = PcapReader(file_name)
    if start > 0:
        reader.read_all(start)
    if count > 0:
        return reader.read_all(count)
    else:
        return reader.read_all(-1)

def write(file_name, packets):
    writer = PcapWriter(file_name, append = True)
    for p in packets:
        writer.write(p)
    writer.flush()
    writer.close()

if __name__ == '__main__':
    packets = read('726445CD34B7273EBEA2973BBD6E784C.C39BC427.pcap', 0, 10)
    # packle the packets to transfer
    p = PicklablePacket(packets[0])
    s =  p.dumps()
    p = PicklablePacket.loads(s)
    print p
    print p.summary()
    
    serialized_packets = [PicklablePacket(p).dumps() for p in packets]
    deserialized_packets = [PicklablePacket.loads(s) for s in serialized_packets]
    write('new.pcap', packets)