查找上一个非';t等于Python中不需要的字节

查找上一个非';t等于Python中不需要的字节,python,binary,blob,padding,seek,Python,Binary,Blob,Padding,Seek,我正在编写一个小脚本,用来打开一个二进制文件,找到一个经常变化的二进制blob,并将该blob复制到一个新文件中 以下是二进制文件的布局: -JUNK (Unknown Size) (Unknown Contents) -3-byte HEADER containing encoded size of blob -PADDING (Unknown Size) (Every byte is FF in hex) -Start of blob (72 bytes) (Unknown Contents

我正在编写一个小脚本,用来打开一个二进制文件,找到一个经常变化的二进制blob,并将该blob复制到一个新文件中

以下是二进制文件的布局:

-JUNK (Unknown Size) (Unknown Contents)
-3-byte HEADER containing encoded size of blob
-PADDING (Unknown Size) (Every byte is FF in hex)
-Start of blob (72 bytes) (Unknown Contents)
-16 bytes that are ALWAYS the same
-End of blob (Size can be determined from subtracting (72+16) from value HEADER) (Unknown Contents)
-JUNK (Unknown Size) (Unknown Contents)
以下是我迄今为止编写的代码:

from sys import argv
import binascii
import base64

InputFileName = argv[1]

with open(InputFileName, 'rb') as InputFile:

    Constant16 = base64.b64decode("GIhTSuBask6y60iLI2VwIg==")
    Constant16Offset = InputFile.read().find(Constant16)

    InputFile.seek(Constant16Offset)
    InputFile.seek(-72,1)

    InputFile.seek(-1,1)
    FFTestVar = InputFile.read(1)

    while FFTestVar == b'\xFF':
        InputFile.seek(-2,1)
        FFTestVar = InputFile.read(1)

    InputFile.seek(-3,1)
    BlobSizeBin = InputFile.read(3)
    BlobSizeHex = binascii.b2a_hex(BlobSizeBin)
    BlobSizeDec = int(BlobSizeHex, 16)

    InputFile.seek(Constant16Offset)
    InputFile.seek(-72,1)

    Blob = InputFile.read(BlobSizeDec)

    with open('output.bin', 'wb') as OutputFile:

        OutputFile.write(Blob)
不幸的是,while循环很慢。InputFile的大小可能高达24MB,而填充可能是其中的一大块。一次检查一个字节的速度太慢了

我想可能有更好的方法,但一两个小时的谷歌搜索并没有什么帮助


谢谢

您可以将整个文件读入内存(实际上是这样做的):

然后,您可以将
数据
视为随意字符串(但它不是unicode字符串,而是一个字节数组,不幸的是在python 2.X下被称为
str
)。您需要记住偏移量,因此我们将创建
offset
属性。看起来像
InputFile.seek(xx)
的每一行都必须转换成
offset=xx
InputFile.seek(xx,1)
转换成
offset+=xx

magic_number = base64.b64decode("GIhTSuBask6y60iLI2VwIg==")
offset = magic_number_offset = data.find(magic_number)
offset -= 72
然后,使用
re
模块代替while循环(您需要导入该模块):

代码的其余部分是:

offset -= 3
blob_size_bin = data[offset:offset+3]
blob_size_hex = binascii.b2a_hex(blob_size_bin)
blob_size_dec = int(blob_size_hex, 16)
offset = magic_number_offset - 72
blob = data[offset:offset+blob_size_dec]
如果文件非常大并且python进程占用大量内存,那么可以使用
mmap
模块,而不是将整个文件加载到内存中


如果这个解决方案仍然很慢,您可以颠倒数据的顺序(
reversed_data=data[::-1]
),并搜索文件或我迄今为止可怕的实现的模式
[^\ff]

@tjameson。有时在代码中很容易看到问题。@tjameson我在我的帖子中添加了我的实现。我将使用mmap模块和re模块。mmap将允许在文件中找到任何你想要的东西,它的速度很快,没有内存溢出。你可以很容易地将你的代码调整到mmap.Hmm,如果你能负担得起
InputFile.read()
开始时,你能扫描内存中的所有内容吗?我刚醒来,这看起来很棒!我会测试一下。不过,有一个简单的问题:pattern.search()实现是否会在输入文件的第一个垃圾部分中找到任何匹配项,并在找到填充部分的开头之前返回该匹配项?否。请注意模式末尾的美元符号
$
字符。这意味着匹配必须在
endpos
参数确定的位置结束(或者如果省略了
endpos
,则匹配必须在整个字符串结束的位置结束)。非常感谢您的帮助!)
pattern = re.compile("[^\xFF]\xFF*$")
offset = pattern.search(data, endpos=offset).start() + 1
offset -= 3
blob_size_bin = data[offset:offset+3]
blob_size_hex = binascii.b2a_hex(blob_size_bin)
blob_size_dec = int(blob_size_hex, 16)
offset = magic_number_offset - 72
blob = data[offset:offset+blob_size_dec]