第二届“奇安信”杯网络安全技能竞赛Reverse | pyre(需要用到反编译工具 pyinstxtractor.py)
赛题描述
这种exe文件怎么调用py的库?
题目附件:(下载可能会有问题,记得直接跳过下载就可以了)
抱歉无法处理您这个问题哦,您可以换个问题
PyInstaller Extractor 解包
- 适用场景
制作exe后丢失源代码
- 前提条件
使用pyinstaller 进行打包, 且未进行加密.
- 安装
下载v2.0版本的PyInstaller Extractor
这是下载pyinstxtractor.py原地址:https://nchc.dl.sourceforge.net/project/pyinstallerextractor/dist/pyinstxtractor.py
计算机反编译是指通过对他人软件的目标程序(比如可执行程序)进行逆向分析和研究,以推导出他人软件所使用的思路、原理、结构、算法、处理过程、运行方法等设计要素,在某些特定情况下可能会推导出源码。
反编译可以作为开发软件时的参考,或者直接用于软件中。
如果找到了一个 Python 3.7 编译的 EXE 文件,则可以使用反编译获取源码,基本过程如下:
- 将 EXE 文件转换成 PYC 文件;
- 反编译 PYC 文件。
此过程需要反编译工具 pyinstxtractor.py,可以到 GitHub 官网下载,地址为:GitHub - extremecoders-re/pyinstxtractor: PyInstaller Extractor
图1
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?图1:GitHub官网中的 pyinstxtractor.py
反编译的具体步骤为:
1) 使用 pyinstxtractor.py 将 EXE 文件转换成 PYC 文件,在命令行界面中输入下面的命令:
python pyinstxtractor.py helloworld.exe
然后按下 Enter 键,如图2所示。
?
图2:将 EXE 文件转换成 PYC 文件
解压成功后,同路径下会出现 helloworld.exe_extracted 文件夹,这里面就包含了 PYC 文件。
2) 使用 uncompyle6 将 PYC 文件反编译为 PY 文件。uncompyle6 需要单独安装,安装命令如下:
pip install uncompyle6
安装后,使用 uncompyle6 进行反编译,在命令行界面中输入下面的命令:
uncompyle6 12.5_01.pyc > main.py
按下 Enter 键,如图3所示。
?
图3:使用 uncompyle6 进行反编译
成功后,生成 main.py,这样就完成了反编译。
正式解题步骤:
- 使用
- 将需解包的exe与下载的pyinstxtractor.py存入同级文件夹
2. 使用命令行输入如下指令, 得到exe的解包
python pyinstxtractor.py {exe路径}
示例: python pyinstxtractor.py CreatFoder.exe
运行后多出一个目录
3. 在解包的文件夹下, 找到主文件进行反编译得到源码.
4. 关于pyc的反编译, 本文使用uncompyle6库, 大家也可以使用下方的在线反编译。
-
在线反编译工具
在线pyc,pyo,python,py文件反编译,目前支持python1.5到3.6版本的反编译-在线工具
- 本地库安装
pip install uncompyle6
- 使用
- 在解包的文件夹下, 找到主文件
2. 在同级目录下使用命令行输入如下指令
uncompyle6.exe {pyc文件路径} >{py文件输出路径} 示例: uncompyle6.exe .\CreatFoder.pyc >ppi.py
3. 解压完成, 源码get~
- 版本差异
-
使用PyInstxtractor 2.0以下版本进行解包, 需对目标文件补充magic head(表示python的版本和编译时间), 才能正确进行反编译.
使用16进制模式查看主文件与主文件目录下的 struct 文件,需要在主文件头插入16个字节与 struct文件保持一致, 再使用uncompyle6进行反编译.
(注意, 此说明来自网络, 答主并未按此步骤成功操
让我们思考如何优化这段代码:
-
check = "flag{" c = [ ? ? 144, ? ? ? ? 163, ? ? ? ? 158, ? ? ? ? 177, ? ? ? ? 121, ? ? ? ? 39, ? ? ? ? 58, ? ? ? ? 58, ? ? ? ? 91, ? ? ? ? 111, ? ? ? ? 25, ? ? ? ? 158, ? ? ? ? 72, ? ? ? ? 53, ? ? ? ? 152, ? ? ? ? 78, ? ? ? ? 171, ? ? ? ? 12, ? ? ? ? 53, ? ? ? ? 105, ? ? ? ? 45, ? ? ? ? 12, ? ? ? ? 12, ? ? ? ? 53, ? ? ? ? 12, ? ? ? ? 171, ? ? ? ? 111, ? ? ? ? 91, ? ? ? ? 53, ? ? ? ? 152, ? ? ? ? 105, ? ? ? ? 45, ? ? ? ? 152, ? ? ? ? 144, ? ? ? ? 39, ? ? ? ? 171, ? ? ? ? 45, ? ? ? ? 91, ? ? ? ? 78, ? ? ? ? 45, ? ? ? ? 158, ? ? ? ? 8 ] tmp = [] for i in range(len(check)): ? ? for j in range(1, 1000): ? ? ? ? if ord(check[i]) * 33 % j == c[i]: ? ? ? ? ? ? tmp.append(j) b = max(tmp, key=tmp.count) List = "0123456789abcdeflg{}-" for i in range(42): ? ? for tmp in List: ? ? ? ? if ord(tmp) * 33 % b == c[i]: ? ? ? ? ? ? print(tmp, end="")
-
运行得到flag:flag{2889e7a3-0d6b-4cbb-b6e9-04c0f26c9dca}
-
代码分析:
首先,这段代码的主要目的是通过对给定的数字数组
c
进行某种转换,以找到与check
字符串相匹配的字符,并最终输出一个结果字符串。让我们逐步分析这段代码:
- 一个名为
check
的字符串被初始化为"flag{"
。 - 一个名为
c
的数组被初始化,包含了一系列的数字。 - 首先,我们可以注意到,在第一个嵌套循环中,对于每个字符,我们都重复进行了相同的计算多次,这是不必要的。我们可以直接计算每个字符的结果,并存储在一个字典中,以便后面直接使用。
- 其次,由于最终要输出的字符是来自于
List
中的,我们可以在初始化时就将这个列表转换为一个字典,以ord(char)
为键,char
为值,这样就可以直接通过计算结果来查找对应的字符- 一个名为
tmp
的空列表被初始化,用于存储临时结果。 - 第一个嵌套的
for
循环遍历check
字符串的每个字符,并在内部循环中与数字1到1000进行某种运算。这里的主要目的是找到一个数字j
,使得ord(check[i]) * 33 % j
的结果等于c[i]
。如果找到这样的数字,就将其添加到tmp
列表中。 - 找到
tmp
列表中出现次数最多的数字b
。 - 在最后的循环中,通过遍历一个名为
List
的字符串列表,并再次使用相同的运算逻辑,找到一个字符,其ord(tmp) * 33 % b
的结果等于c[i]
。如果找到这样的字符,就打印出来。
- 一个名为
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!