10

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

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

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

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

异或之前

数据与密钥 01020304 进行异或运算,将原始字节归零:

异或后

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

不正确的异或尝试

4

2 回答 2

3

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

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 字节的密钥进行异或,但随后只写出原始长度的数据。

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

于 2012-07-13T01:18:50.773 回答
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)

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

于 2012-07-13T01:20:25.713 回答