Python程式碼轉換為C程式碼的時候,將會大大增加框架程式碼量。
基礎教程 | Cython 官方文件中文版(gitbooks.io)
1、正向py->c
先有正向,再有逆向
pip install cython
寫一個簡單的pyx檔案
.pyx 檔案是由 Cython 程式語言 "編寫" 而成的 Python 擴充套件模組原始碼檔案
print("hello")
寫一個 setup.py檔案
from distutils.core import setup
from Cython.Build import cythonize
setup(
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;
const char *s;
const Py_ssize_t n;
const char* encoding;
const char is_unicode;
const char is_str;
const char 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
指代
【----幫助網安學習,以下所有學習資料免費領!加vx:dctintin,備註 “部落格園” 獲取!】
① 網安學習成長路徑思維導圖
② 60+網安經典常用工具包
③ 100+SRC漏洞分析報告
④ 150+網安攻防實戰技術電子書
⑤ 最權威CISSP 認證考試指南+題庫
⑥ 超1800頁CTF實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP客戶端安全檢測指南(安卓+IOS)
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
但是byte型別怎麼初始化呢?
我們編寫一個demo,然後反編譯去檢視初始化方式即可
demo.pyx
key = b'mykekekeke'
en_flag = b'12312312312312'
demo_setup.pyx
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("demo.pyx")
)
執行命令
python demo_setup.py build_ext --inplace
先看看c檔案
還是很清晰的,直接IDA分析so檔案
發現byte型別也儲存在函式_Pyx_CreateStringTabAndInitStrings
所以我們再翻閱一下,成功找到類似key的程式碼
DASCTF{cpython_is_so_easy}
更多網安技能的線上實操練習,請點選這裡>>