在scapy中解码hex pcap数据包

时间:2017-06-23 10:07:41

标签: python scapy

有一个pcap十六进制数据包,格式如下:

0000   D4 C3 B2 A1 02 00 04 00  00 00 00 00 00 00 00 00   ................
0010   FF FF 00 00 01 00 00 00  5F D0 4C 59 57 D6 0E 00   ........_.LYW...
0020   84 00 00 00 84 00 00 00  00 00 C2 85 C1 03 00 00   ................
0030   00 00 00 02 81 00 00 0A  08 00 45 00 00 6E E4 C4   ..........E..n..
0040   00 00 FF 06 C7 AF 01 02  03 04 0A 01 01 0F 00 10   ................
0050   00 0A 00 01 E2 40 00 03  94 47 50 10 10 00 D2 F8   .....@...GP.....
0060   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
0070   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
0080   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
0090   00 00 00 00 3B C5 9A 8F  38 A4 2B 76 7D 39 7A 68   ....;...8.+v}9zh
00a0   8A 59 F6 A4 CC 32 C7 97  B1 86 F6 50               .Y...2.....P

从0x0025开始的字节00 00 C2 85 C1 03是我的真实数据包,pcap数据包有一个0x25 = 37字节的标头,我想知道如何在python中的scapy中解码这个数据包。在以下代码中直接解码它并不起作用:

load_packet = Ether(raw_packet)
print load_packet.src, load_packet.dst
print load_packet.getlayer(IP).src, load_packet.getlayer(IP).dst
print load_packet.getlayer(TCP).sport, load_packet.getlayer().dport

其中raw_packet是上面的数据包字符串。

1 个答案:

答案 0 :(得分:0)

这段代码有点难看(说实话很多),但它有效。
只需将hexdump放在名为stack_overflow的文件中,然后运行下面的脚本 我已经使用python3.5测试了它,

from scapy.all import *
import sys

def fix_packet(in_file, out_file, offset_to_start):
    '''
    Create a new hexdump text file without the bytes that need to be skipped

    in_file: hexdump file to read from
    out_file: hexdump file to write to
    offset_to_start: how many bytes (in decimal) to skip until the strat of the actual packet
    '''
    hex_data_to_store = []
    ascii_data_to_store = []

    for line in open(in_file, 'r').readlines():
        ascii_data = line.strip().split('   ')[len(line.split('   ')) - 1]
        hex_data = line.strip().split('   ')[1].split('   ')[0].replace(' ', '')

        if not offset_to_start:
            hex_data_to_store.append(hex_data)
            ascii_data_to_store.append(ascii_data)
        else:
            if offset_to_start - len(ascii_data) >= 0:
                offset_to_start -= len(ascii_data)
            else:
                hex_data_to_store.append(hex_data[32 - ((len(ascii_data) - offset_to_start) * 2)::])
                ascii_data_to_store.append(ascii_data[16 - (len(ascii_data) - offset_to_start)::])
                offset_to_start = 0

    hex_data_to_store = ''.join(hex_data_to_store)
    ascii_data_to_store = ''.join(ascii_data_to_store)

    with open(out_file, 'w') as f:
        index = 0
        while True:
            if len(ascii_data_to_store) >= 16:
                f.write('{:04x} {} {}\n'.format(index, ' '.join('{}{}'.format(a,b) for a,b in zip(hex_data_to_store[:32:2],
                  hex_data_to_store[1:32:2])),
                  ascii_data_to_store[:16]))
                hex_data_to_store = hex_data_to_store[32::]
                ascii_data_to_store = ascii_data_to_store[16::]
            else:
                f.write('{:04x} {} {}{}\n'.format(index,
                  ' '.join('{}{}'.format(a,b) for a,b in zip(hex_data_to_store[::2], hex_data_to_store[1::2])),
                  '   '*(16 - len(ascii_data_to_store)), ascii_data_to_store[:]))
                break
            index += 16

def write_data(data):
    '''
    This is a trick because import_hexcap reads the hexdump from the stding
    '''
    with open('new_file', 'w') as f:
        f.write(data)
        f.write(chr(4))

def read_hex():
    old_stdin = sys.stdin
    sys.stdin = open('new_file', 'r')
    pkt=Ether(import_hexcap())
    sys.stdin = old_stdin
    return pkt

fix_packet(in_file='stack_overflow', out_file='new_hex', offset_to_start=40)
hex_str = [x.strip() for x in open('new_hex', 'r').readlines()]
write_data('\n'.join(hex_str))
load_packet=read_hex()
print(load_packet.src, load_packet.dst)
print(load_packet.getlayer(IP).src, load_packet.getlayer(IP).dst)
print(load_packet.getlayer(TCP).sport, load_packet.getlayer(TCP).dport)

我得到了以下输出:

>>> print(load_packet.src, load_packet.dst)
00:00:00:00:00:02 00:00:c2:85:c1:03

>>> print(load_packet.getlayer(IP).src, load_packet.getlayer(IP).dst)
1.2.3.4 10.1.1.15

>>> print(load_packet.getlayer(TCP).sport, load_packet.getlayer(TCP).dport)
16 10