正则表达式/ Python3-re.findall()-查找操作码之间的所有匹配项

时间:2018-09-06 07:05:47

标签: regex python-3.x tlv

背景

我正在对使用Type-Length-Value方法编码数据的TCP流进行反向工程。

示例:

foundation-contentloaded

但是数据是一个数据对象,可以包含具有可变数据长度的多个变量。

TCP Payload: b'0000001f001270622e416374696f6e4e6f74696679425243080310840718880e20901c'
---------------------------------------------------------------------------------------
Type:     00 00   # New function call
Length:   00 1f   # Length of Value (Length of Function + Function + Data)
Value:    00 12   # Length of Function
Value:    70 62 2e 41 63 74 69 6f 6e 4e 6f 74 69 66 79 42 52 43   # Function ->(hex2ascii)-> pb.ActionNotifyBRC
Value:    08 03 10 84 07 18 88 0e 20 90 1c   # Data    

当前,我正在使用以下Python3代码解析数据:

Data: 08 05 10 04 10 64 18 c8 01 20 ef 0f
----------------------------------------------
Opcode : Value
  08   :  05          # var1 : 1 byte
  10   :  04          # var2 : 1 byte
  18   :  c8 01       # var3 : 1-10 bytes
  20   :  ef 0f       # var4 : 1-10 bytes

到目前为止一切都很好...

问题

如果操作码出现在先前的变量Value中,则该代码不再可靠。

############################### NOTES ###############################
# Opcodes sometimes rotate starting positions but the general order is always held:
#     Data:     20 ef 0f 08 05 10 04 10 64 18 c8 01
#####################################################################

import re
import binascii

def dataVariable(data, start, end):
    p = re.compile(start + b'(.*?)' + end)
    return p.findall(data + data)

data = bytearray.fromhex('08051004106418c80120ef0f')
var3 = dataVariable(data, b'\x18', b'\x20')
print("Variable 3:", end=' ')
for item in set(var3):
    print(binascii.hexlify(item), end=' ')

----------------------------------------------------------------------------
[Output]: Variable 3: b'c801'

我期望输出:

Data: 08 05 10 04 10 64 18 c8 20 01 20 ef 0f
----------------------------------------------
Opcode : Value
  08   :  05          
  10   :  04          
  18   :  c8 20 01        # The Value includes the next opcode (20)  
  20   :  ef 0f
----------------------------------------------------------------------------
[Output]: Variable 3: b'c8'
[Output]: Variable 4: b'0120ef0f'

我的正则表达式好像有问题吗?

更新

为进一步阐明,var3和var4代表整数。 我设法弄清楚了值的长度是如何编码的。最高有效位被用作标志来通知我另一个字节即将到来。然后,您可以剥离每个字节的MSB,交换字节序并转换为十进制。

[Output]: Variable 3: b'c8' b'c82001'
[Output]: Variable 4: b'0120ef0f' b'ef0f'

1 个答案:

答案 0 :(得分:0)

您可以使用

def dataVariable(data, start, end):
    p = re.compile(b'(?=(' + start + b'.*' + end + b'))')
    res = []
    for x in p.findall(data):
        cur = b''
        for i, m in enumerate([x[i:i+1] for i in range(len(x))]):
            if i == 0:
                continue
            if m == end and cur:
                res.append(cur)
            cur = cur + m
    return res

请参见Python demo

data = bytearray.fromhex('08051004106418c8200120ef0f0f') # => b'c82001' b'c8'
#data = bytearray.fromhex('185618205720') # => b'56182057' b'2057' b'5618' 
var3 = dataVariable(data, b'\x18', b'\x20')
print("Variable 3:", end=' ')
for item in set(var3):
    print(binascii.hexlify(item), end=' ')

对于Variable 3: b'c8' b'c82001'字符串,输出为'08051004106418c8200120ef0f0f',对于b'56182057' b'2057' b'5618'输入,输出为185618205720

该模式为(?=(...))类型,用于查找所有重叠的匹配项。如果不需要重叠功能,请从正则表达式中删除这些部分。

这里的重点是:

  • start模式匹配从end到最后start + b'.*' + end的所有子字符串
  • 在匹配过程中进行迭代,删除第一个start字节,并在找到end字节时将一个项添加到结果列表中,并在每次迭代时累加找到的字节(因此,将所有内部子字符串都放入内部比赛)。