【问题标题】:How do I parse a captured packet in python?如何在 python 中解析捕获的数据包?
【发布时间】:2013-12-31 14:38:37
【问题描述】:

我有一个使用 python 的套接字捕获数据包原始数据包:

s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))

while True:
    message = s.recv(4096)
    test = []
    print(len(message))
    print(repr(message))

我假设返回的数据包是十六进制字符串格式,但是print(repr(message)) 的打印输出让我得到这样的信息:

b'\x00\x1b\xac\x00Gd\x00\x14\xd1+\x1f\x19\x05\n\x124VxC!UUUU\x00\x00\x00\x00\xcd\xcc\xcc=\xcd\xccL>\x9a\x99\x99>\xcd\xcc\xcc>\x00\x00\x00?\x9a\x......'

其中包含奇怪的非十六进制字符,例如 !UUUU=。这是什么编码,如何解码数据包?


我现在提前知道数据包的样子,因为我是使用winpcapy 生成数据包的人:

from ctypes import *
from winpcapy import *
import zlib
import binascii
import time


from ChanPackets import base, FrMessage, FrTodSync, FrChanConfig, FlChan, RlChan


while (1):

    now = time.time()

    errbuf = create_string_buffer(PCAP_ERRBUF_SIZE)
    fp = pcap_t
    deviceName = b'\\Device\\NPF_{8F5BD2E9-253F-4659-8256-B3BCD882AFBC}'
    fp = pcap_open_live(deviceName, 65536, 1, 1000, errbuf)

    if not bool(fp):
        print ("\nUnable to open the adapter.  %s is not supported by WinPcap\n" % deviceName)
        sys.exit(2)

    # FrMessage is a custom class that creates the packet
    test = FrMessage('00:1b:ac:00:47:64', '00:14:d1:2b:1f:19', 0x12345678, 0x4321, 0x55555555, list(i/10 for i in range(320)))

    # test.get_Raw_Packet() returns a c_bytes array needed for winpcap to send the packet
    if (pcap_sendpacket(fp, test.get_Raw_Packet(), test.packet_size) != 0):
        print ("\nError sending the packet: %s\n" % pcap_geterr(fp))
        sys.exit(3)


    elapsed = time.time() - now
    if elapsed < 0.02 and elapsed > 0:
        time.sleep(0.02 - elapsed)

    pcap_close(fp)

注意:我想得到一个代表每个字节的十六进制值数组

【问题讨论】:

    标签: sockets python-3.x raw-sockets


    【解决方案1】:

    这是什么编码,如何解码数据包?

    您看到的是bytes 对象在 Python 中的表示。正如您可能已经猜到的那样,\xab 代表字节 0xab (171)。

    其中包含奇怪的非十六进制字符,例如 !UUUU=

    可打印的 ASCII 字符表示它们自己,即表示只包含 U 而不是 \x55

    你拥有的是一个字节序列。如何解码它们取决于您的应用程序。例如,要解码包含以太网帧的数据包,您可以使用scapy (Python 2):

    >>> b = '\x00\x02\x157\xa2D\x00\xae\xf3R\xaa\xd1\x08\x00E\x00\x00C\x00\x01\x00\x00@\x06x<\xc0\xa8\x05\x15B#\xfa\x97\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\xbb9\x00\x00GET /index.html HTTP/1.0 \n\n'
    >>> c = Ether(b)
    >>> c.hide_defaults()
    >>> c
    <Ether  dst=00:02:15:37:a2:44 src=00:ae:f3:52:aa:d1 type=0x800 |
    <IP  ihl=5L len=67 frag=0 proto=tcp chksum=0x783c src=192.168.5.21 dst=66.35.250.151 |
    <TCP  dataofs=5L chksum=0xbb39 options=[] |
    <Raw  load='GET /index.html HTTP/1.0 \n\n' |>>>>
    

    我想得到一个代表每个字节的十六进制值数组

    你可以使用binascii.hexlify():

    >>> pkt = b'\x00\x1b\xac\x00Gd\x00'
    >>> import binascii
    >>> binascii.hexlify(pkt)
    b'001bac00476400'
    

    或者如果你想要一个包含字符串十六进制值的列表:

    >>> hexvalue = binascii.hexlify(pkt).decode()
    >>> [hexvalue[i:i+2] for i in range(0, len(hexvalue), 2)]
    ['00', '1b', 'ac', '00', '47', '64', '00']
    

    【讨论】:

    • 最终我想要的只是我正在生成的原始数据包的十六进制转储(请参阅更新答案)。如果可能的话,我更愿意这样做是库存 python 库。
    • @KronoS:我已经更新了答案以显示如何获取十六进制值
    【解决方案2】:

    在 python 中,可以使用 scapy 函数(如 IP()TCP()UDP() 等)完成原始数据包解码。

    import sys
    import socket
    from scapy.all import *
    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
    while 1:
        packet = s.recvfrom(2000);
        packet = packet[0]
        ip = IP(packet)
        ip.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-08
      • 1970-01-01
      • 2014-01-13
      • 1970-01-01
      • 2011-06-24
      • 2012-03-25
      • 2014-03-18
      • 1970-01-01
      相关资源
      最近更新 更多