Regex / Python3 - re.findall () - Найти все вхождения между кодами операций - PullRequest
0 голосов
/ 06 сентября 2018

Фон

Я занимаюсь обратным проектированием потока TCP, который использует подход Type-Length-Value для кодирования данных.

Пример:

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    

Однако Данные - это объект данных, который может включать несколько переменных с переменными длинами данных.

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

В настоящее время я анализирую Данные, используя следующий код Python3:

############################### 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'

Я ожидалвывод:

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

Кажется, что есть проблема с моим регулярным выражением?

Обновление

Для дальнейшего пояснения, var3 и var4 представляют целые числа.Мне удалось выяснить, как длина значения была закодирована.Наиболее значимый бит использовался в качестве флага, чтобы сообщить мне, что прибывает другой байт.Затем вы можете обрезать MSB каждого байта, поменять местами порядковый номер и преобразовать в десятичную.

  data   ->   binary representation    -> strip MSB and swap endianness -> decimal representation

ac d7 05 -> 10101100 11010111 00000101 ->   0001 01101011 10101100      ->   93100
e4 a6 04 -> 11100100 10100110 00000100 ->   0001 00010011 01100100      ->   70500
90 e1 02 -> 10010000 11100001 00000010 ->        10110000 10010000      ->   45200
dc 24    ->          11011100 00100100 ->        00010010 01011100      ->   4700
f0 60    ->          11110000 01100000 ->        00110000 01110000      ->   12400

1 Ответ

0 голосов
/ 06 сентября 2018

Вы можете использовать

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 :

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 pattern
  • выполняет итерацию по совпадению, удаляя первый байт start и добавляя элемент в результирующий список, когда найден байт end, добавляя найденные байты на каждой итерации (таким образом, получая все внутренние подстроки внутри совпадения).
...