用scapy解析不同层的数据,包括http

需求

用scapy解析每个层需要的数据
但是有一个问题是不支持http的,解决方法是安装scapy-http,具体效果请参考这里

实现完整代码:

#!/usr/bin/env python
try:
    import scapy.all as scapy
except ImportError:
    import scapy

try:
    # This import works from the project directory
    import scapy_http.http as http
except ImportError:
    # If you installed this package via pip, you just need to execute this
    from scapy.layers import http

import re


def processStr(data):
    pattern = re.compile('^b\'(.*?)\'$', re.S)
    res = re.findall(pattern, str(data))
    final = re.split('\\\\r\\\\n', res[0])
    return final

packets = scapy.sniff(iface='eth0', count=100)
for p in packets:
    if 'TCP' in p:
        print('=' * 78)
        Ether_name = p.name
        Ether_dst =  p.dst


        Ether_src = p.src
        IP_name = p.payload.name
       # IP_proto = p.payload.proto
        IP_src = p.payload.src
        IP_dst = p.payload.dst

        print(Ether_name)
        print('dst : ' + Ether_dst)
        print('src : ' + Ether_src)

        print(IP_name)
        # print('protcol : ' + IP_proto)
        print('src : ' + IP_src)
        print('dst : ' + IP_dst)
        if p.haslayer(http.HTTPRequest):
            print("*********request******")
            http_name = 'HTTP Request'
            http_header = p[http.HTTPRequest].fields
            headers = http_header['Headers']
            items = processStr(headers)
            for i in items:
                print(i)

        elif p.haslayer(http.HTTPResponse):
            print("*********response******")
            http_name = 'HTTP Response'
            http_header = p[http.HTTPResponse].fields
            headers = http_header['Headers']
            items = processStr(headers)
            for i in items:
                print(i)

            if 'Raw' in p:
                load = p['Raw'].load
                items = processStr(load)
                for i in items:
                    print(i)

具体实现

得到数据

有两种方式,实时抓包,读取 pcap文件
实时抓包:利用sniff方法来实现

from scapy.all import *
packets = sniff(iface=eth0, count=100)

eth0是我想检测的网卡,你需要根据你的情况来换

读取文件:利用这个库中的 rdpcap()方法来实现

import scapy.all as scapy
packets = scapy.rdpcap(你的文件路径)
解析制定数据

大致思路,可以采用

for p in packets:
    p.show()

来查看每个层的数据有那些属性可以取出,这里的p代表的是 ether层。
例如想要取出 ether层的dst属性 可以用p.dst

还有一个属性payload可以不断进下一个层
比如现在有四个层 Ether,IP,TCP,RAW
IP 可以表示为p.payload, 想要IP层的src可以用p.payload.src

但是这些表示方法只是在scapy库中,补充的那个库并虽然可以这样使用,
如果要取得http层的数据有些字段会不好取,像Agent-Encoding这个字段,就不好取,他会识别不出来,而且这么写代码太累。

具体怎么使用一开始我也有点难下手,后来看到了这篇博客,非常感谢
我这里是需要http层的request,response的所有headers的内容,如果response里面有返回的内容也要保存下来

  • 存在问题
    一开始我是想像这样上面那个博客一样,一个一个的取数据,但是这样有个问题,访问不同的网页有时候你定义的这个数据在这个返回内容里面可能是没有的,那它就没有这个定义的字段返回,那么你写的这个字段的值就会报错,说这个值不存在。
    所以这条路行不通,后来看到他其实有把所有的headers放到的内容放到headers这个属性里面,所以我想到那这个属性会随着这个内容的不同而改变,可以用正则得到这部分的数据,然后按格式解析出来就不会有我刚刚说的问题了。

取得headers的内容后调用正则解析得到一个包含有header所有内容的list
实现如下:

def processStr(data):
    pattern = re.compile('^b\'(.*?)\'$', re.S)
    res = re.findall(pattern, str(data))
    final = re.split('\\\\r\\\\n', res[0])
    return final
遗留问题 :

现在基本已经达到我的需求,但是还有一个问题,所有返回的内容如果里面包含汉字,是以16进行的编码进行显示的,最好可以显示成汉字,我现在能想到的解决方法是利用编码函数给转一下就应该能解决,但是还没具体实现,实现了来更新。

大家有什么问题欢迎交流呀~,欢迎指正

参考

https://github.com/invernizzi/scapy-http
https://www.cnblogs.com/14061216chen/p/8093441.html
https://blog.csdn.net/yuberhu/article/details/64123516
http://fivezh.github.io/2016/05/31/Python-http-packet-parsing/

  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值