0

我是python的初学者,目前正在尝试在python 3中使用dpkt构建一个数据包捕获分析工具。我还没有做太多,我正在尝试慢慢构建它,一步一步,这样我才能真正理解我的问题并学习从他们。就目前而言,我的第一个任务就是能够读取、解析和关闭数据包捕获,将相关信息存储为合适的数据类型。我遇到的第一个问题是,我能够解析初始函数中的所有数据包信息,如注释掉的行(第 17 行)所示,但是当我尝试调用 main() 中的任何数据包信息时,我只得到流中的第一个数据包(第 36 行)。我认为解决方案是要么创建一个列表/字典来存储来自 parsepcap 函数的数据,要么将 pcap 文件的打开、解析和关闭移动到 main()。我' 我不知道如何从这里开始,所以任何帮助将不胜感激。第二个任务是将数据包信息汇总为数据包类型的数量(UDP、TCP、IGMP),打印每种类型的第一个和最后一个时间戳以及每种类型的平均数据包长度,但我还没有完成。再次感谢任何帮助。

import dpkt
import socket
import sys

#Open, Parse and Close a PCAP file
#Input = File
#Output = File Contents    
def parsepcap(pcap):
    with open(pcap,'rb') as pcap_in:
        contents = dpkt.pcap.Reader(pcap_in)       
        for ts, buf in contents:
            eth = dpkt.ethernet.Ethernet(buf)
            ip = eth.data
            tcp = ip.data
            dst_ip = socket.inet_ntoa(ip.dst)
            src_ip = socket.inet_ntoa(ip.src)
            #print(f'Source: {src_ip} -> Destination: {dst_ip}')
        return eth, ip, tcp, dst_ip, src_ip

def main():
    #Test Arguments
    sys.argv.append('packets1.pcap')
    #sys.argv.append('packets2.pcap')
    #sys.argv.append('evidence-packet-analysis.pcap')

    #Checks if there are two arguments being passed to sys.argv. If not, then explains usage.
    if len(sys.argv) != 2:
        print('[Error] Usage: py pcap_cw.py [pcapfile.pcap]')
        return
    
    in_location = sys.argv[1] #string we are getting data from - URL or path
    
    try:            
        print('[+] Analysing %s' % sys.argv[1])
        text = ""
        text = parsepcap(in_location)
        print(text)
    
    except FileNotFoundError as err1:
        print(f' File "{in_location}" does not exist. Please choose another file.')
    except Exception as err2:
        print(f'Oh No! - {err2}')
    

if __name__ == '__main__':
    main()

https://github.com/Sly-Lamp/pcap

4

1 回答 1

1

您正在循环内设置返回变量。这意味着它们在每次循环迭代时都会被覆盖,这导致您只收到最后一个值。

一个简单的解决方案是将您的方法转换为generatorhttps://docs.python.org/3/glossary.html#term-generator),它会在迭代时返回每个值,然后在外部函数上对其进行迭代。


def parsepcap(pcap):
    with open(pcap,'rb') as pcap_in:
        contents = dpkt.pcap.Reader(pcap_in)
        for ts, buf in contents:
            eth = dpkt.ethernet.Ethernet(buf)
            ip = eth.data
            tcp = ip.data
            dst_ip = socket.inet_ntoa(ip.dst)
            src_ip = socket.inet_ntoa(ip.src)
            yield eth, ip, tcp, dst_ip, src_ip

并且在设置文本时:

'\n'.join(parsepcap(pcap))

一个完整的例子(有一些变化)是:


import dpkt
import socket
import sys


def parsepcap(pcap):
    with open(pcap, 'rb') as pcap_in:
        for _, buf in dpkt.pcap.Reader(pcap_in):
            eth = dpkt.ethernet.Ethernet(buf)
            ip = eth.data
            tcp = ip.data
            dst_ip = socket.inet_ntoa(ip.dst)
            src_ip = socket.inet_ntoa(ip.src)
            yield eth, ip, tcp, dst_ip, src_ip


def main(pcap_path):
    try:
        print(f'[x] Parsing: {pcap_path}')
        for packet in parsepcap(pcap_path):
            print(f'\t{packet[4]} -> {packet[3]}')
    except FileNotFoundError:
        print(f' File "{pcap_path}" does not exist.')
    except Exception as err2:
        print(f'Oh No! - {err2}')


if __name__ == '__main__':
    if len(sys.argv) != 2:
        print('[Error] Usage: py pcap_cw.py [pcapfile.pcap]')
        sys.exit(1)
    main(sys.argv[1])

结果(我冒昧地只打印了最“可打印”的部分,即源 IP 和目标 IP):


python3 test_3.py foo.pcap
[x] Parsing: foo.pcap
    192.168.0.130 -> 255.255.255.255

于 2020-11-25T21:08:02.050 回答