Python2和Python3 DPKT似乎返回不同的输出格式

问题描述 投票:0回答:1

DPKT库说它现在支持Python3,但是当我在Python 2.x和3.x中使用它时,它具有不同的行为。虽然,两者都不正确,但会出现。

例如,在Python 2.x中,示例为here

with open('test.pcap') as f:
    pcap = dpkt.pcap.Reader(f)
    for ts, buf in pcap:
       eth = dpkt.ethernet.Ethernet(buf)
       print eth

返回一种我不期望的格式,类似于以下对象:

   ^����6#���l�m�
Q!6�(�����k����~�pO���o���N�l   �k4�'���8�9�j��@mf���5��pB�6bٌ�~p��Jf.Jܼ3H�:�ݭ�k-O7+�O��
4�(�9��^F�fb��V��t˜������\�X1��#�.�ج<�Q�!����>�^ɹDĀ�orC=bC���S�6;��SR�`�� �

ZD����j2Q���m����h��)1@��1���aw}�d�ڧn�                                          ��
0Z:�`8ຄE(�@4���}������Mu��63fP�/�
������h'7�h'7�;������

但是,在Python 3中,我被迫以'rb'模式打开pcap文件,这很好,除了输出问题(我不确定'rb'现在与问题无关) :

with open('test.pcap', 'rb') as f:
    pcap = dpkt.pcap.Reader(f)
    for ts, buf in pcap:
       eth = dpkt.ethernet.Ethernet(buf)
       print eth

现在返回我认为是字节串的内容,但是我还没有找到一种方法来从所需的数据中获取数据。例如,如果需要标记的数量,可以从其站点的上述示例中轻松获取17个标志,但似乎根本无法使它们的示例正常工作:

b'\x00\x0f\x1f\x16\xd1\xcd\x00\xc0\xf0y\x9a\xfd\x08\x00E\x00\x00\x1c\xb1\xce\x00\x006\x01N\xf7\xc0\xa8\x01d\xc0\xa8\x01g\x08\x00\xd9\xd7\xb7\xc4fc'

我没有运气将此字符串转换为人类可读的对象。我尝试过的decodebinascii或其他任何组合均无效。我使用这个库不正确吗?

python python-3.x python-2.x pcap dpkt
1个回答
0
投票

[python2和python3之间的主要区别之一是在python3中,strbytes不再相同。比较:

$ python2 -c 'print(b"foo" == "foo")'
True

$ python3 -c 'print(b"foo" == "foo")'
False

这说明了为什么必须在python3中使用"rb"打开文件。 (尽管如果您在某些使用python2的平台上不这样做,则很可能会得到虚假结果,因为如果没有b行结尾,文件中恰好存在的行尾可能会不适当地扩展。)

[另一个区别:在python3中,print是一个函数,而不是语句,因此,您上面在python3中显示的代码实际上是语法错误。相反,您需要print(eth)

回答您的实际问题:当您仅打印eth时,您隐式地要求eth对象使其自身可打印。这与调用print(str(eth))相同,因此它为您提供了包含以太网帧的二进制数据缓冲区的可打印字符串版本。

您需要使用dpkt的功能来发现,然后解剖您关心的镜框部分。

这是一个简短示例,它解码包含DNS数据包的pcap:

import dpkt
with open("/tmp/dns.pcap", "rb") as f:
    pcap = dpkt.pcap.Reader(f)
    for ts, buf in pcap:
        l2 = dpkt.ethernet.Ethernet(buf)
        print("Ethernet (L2) frame:", repr(l2))

        if l2.type not in (dpkt.ethernet.ETH_TYPE_IP, dpkt.ethernet.ETH_TYPE_IP6):
            print("Not an IP packet")
            continue
        l3 = l2.data
        print("IP packet:", repr(l3))

        if l3.p not in (dpkt.ip.IP_PROTO_TCP, dpkt.ip.IP_PROTO_UDP):
            print("Not TCP or UDP")
            continue

        l4 = l3.data
        print("Layer 4:", repr(l4))

        if l4.dport in (53, 5353) or l4.sport in (53, 5353):
            dns = l4.data
            if not isinstance(dns, dpkt.dns.DNS):
                dns = dpkt.dns.DNS(dns)
            print("DNS packet:", repr(dns))

关于您的输出为何与本教程看起来不同的原因。本教程已过时。显然,在某些时候,__str__对象上的dpkt魔术方法的实现发生了变化(当您只是print一个对象时,便会得到其__str__方法的结果)。

最初,__str__返回该对象的格式化表示。稍后,它仅返回对象原始字节的字符串表示形式。因此,现在您需要调用repr(obj)以获得格式化的表示形式。

© www.soinside.com 2019 - 2024. All rights reserved.