• Как найти заданные сигнатуры во множестве файлов, открытых для бинарного чтения?

    @insolor
    Если файлы не слишком большие (полностью помещаются в память), можно грузить в память, и матчить целиком.

    Пример, если достаточно найти одно совпадение:

    import re
    
    pattern = b'\x80.A.+\x80.Z' # cmp reg8, 'A' ..... cmp reg8, 'Z'
    
    with open("file.bin", 'rb') as f:
        match = re.search(pattern, f.read())
        if match:
            print(hex(match.start()), match.group(0))  # выводим смещение от начала файла и найденное совпадение
        else:
            print('Nothing found')


    Вывод:

    0x2cb3b4 b'\x80\xf9A|\x05\x80\xf9Z'

    Если нужно найти все совпадения:

    with open("file.bin", 'rb') as f:
        for match in re.finditer(pattern, f.read()):
            print(hex(match.start()), match.group(0))


    Вывод:

    0x2cb3b4 b'\x80\xf9A|\x05\x80\xf9Z'
    0x444184 b'\x80\xf9A|\x05\x80\xf9Z'


    Тестировалось на файле размера порядка 10 МБ, нужные мне совпадения находит мгновенно.

    Если файлы достаточно большие (несколько гигабайт), то придется читать файл по блокам. И все-таки нужно определиться, какой максимальный размер может занимать искомый блок данных, в зависимости от этого выбирать размер считываемого блока.

    Нужно использовать два буфера, т.к. начало совпадения может оказаться внутри одного буфера, а конец внутри другого. На каждом этапе два соседних буфера складываются, поиск происходит внутри объединенного буфера.

    Пример реализации:

    block_size = 512*1024**2  # 512 мегабайт
    
    block1 = b''
    
    with open('file.bin', 'rb') as f:
        while True:
            block2 = f.read(block_size)
            if not block2:  # Достигнут конец файла
                match = None
                break
            match = re.search(pattern, block1 + block2)  # Не тестировалось на больших файлах, сцепление длинных байтовых строк в цикле может тормозить!
            if match:
                break
            block1 = block2
    
    if match:
        print(hex(match.start()), match.group(0))
    else:
        print('Nothing found')
    Ответ написан
    Комментировать