python 网络数据包处理和嗅探工具Scapy 学习笔记(一)

Scapy 学习笔记(一)

本文主要是关于scapy的安装和scapy存在的内存泄露导致内存爆掉的解决方案,关于如何操纵数据包请看另一篇博客:

https://blog.csdn.net/meanong/article/details/53942671

  • Scapy 学习笔记(一)
    • scapy在windows中安装教程
  • 关于rdpcap方法中的内存泄露问题
    • 解决方法

scapy在windows中安装教程

关于scapy在Linux中安装教程网上很多,但是在windows下的安装就显得有点少了。查了很多资料终于安装完毕,现在将scapy的在windows下的安装教程备份一下。
  • 1.scapy在windows下安装时,在官网上只找到了支持python 2.x的,关于python 3.x系列的合适支持就不晓得了。首先下载scapy安装包。我使用的安装包链接为http://download.csdn.net/detail/meanong/9725487:
  • 2.将压缩文件解压,然后安装一级目录中对应的环境。
  • 3.将scapy-latest解压之后,打开命令行,切换到对应的文件中setup.py所在路径。
  • 4.运行命令python setup.py install即可完成安装。
  • 5.测试方法:
    • 打开命令行,输入Python进入Python解释器
    • 输入import scapy.all as scapy
      得到如下结果那么恭喜安装成功
      python 网络数据包处理和嗅探工具Scapy 学习笔记(一)_第1张图片

关于rdpcap方法中的内存泄露问题

博主在使用scapy库的时候主要用这个库来对已经捕获好的pcap文件进行分析,提取特征。所以rdpcap方法是接触最早最多的方法了。但是在使用的时候电脑的内存总是无缘无故炸掉,经过一番搜索发现了rdpcap方法中存在的内存泄露问题。(该问题详细描述以及解决方法转自http://www.qixing318.com/article/202227606.html)
rdpcap方法的实现代码如下

    def rdpcap(filename, count=-1):
        """Read a pcap file and return a packet list
        count: read only  packets"""
        return PcapReader(filename).read_all(count=count)

那我们继续找PcapReader这个类。同样在这个文件中。继承自同在这个文件中定义的RawPcapReader类。但我此时更关心的是这个read_all是如何定义的……

def read_all(self,count=-1):
    res = RawPcapReader.read_all(self, count)
    import plist
    return plist.PacketList(res,name=os.path.basename(self.filename))

很显然,读取文件内容这部分的主体功能还是来自于他的父类RawPcapReader中的read_all函数,而父类函数定义如下:

def read_all(self,count=-1):
    """return a list of all packets in the pcap file
    """
    res=[]
    while count != 0:
        count -= 1
        p = self.read_packet()
        if p is None:
            break
        res.append(p)
    return res

rdpcap其实就是一行代码——return. 在return时,实例化了PcapReader类,并调用了其read_all函数。不难想到——既然rdpcap的作用是读取一个pcap文件的内容,那一定会有open操作。我们必然要问一句:既然open了,那么你是在哪close的呢?
刚才说了,PcapReader类是继承自RawPcapReader类。我们直接看下RawPcapReader类中的两个关键函数就好了——初始化函数和关闭函数:

def __init__(self, filename):
    self.filename = filename
    try:
        self.f = gzip.open(filename,"rb")
        magic = self.f.read(4)
    except IOError:
        self.f = open(filename,"rb")
        magic = self.f.read(4)
    if magic == "\xa1\xb2\xc3\xd4": #big endian
        self.endian = ">"
    elif  magic == "\xd4\xc3\xb2\xa1": #little endian
        self.endian = "<"
    else:
        raise Scapy_Exception("Not a pcap capture file (bad magic)")
    hdr = self.f.read(20)
    if len(hdr)<20:
        raise Scapy_Exception("Invalid pcap file (too short)")
    vermaj,vermin,tz,sig,snaplen,linktype = struct.unpack(self.endian+"HHIIII",hdr)

    self.linktype = linktype

def close(self):
    return self.f.close()

可见,一旦实例化这个类,初始化函数就会自动的将用户指定的pcap文件打开,但用完之后,必须用户手动close掉才可以。而rdpcap这个函数只实例化了PcapReader这个类,却没有close掉,也没有将实例化的对象传递出来,用户也无法close掉……结果就是——谁都没有关闭这个对象。导致内存泄漏

解决方法

修改rdpcap函数,修改方法如下:

def rdpcap(filename, count=-1):
    """Read a pcap file and return a packet list
count: read only  packets"""
    pcap = PcapReader(filename)
    data = pcap.read_all(count=count)
    pcap.close() 
    return data

你可能感兴趣的:(数据包解析)