10

次のコードは、バイナリ形式を正しく読み書きしていないようです。バイナリ ファイルを読み取り、データをビット単位で 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()

回答ごとにバイトを読み取る必要があるようです。上記の関数は複数のバイトを操作するため、上記の関数はどのように以下に組み込まれますか? またはそれは問題ではありませんか?structを使用する必要がありますか?

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

たとえば、次のファイルには 01020304 という 4 つの繰り返しバイトがあります。

XOR の前に

データは、元のバイトをゼロにする 01020304 のキーで XOR されます。

XOR 後

これは元の関数での試行です。この場合、05010501 は正しくない結果です。

間違った XOR 試行

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 バイトのキーで xor しますが、元の長さのデータのみを書き出すだけです。

4 バイトのキーのデータのバイト順はプロセッサによって異なりますが、常に上位バイトが最初に書き込まれますが、文字列またはバイト配列のバイト順は常に下位バイトが最初に書き込まれるため、この問題は少し厄介でした。あなたの16進ダンプに示されているように。キーを 16 進整数として指定できるようにするには、異なる表現を条件付きで補正するコードを追加する必要がありました。つまり、16 進ダンプに表示されるバイトと同じ順序でキーのバイトを指定できるようにする必要がありました。

于 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 に答える