使用Python修改二进制文件

7

我正在尝试修补一个十六进制文件。

我有两个需要修补的文件 (hex),它们分别叫做 "patch 1" 和 "patch 2"。

需要被修补的文件是一个名为 "file.bin" 的 16 MB 文件。

我已经尝试了很多种不同的方法,花了6或7个小时来找出如何完成它。我可以一整天写入文件,但我正尝试做以下事情:

用读取字节打开 patch1.bin
用读取字节打开 patch2.bin
用写入字节打开 file.bin

我想要跳转到位置 0xc0010 和 0x7c0010,并应用 patch1.bin,
然后我想要跳转到 0x040000 并应用 patch2.bin。

所以总的来说,我将应用3个补丁,然后关闭 "file.bin"。

如果有人能给我一个示例,我会非常感激:)

我先尝试了这个:

patch1 = open("patch1", "r");
patch2 = open("patch2", "r");
main = open("file.bin", "w");

main.seek(0xC0010);
main.write(patch1);
main.seek(0x7C0010);
main.write(patch1);
main.seek(0x40000);
main.write(patch2);
main.close();

但是我被告知我试图将一个字符串写入文件,而这并不是我想要的,哈哈。然后我尝试了这个:

infile1 = open("patch1.bin", "rb") 
new_pos1 = int("0x00", 16)
infile1.seek(new_pos1, 0)
infile2 = open('file.bin', 'wb')
new_pos2 = int('0xc0010', 16)
infile2.seek(new_pos2, 0xc0010)
chunk1 = int("6FFFE0", 16)         #this is how long patch1 file is
data1 = infile1.read(chunk1)
with open("file.bin", "a") as outfile:
    outfile.write(data1)

但是,无论我尝试什么,它都没有起作用,因为我无法将数据写入正确的偏移量。我确实几次成功地将 patch1 写入 file.bin,但它并没有在正确的偏移处进行补丁,事实上它删除了 file.bin 并仅仅复制了 patch1 到其位置。这当然是错误的。
需要提醒您的是,我对 Python 和编程都很新手,但我真的很努力地学习,所以任何好的例子都会被检查,并希望可以成为我良好的学习教材 :)
感谢大家帮助我找出我的错误 :)

你尝试了什么?引用你的代码。 - Antony Hatchkins
1
那不是一个“十六进制文件”,它是一个二进制文件。一个十六进制文件应该是一个包含十六进制数字的文本文件。当你想要处理文本时,这些通常用于表示二进制数据。 - unwind
3个回答

13

你只需要使用seekwrite。使用seek来跳转到指定位置,使用write来覆盖已有的数据。

with file('patch1.bin', 'rb') as fh:
    patch1 = fh.read()

with file('patch2.bin', 'rb') as fh:
    patch2 = fh.read()

with file('file.bin', 'r+b') as fh:
    # apply patch1
    fh.seek(0xc0010)
    fh.write(patch1)
    fh.seek(0x7c0010)
    fh.write(patch1)
    # apply patch2
    fh.seek(0x040000)
    fh.write(patch2)

2
好的,我找到了问题所在,使用file('file.bin', 'w')需要改为'r+'... 在我修改后,代码完美地运行了。非常感谢 :) - james28909
2
打开补丁文件时,应该用二进制模式打开 - open("<fn>", "rb"),而要打补丁的文件应该以“r+b”模式打开。 - Simon Callan
1
"w" 模式会截断文件。使用 "r+b" 模式来修补现有文件。 - Antony Hatchkins
我逐字测试了文件,但是当我运行脚本时,与手动修补文件时不同,我使用HxD进行了测试并使用文件比较功能。有没有办法使它更准确? - james28909
当处理大文件时,也许你应该考虑使用 mmap 而不是 file.read 等方法。 - youfu
显示剩余2条评论

3

1.txt:

asdf

a.py:

with open('1.txt','r+b') as f:
    f.seek(2)
    f.write('D')

1.txt:

asDf

这应该能给你一些线索。

是的,我现在知道我做错了什么了 ;) 感谢你教育一个新手哈哈 - james28909

2
你需要使用 r+b 模式来编辑目标文件。 wb 是用于写入而不更新并截断现有文件的模式。请查看 http://docs.python.org/2/library/functions.html#open 或您操作系统的 fopen 手册以获取有关不同文件模式的详细信息。

w+b 截断文件。在这种情况下使用 r+b - Antony Hatchkins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接