Python从PE文件中导出资源文件

最近需要修改一个QT编写的应用,就是将资源图片修改一下,但是资源图片被打包到DLL的.rdata段中,无法直接导出,于是想通过Python直接读取导出,然后定位需要修改图片的位置。具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# -*- coding:utf-8 -*-

import os,sys,re

def find_all_pos(filename,feature):
"""打开二进制文件,搜索指定特征的位置,并返回所有位置的列表
"""
with open(filename, 'rb') as binFile:
binFileStr = binFile.read()
posArray = [m.start() for m in re.finditer(feature, binFileStr)]
return posArray

def export_all_png(filename,posArray):
"""打开二进制文件,根据特征位置数组,导出所有的PNG文件
"""
with open(filename, 'rb') as binFile:
for i in range(len(posArray)-1):
pngLen = posArray[i+1] - posArray[i]
# print(pngLen)
binFile.seek(posArray[i])
pngFileBin = binFile.read(pngLen)
pngFile = open("res\\"+str(i)+".png", "wb")
pngFile.write(pngFileBin)

def find_feature_pos(filename,feature):
"""打开二进制文件,搜索指定特征最早出现的位置,并返回结果
"""
with open(filename, 'rb') as binFile:
binFileStr = binFile.read()
result = re.search(feature,binFileStr)
try:
return result.span(0)[0]
except:
return -1

def merge_new_file(filename,feature_pos):
"""打开二进制文件,提取特征之后的数据,与新的文件头合并
"""
file_header=b"\x44\x55\x66"
with open(filename, 'rb') as binFile:
binFile.seek(feature_pos)
datFileBin = binFile.read()
datFile = open(filename[:-4]+"_new"+filename[-4:], "wb")
datFile.write(file_header)
datFile.write(datFileBin)

def walk_files(src_filepath = ".", file_name_feature=".exe"):
"""遍历目录中的文件,提取指定特征的文件
"""
filepath_list = []

for root, dirs, files in os.walk(src_filepath):
for file in files:
if file.endswith(file_name_feature)==False:
continue
if root == '.':
root_path = os.getcwd() + "/"
else:
root_path = root

if (root_path != src_filepath) and (root != '.'):
filepath = root_path + "/" + file
else:
filepath = root_path + file

if filepath not in filepath_list:
filepath_list.append(filepath)

return filepath_list

if __name__ == "__main__":
for path in sys.argv[1:]:
if os.path.isfile(path):
posArray = find_all_pos(path,b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
# 位置数组应该大于1
if(len(posArray)>1):
# print(posArray)
if(os.path.exists("res")==False):
os.makedirs("res")
pngList=""
for i in range(len(posArray)):
pngList = pngList + str(i) + ",0x%x"%posArray[i] +"\n"
# 保存图片位置信息
pngFileMeta = open("res\\pnglistpos.csv", "w")
pngFileMeta.write(pngList)

export_all_png(path,posArray)

运行时采用如下命令:

1
2
3
python -m venv env
.\env\Scripts\activate
python utf8_to_gbk.py filepath

参考链接

  1. PNG文件格式详解,by oriole.
  2. Python输出列表list,by huang_0430.
  3. python创建目录(文件夹),by FanWinter.
  4. python 数字 十六进制 打印,by wowocpp.
  5. python文件的打开、读取、关闭、写入与二进制文件的读写操作,by aliyun.
  6. How to find all occurrences of a substring?,by stackoverflow.
  7. 如何逆向解决QT程序汉化中的乱码问题-干货,by 葫芦娃很厉害.
  8. 如何汉化一个软件,by CCDebuger.
  9. Qt 资源系统(Qt Resource System),by 南理汉子.