用Python读写二进制文件

2024-04-26 08:14:30 发布

您现在位置:Python中文网/ 问答频道 /正文

以下代码似乎无法正确读/写二进制形式。它应该读取一个二进制文件,按位对数据进行异或并将其写回文件。没有任何语法错误,但数据无法验证,我已经通过另一个工具测试了源数据,以确认xor键。

更新:根据评论中的反馈,这很可能是由于我正在测试的系统的终结性。

xortools.py

def four_byte_xor(buf, key):
    out = ''
    for i in range(0,len(buf)/4):
        c = struct.unpack("=I", buf[(i*4):(i*4)+4])[0]
        c ^= key
        out += struct.pack("=I", c)
    return out

调用xortools.py:

from xortools import four_byte_xor
in_buf = open('infile.bin','rb').read()
out_buf = open('outfile.bin','wb')
out_buf.write(four_byte_xor(in_buf, 0x01010101))
out_buf.close()

似乎我需要读取每个answer的字节数。当上面的函数操作多个字节时,上面的函数将如何合并到下面的函数中?还是没关系?我需要用struct吗?

with open("myfile", "rb") as f:
    byte = f.read(1)
    while byte:
        # Do stuff with byte.
        byte = f.read(1)

例如,以下文件有4个重复字节01020304:

before XOR

数据是XOR'd,键为01020304,将原始字节归零:

after XOR

下面是对原始函数的一次尝试,在这种情况下,05010501是不正确的结果:

incorrect XOR attempt


Tags: 文件数据函数inread字节二进制open
2条回答

尝试此功能:

def four_byte_xor(buf, key):
    outl = []
    for i in range(0, len(buf), 4):
        chunk = buf[i:i+4]
        v = struct.unpack(b"=I", chunk)[0]
        v ^= key
        outl.append(struct.pack(b"=I", v))
    return b"".join(outl)

我不确定你是不是真的把输入量增加了4个字节,但我没有试图破译它。这假设您的输入可以被4整除。

编辑,基于新输入的新功能:

def four_byte_xor(buf, key):
    key = struct.pack(b">I", key)
    buf = bytearray(buf)
    for offset in range(0, len(buf), 4):
        for i, byte in enumerate(key):
            buf[offset + i] = chr(buf[offset + i] ^ ord(byte))
    return str(buf)

这也许可以改进,但它确实提供了适当的输出。

这里有一个相对简单的解决方案(经过测试):

import sys
from xortools import four_byte_xor
in_buf = open('infile.bin','rb').read()
orig_len = len(in_buf)
new_len = ((orig_len+3)//4)*4
if new_len > orig_len:
    in_buf += ''.join(['x\00']*(new_len-orig_len))
key = 0x01020304
if sys.byteorder == "little":  # adjust for endianess of processor
    key = struct.unpack(">I", struct.pack("<I", key))[0]
out_buf = four_byte_xor(in_buf, key)
f = open('outfile.bin','wb')
f.write(out_buf[:orig_len]) # only write bytes that were part of orig
f.close()

它所做的是将数据的长度填充到4字节的整数倍,即使用4字节键的xor,但随后只写出原始长度的数据。

这个问题有点棘手,因为4字节键的数据字节顺序取决于处理器,但总是先用高字节写入,而字符串或字节数组的字节顺序总是先用低字节写入,如十六进制转储所示。要允许将密钥指定为十六进制整数,必须添加代码以有条件地补偿不同的表示形式,即允许密钥的字节可以按照十六进制转储中出现的字节的相同顺序指定。

相关问题 更多 >