Cpython逆向
Python代碼轉換為C代碼的時候,將會大大增加框架代碼量。
1、正向py->c
先有正向,再有逆向
pip install cython
寫一個簡單的pyx文件
.pyx 文件是由 Cython 編程語言 "編寫" 而成的 Python 擴展模塊源代碼文件
print("hello")
寫一個 setup.py文件
from distutils.core import setup
from Cython.Build import cythonizesetup(ext_modules = cythonize("test.pyx")
)
使用命令開始編譯
python setup.py build_ext --inplace
生成如下文件
打開test.c發現有幾千行代碼
單純的一行python代碼,生成為c代碼就幾千行
調用so文件
2、逆向分析
2.1 字符串類型
_Pyx_CreateStringTabAndInitStrings
全局字符串賦值一般在_Pyx_CreateStringTabAndInitStrings中,該函數中使用的字符串定義數組形如:
typedef struct{
PyObject**p;
constchar*s;
constPy_ssize_t n;
constchar* encoding;
constchar is_unicode;
constchar is_str;
constchar intern;
} __Pyx_StringTabEntry;
而字符串是通過__Pyx_StringTabEntry的數組進行初始化的,也就是說當我們在該函數中看到以下偽代碼時:
v8 = _mm_unpacklo_epi64(&qword_28A98, "AttributeError");
v9 = 15LL;
v10 = 0LL;
v11 = 0x100;
v12 = 1;
就代表這是一個{&qword_28A98, "AttributeError", 15, 0, 1, 0, 1}的__Pyx_StringTabEntry,也就是說qword_28A98中將要初始化一個內容是"AttributeError"的字符串對象的地址,在后續調用中,調用到AttributeError字符串的地方都會用&qword_28A98指代
2.2 整數類型
_pyx_pymod_exec_chal
qword_29170 = PyLong_FromLong(113LL, v9, v244, v245);
if ( qword_29170 )
qword_29170中將存儲一個值為113的整數類型的Python對象。
qword_29600 = PyLong_FromString("2654435769", 0LL, 0LL);
if ( qword_29600 )
大數會用PyLong_FromString函數來初始化,這里qword_29600中將存儲一個值為2654435769的整數類型的Python對象,后續用到2654435769的地方將使用qword_29600。
2.3 import寫法
v539 = _Pyx_ImportDottedModule_constprop_0(random);
if ( PyDict_SetItem(_pyx_mstate_global_static, random, v539) < 0 )
{
導入``random``模塊,同``import random
3、實戰分析
這里提供一道自己出的題目,采用了RC4加密,流程很簡單。
讓我們開干
把提供的so文件拖進IDA中
而且這個函數 _Pyx_CreateStringTabAndInitStrings() 非常大,不能反編譯
目前不知道這個函數的加密,我們先打印其相關的屬性,看看能不能找到蛛絲馬跡
import test
dir(test)
發現是RC4加密,這樣邏輯就清晰了
所以現在的目標是獲得RC4的秘鑰和密文咯,假設RC4沒有魔改
剛才我們在函數_Pyx_CreateStringTabAndInitStrings 找到了非常類似密文的值
9d7422eabf8baf369c09121f02e940099d9c6b538d88e30aac08
但是沒有找到 秘鑰,說明秘鑰可能就不是字符串,而是byte類型!
我們先搜索RC4相關函數
發現代碼非常多,暫時先不去分析RC4算法
看看哪里調用了我們的RC4算法
函數:_pyx_pymod_exec_test
{width=
但是byte類型怎么初始化呢?
我們編寫一個demo,然后反編譯去查看初始化方式即可
demo.pyx
key = b'mykekekeke'
en_flag = b'12312312312312'
demo_setup.pyx
from distutils.core import setup
from Cython.Build import cythonizesetup(ext_modules = cythonize("demo.pyx")
)
運行命令
python demo_setup.py build_ext --inplace
先看看c文件
還是很清晰的,直接IDA分析so文件
發現byte類型也存儲在函數_Pyx_CreateStringTabAndInitStrings
所以我們再翻閱一下,成功找到類似key的代碼
DASCTF{cpython_is_so_easy}
4、參考
Cython 二進制庫逆向分析全面指南
https://mp.weixin.qq.com/s/2mjjfuEwSDfMB5ssAQDwKQ