当前位置:   article > 正文

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

python逆向

目录

一.查壳

 二.从stream.exe中提取stream.pyc和struct.pyc文件

1.方法一:使用pyinstxtractor.py提取(较为简单)

(1)下载pyinstxtractor.py

(2)将stream.exe和pyinstxtractor.py文件置于同一文件夹内,在该路径内打开cmd

(3)获取pyc文件

(4)修复Magic Head

2.方法二:使用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)首先安装pyinstaller

pip 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. 使用命令行下载

  1. git clone https://github.com/zrax/pycdc.git #下载pycdc
  2. cd pycdc #进入pycdc目录
  3. cmake . #注意是cmake . 这个'.'点号

使用visual studio打开pycdc文件夹中的pycdc.sln文件

打开后选择x64 release模式编译运行

在pycdc/Release文件夹内可以找到pycdc.exe

也可以选则直接下载源码

2. 直接下载

项目地址:zrax/pycdc: C++ python bytecode disassembler and decompiler (github.com) 

点击Code>Download Zip

 解压后得到的文件夹用VisualStudio打开,然后找到pycdc.cpp文件,然后点击管理配置 

 点击绿色+号选择x64-release,然后ctrl+s保存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源码

  1. #!/usr/bin/env python
  2. # visit https://tool.lu/pyc/ for more information
  3. # Version: Python 3.10
  4. import base64
  5. def gen(key):
  6. s = list(range(256))
  7. j = 0
  8. for i in range(256):
  9. j = (j + s[i] + ord(key[i % len(key)])) % 256
  10. tmp = s[i]
  11. s[i] = s[j]
  12. s[j] = tmp
  13. i = j = 0
  14. data = []
  15. for _ in range(50):
  16. i = (i + 1) % 256
  17. j = (j + s[i]) % 256
  18. tmp = s[i]
  19. s[i] = s[j]
  20. s[j] = tmp
  21. data.append(s[(s[i] + s[j]) % 256])
  22. return data
  23. def encrypt(text, key):
  24. result = ''
  25. for c, k in zip(text, gen(key)):
  26. result += chr(ord(c) ^ k)
  27. result = base64.b64encode(result.encode()).decode()
  28. return result
  29. text = input('Flag: ')
  30. key = 'As_we_do_as_you_know'
  31. enc = encrypt(text, key)
  32. if enc == 'wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl':
  33. print('yes!')
  34. return None
  35. None('try again...')

四.程序逻辑及解题脚本

  1. #!/usr/bin/env python
  2. # visit for more information
  3. # Version: Python 3.10
  4. # 反编译代码
  5. import base64
  6. def gen(key):
  7. s = list(range(256))#s=[0,1,...,255]
  8. j = 0
  9. for i in range(256):
  10. j = (j + s[i] + ord(key[i % len(key)])) % 256
  11. tmp = s[i]
  12. s[i] = s[j]
  13. s[j] = tmp
  14. i = j = 0
  15. data = []
  16. for _ in range(50):# _字符表示不指明循环变量,但是循环会进行50次
  17. i = (i + 1) % 256
  18. j = (j + s[i]) % 256
  19. tmp = s[i]
  20. s[i] = s[j]
  21. s[j] = tmp
  22. data.append(s[(s[i] + s[j]) % 256])
  23. return data
  24. def decrypt(enc , key):
  25. result=''
  26. enc = base64.b64decode(enc.encode()).decode()
  27. c = ""
  28. for i, k in zip(enc, gen(key)):
  29. c += chr((ord(i) ^ k))
  30. print(c)
  31. key = 'As_we_do_as_you_know'
  32. enc = "wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl"
  33. decrypt(enc, key)
  34. #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.10

6.Python 反编译:pycdc工具的使用

六.扩展--通过翻译字节码得到源码

DASCTF2023 RE easyRE 这题使用python3.11解释器,由于版本过高,得到pyc字节码文件后无法反编译出python源码.

1.使用python3.11解释器调用dis解释出pyc文件的字节码

  1. import marshal
  2. import dis
  3. f=open(r'easyRE.pyc','rb')
  4. # 将pyc文件和该脚本放于同一文件夹内,或者自行指定绝对路径
  5. code=marshal.loads(f.read()[16:])
  6. print(dis.dis(code))
  7. f.close()

字节码:

2.使用ChatGpt翻译字节码得到源码(看文档生啃也可以)

ChatGpt翻译出的源码

  1. import random
  2. r = random.Random(322376503)
  3. pt = input('Enter your flag: ').encode()
  4. 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'
  5. buf = []
  6. for b in pt:
  7. buf.append(b ^ r.randint(0, 255))
  8. if bytes(buf) == ct:
  9. print('Correct!')
  10. else:
  11. assert False

3. pydisasm -F xasm PycFile.pyc>out.txt命令打印字节码

dis库打印时可能会有报错的情况,这时可以尝试这条命令

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号