请教如何使用 Python 直接对二进制文件进行修改

2020-10-29 09:08:16 +08:00
 v2410117

刚接触 python 不久,想用 python 直接修改二进制文件中的某段字符串内容,在网上查询使用fopen然后用seek定位,write写入.我测试过确实能达到效果。

但是如果替换的长度不一样,比如本来的字符串为test,我用上面的方法想替换成mytest,因为长度比原来的长,就替换不成功,本来我想的是,在内存里找一块空的地址,写入mytest,然后将地址替换到test里面,虽然想的很美好,但是实在不会操作,特来请教一下这种替换长度不一致的,该如何操作,提前致谢

3968 次点击
所在节点    Python
22 条回复
whileFalse
2020-10-29 09:12:02 +08:00
如果文件不大的话,全部读出-内存替换-全部写回
fasionchan
2020-10-29 09:12:20 +08:00
文件不大的话可以将整个文件读到内存,在内存中做替换后,再整体覆盖写入
whileFalse
2020-10-29 09:17:56 +08:00
replace_data = b'mytest'
replace_begin = 3
replace_end = 7

with open('a.txt', 'rb') as f:
data = f.read()
print(data)
print(data[replace_begin:replace_end])
data = data[:replace_begin] + replace_data + data[replace_end:]
print(data)
with open('b.txt', 'wb') as f:
f.write(data)
no1xsyzy
2020-10-29 09:34:50 +08:00
Python 不需要找 “空的地址”,你直接创建对象就会自动分配内存。
f.read() 就会创建 bytes 对象,之后 replace 替换,完了再 f.write() 回去就成
不一样长度的话,除非整 block,并且修改文件系统 metadata,不然从你修改的位置开始后面全部得覆写一遍的。
lllllliu
2020-10-29 09:41:04 +08:00
难道不是计算修改后的文件长度,修改区段表或者结构段定义头的长度,然后在修改或填充么。。
zone10
2020-10-29 09:56:54 +08:00
新手多找成型的代码看, 按照规范来写代码, 别老是以自己狭隘的思路写, 看多了你就知道有些问题压根不存在
v2410117
2020-10-29 10:09:41 +08:00
@whileFalse 大佬您好,首先感谢您提供的代码,我使用测试后,发现修改后提示`segmentation fault`,无法运行,是还需要修改其他的结构吗?谢谢
v2410117
2020-10-29 10:10:57 +08:00
@zone10 感谢您提供的建议,多多看代码!
whileFalse
2020-10-29 10:14:32 +08:00
@v2410117 你在代码相同目录下放一个 a.txt 文件,内容是“123test123”试试看
playniuniu
2020-10-29 10:19:16 +08:00
二进制文件比如 ELF 类型的是有特定格式的,你要是在中间随便增加长度,估计整个程序都运行不了。要增加长度,先确定二进制文件的类型,比如 ELF 格式的,是需要找一片空白区域,把新数据放进去,在把原来读这端程序的地方改成读新的,还是蛮麻烦的。
v2410117
2020-10-29 10:35:46 +08:00
@whileFalse 文本文件是可以,但是二进制执行文件就不行了,应该是如楼上说的那样,还要修改结构啥的吧!
v2410117
2020-10-29 10:37:21 +08:00
@playniuniu 嗯,对,确实如您所说的为 elf 格式,按直接拼接 bytes 的做法确实导致整个程序都无法运行了.我也是想的您后面提到的那个操作,先找个空白区域写好,然后修改读的地址,但是不太会用 python 操作,正在寻找解决办法中
mumbler
2020-10-29 10:40:57 +08:00
二进制结构一般会固定字段长度,如果 test 没占满,后面一定会有空字节,就把 mytest 写入前 6 位。归根结底,要了解这种二进制的文件结构
whileFalse
2020-10-29 10:43:43 +08:00
@v2410117 可执行文件有文件格式啊……你得研究文件格式。修改还是按照我说的方法修改的。但在特定的文件格式下应该怎么修改,那你得自己研究。
zhyl
2020-10-29 10:46:58 +08:00
如果需要写入后的二进制文件还是正常运行,那么重点不在于如何写入,需要了解对应二进制文件的格式,例如 windows 下 PE 格式以区段划分,代码存放在代码段,数据存放在数据段,如果修改(变长或减短)数据段的内容,那么在代码段中所有这块修改数据之后的数据被引用时,其引用的地址都需要修正。
belite
2020-10-29 10:54:13 +08:00
我有一个想法 边读边改边写 写到另一个空文件里 完成后替换原文件
aneostart173
2020-10-29 10:55:27 +08:00
你这个要求对应文本编辑器的插入编辑操作,文本编辑器的实现就很复杂,一两句说不清楚。
CRVV
2020-10-29 11:07:42 +08:00
@v2410117

如果你连改文件内容都需要来发帖子问,改 ELF 然后还要能跑属于你不可能完成的事情,放弃吧。

https://blog.0patch.com/2017/11/did-microsoft-just-manually-patch-their.html
这是微软做过然后能上新闻的操作。
playniuniu
2020-10-29 14:55:21 +08:00
@v2410117 这篇文章有关于 Android so 文件 的修改方法 http://www.520monkey.com/archives/561,你可以参考一下,其他 ELF 格式应该差不多
imn1
2020-10-29 15:05:54 +08:00
1.字节是可以使用 replace 函数的
2.可以前后截取,再用新字节重新拼接

如果二进制文件是某种格式,自然要按那种格式的规范来做,不是这样随意改动,例如 jpg 里面改动 exif,exif 实际只是字节数据,可以改动不影响图像显示,但也是要符合 exif 以及 jpeg 规范的,没有足够知识的话,最好用相关模块辅助完成

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/719647

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX