Python逆向基本操作步骤详解——以杭电新生赛hgame week2 reverse stream(python3.10逆向)为例

Python逆向基本操作步骤详解——以杭电新生赛hgame week2 reverse stream(python3.10逆向)为例 目录一.查壳二.从stream.exe中提取stream.pyc和struct.pyc文件1.方法一:使用pyinstxtractor.py提取(较为简单)(1)下载pyinstxtractor.py(2)将stream.exe和pyinstxtractor.py文件置于同一文件夹内,在该路径内打开cmd(3)获取pyc文件(4)修复Magic Head2.方法二:使用PyInstaller自带的archive_viewer.py提取(相对复杂)(1)首先安装pyinstaller(2)找到archive_viewer.py文件(3)获取pyc文件(4)将stream.pyc的magic head头信息补上去,同方法1三.反编译stream.pyc文件获取stream.py源码1.使用pyc在线解密(推荐)2.使用pycdc(推荐)(1)安装CMake(2)下载pycdc项目(3)使用pycdc.exe反编译pyc文件3.stream.py源码四.程序逻辑及解题脚本五.参考文章六.扩展--通过翻译字节码得到源码1.使用python3.11解释器调用dis解释出pyc文件的字节码2.使用ChatGpt翻译字节码得到源码(看文档生啃也可以)一.查壳通过查壳可以发现这是python语言编写,使用PyInstaller打包的exe程序,但是并不确定python版本二.从stream.exe中提取stream.pyc和struct.pyc文件1.方法一:使用pyinstxtractor.py提取(较为简单)(1)下载pyinstxtractor.py下载地址: extremecoders-re/pyinstxtractor: PyInstaller Extractor (github.com)点绿色的code,再点download zip即可下载(2)将stream.exe和pyinstxtractor.py文件置于同一文件夹内,在该路径内打开cmd(3)获取pyc文件使用命令:python pyinstxtractor.py stream.exe则会在该路径下输出stream.exe_extracted文件夹,同时也可以看到pyinstaller和python的版本(python3.10)注意:这里最好是让使用的python解释器版本和待解包程序python版本一致(建议使用Anaconda管理python版本),保证输出准确,否则可能会丢失部分文件(4)修复Magic Head一般而言,使用pyinstxtractor解包会自动修复MagicHead,如果没有自动修复则手动修复在文件夹内找到stream.pyc和struct.pyc文件,用winhex或者010editor打开,将struct文件的第一行(Magic head)复制到stream.pyc的最前面,保存更改2.方法二:使用PyInstaller自带的archive_viewer.py提取(相对复杂)(1)首先安装pyinstallerpip install pyinstaller -i https://pypi.douban.com/simple(也可指定为其他源)(2)找到archive_viewer.py文件使用where python找到python所在路径,然后在python所在的文件夹内找Lib\site-packages\PyInstaller\utils\cliutils\archive_viewer.py即: C:\Users\admin\AppData\Local\Programs\Python\Python310\Lib\site-packages\PyInstaller\utils\cliutils\archive_viewer.py(3)获取pyc文件将archive_viewer.py复制到stream.exe所在文件夹内,在文件夹内打开cmd,使用命令python archive_viewer.py stream.exe,这里也可以看到python版本等信息继续使用命令即可输出stream.pyc和struct.pyc文件(4)将stream.pyc的magic head头信息补上去,同方法1三.反编译stream.pyc文件获取stream.py源码1.使用pyc在线解密(推荐)选择pyc文件即可得到源码:2.使用pycdc(推荐)如果不想下载编译的话这里有我编译好的pycdc.exe,可以直接跳转到(4)反编译pyc文件(1)安装CMake官网:Download | CMake下载installer安装包版安装时记得勾选添加到环境变量,其他选项默认即可(2)下载pycdc项目1. 使用命令行下载git clone https://github.com/zrax/pycdc.git #下载pycdc cd pycdc #进入pycdc目录 cmake . #注意是cmake . 这个.点号使用visual studio打开pycdc文件夹中的pycdc.sln文件打开后选择x64 release模式编译运行在pycdc/Release文件夹内可以找到pycdc.exe也可以选则直接下载源码2. 直接下载项目地址:zrax/pycdc: C python bytecode disassembler and decompiler (github.com)点击CodeDownload Zip解压后得到的文件夹用VisualStudio打开,然后找到pycdc.cpp文件,然后点击管理配置点击绿色号选择x64-release,然后ctrls保存json的设置就可以选择x64-release模式编译然后在生成里选择全部生成最后就可以在~\pycdc-master\out\build\x64-Release目录下找到pycdc.exe了(可以将目录配置到环境变量方便使用)(3)使用pycdc.exe反编译pyc文件将pycdc.exe和stream.pyc文件放于同一文件夹内(也可以将pycdc.exe所在文件夹路径添加到环境变量)在文件夹内打开cmd,使用命令:pycdc stream.pyc成功输出源码:3.stream.py源码#!/usr/bin/env python # visit https://tool.lu/pyc/ for more information # Version: Python 3.10 import base64 def gen(key): s list(range(256)) j 0 for i in range(256): j (j s[i] ord(key[i % len(key)])) % 256 tmp s[i] s[i] s[j] s[j] tmp i j 0 data [] for _ in range(50): i (i 1) % 256 j (j s[i]) % 256 tmp s[i] s[i] s[j] s[j] tmp data.append(s[(s[i] s[j]) % 256]) return data def encrypt(text, key): result for c, k in zip(text, gen(key)): result chr(ord(c) ^ k) result base64.b64encode(result.encode()).decode() return result text input(Flag: ) key As_we_do_as_you_know enc encrypt(text, key) if enc wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl: print(yes!) return None None(try again...)四.程序逻辑及解题脚本#!/usr/bin/env python # visit for more information # Version: Python 3.10 # 反编译代码 import base64 def gen(key): s list(range(256))#s[0,1,...,255] j 0 for i in range(256): j (j s[i] ord(key[i % len(key)])) % 256 tmp s[i] s[i] s[j] s[j] tmp i j 0 data [] for _ in range(50):# _字符表示不指明循环变量,但是循环会进行50次 i (i 1) % 256 j (j s[i]) % 256 tmp s[i] s[i] s[j] s[j] tmp data.append(s[(s[i] s[j]) % 256]) return data def decrypt(enc , key): result enc base64.b64decode(enc.encode()).decode() c for i, k in zip(enc, gen(key)): c chr((ord(i) ^ k)) print(c) key As_we_do_as_you_know enc wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl decrypt(enc, key) #hgame{python_reverse_is_easy_with_internet}得到flag:hgame{python_reverse_is_easy_with_internet}五.参考文章1.逆向python生成的可执行文件2.[Python逆向] 逆向Pyinstaller打包的exe文件源码及保护3.Pyinstaller打包的exe之一键反编译py脚本与防反编译4.【Python教程】保姆版教使用Pyinstaller 打包python成exe文件5.使用pydumpck反编译pyintaller生成的exe文件 python3.106.Python 反编译pycdc工具的使用六.扩展--通过翻译字节码得到源码DASCTF2023 RE easyRE 这题使用python3.11解释器,由于版本过高,得到pyc字节码文件后无法反编译出python源码.1.使用python3.11解释器调用dis解释出pyc文件的字节码import marshal import dis fopen(reasyRE.pyc,rb) # 将pyc文件和该脚本放于同一文件夹内,或者自行指定绝对路径 codemarshal.loads(f.read()[16:]) print(dis.dis(code)) f.close()字节码:2.使用ChatGpt翻译字节码得到源码(看文档生啃也可以)ChatGpt翻译出的源码import random r random.Random(322376503) pt input(Enter your flag: ).encode() ct b\x8b\xcck\xd3\xed\x96\xffFb\x06r\x085\x82\xbc \xb2\xde)p\x88Q\x1bf\x18\xb6QUSw\x10\xcd\xd9\x13A$\x86\xe5\xcd\xd9\xff buf [] for b in pt: buf.append(b ^ r.randint(0, 255)) if bytes(buf) ct: print(Correct!) else: assert False3. pydisasm -F xasm PycFile.pycout.txt命令打印字节码dis库打印时可能会有报错的情况,这时可以尝试这条命令