Python读取exe中导入的dll名称
1、脚本介绍
在项目中经常添加一些Qt模块,但是如果每次打包人工的去搜索复制,也是一件挺烦人的事情。所以写个脚本去做这件事情,顺理成章的事情。顺便学下python语法。
2、用法
- 将下面的代码保存,命名为:dependency_walker.py
python.exe .\dependency_walker.py -p "c:\abc.exe,path2"
- 同时会将用到Qt dll保存到当前目录下,命名为:
recorder.txt
- 我在项目用到的Qt 5.15.2.0 所以就设置了一个环境变量,你可能需要修改为你的
3、代码
需要安装pereader,colorama2个库
执行命令pip install pereader
和 pip install colorama
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2022-6-27 10:39:28
# @Author : shixiong.Liu (635672377@qq.com)
import os
import sys
import argparse
import colorama
import pereader
import shutil
class App:
def __init__(self):
self._clear()
def _clear(self):
self.path = ""
self.Qt5_path = ""
self.all_dll_lists = []
def _parse_args(self, args):
parser = argparse.ArgumentParser(description='Tools for analyze file contains dll')
parser.add_argument('-p', '--path', help='files path, format:"path1, path2, path3"')
args = parser.parse_args(args)
self.path = args.path
def _parse_dll(self, path):
pe = pereader.PE(path, is_entropy=True)
for dll in pe.directory_entry_import.dlls:
if dll.name not in self.all_dll_lists:
self.all_dll_lists.append(dll.name)
if dll.name.find("Qt5") == 0:
new_dll_path = ""
if self.Qt5_path.find("bin") == -1:
new_dll_path = self.Qt5_path + "\\bin\\" + dll.name
else:
new_dll_path = self.Qt5_path + "\\" + dll.name
if os.path.exists(new_dll_path):
self._parse_dll(new_dll_path)
shutil.copy(new_dll_path, os.curdir)
print(dll.name)
else:
print(colorama.Fore.RED + "Not find file " + new_dll_path)
def _write_to_file(self):
file = open(".\\recorder.txt", mode="w+", )
self.all_dll_lists.sort()
new_text_content = ""
for name in self.all_dll_lists:
new_text_content += name + "\r"
file.write(new_text_content)
file.close()
print(colorama.Fore.GREEN + "write recorder file finished.")
def run(self, args):
self._parse_args(args)
self.Qt5_path = os.getenv("QTDIR5_15_2_0")
if self.Qt5_path == "" :
print(colorama.Fore.RED + 'Not find QTDIR5_15_2_0 environment')
else:
print(colorama.Fore.GREEN + 'find QTDIR5_15_2_0 environment:' + self.Qt5_path)
for path in self.path.split(","):
print(colorama.Fore.GREEN + "path:" + path)
self._parse_dll(path)
self._write_to_file()
if __name__ == '__main__':
colorama.init(autoreset=True)
try:
app = App()
if not app.run(sys.argv[1:]):
sys.exit(-1)
except KeyboardInterrupt:
pass
sys.exit(0)
4、总结
通过这种分析PE的结构,也是有缺点的,项目通过隐式加载的就没有问题,但是显示加载就没法读取。
说起来Python还真是香,要是用C++,估计的要干好几天时间。