用Python读写二进制文件

时间:2012-07-13 00:10:04

标签: python

以下代码似乎无法正确读/写二进制形式。它应该读取一个二进制文件,逐位XOR数据并将其写回文件。没有任何语法错误,但数据无法验证,我已通过其他工具测试源数据以确认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

使用01020304的密钥对数据进行异或,将原始字节归零:

after XOR

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

incorrect XOR attempt

2 个答案:

答案 0 :(得分: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)

这可能会有所改进,但它确实提供了正确的输出。

答案 1 :(得分:1)

这是一个相对简单的解决方案(已测试):

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个字节的整数倍,xor是四字节密钥,但只写出原始长度的数据。

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