社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

实战分析Cpython逆向

蚁景网络安全 • 10 月前 • 269 次点击  


Cpython逆向

Python代码转换为C代码的时候,将会大大增加框架代码量。

公众号回复 RE 获取 Reverse-chal.zip

1、正向py->c

先有正向,再有逆向

pip install cython

写一个简单的pyx文件

.pyx 文件是由 Cython 编程语言 "编写" 而成的 Python 扩展模块源代码文件

print("hello")

写一个 setup.py文件

from distutils.core import setupfrom 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;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 testdir(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 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}

4、参考

Cython 二进制库逆向分析全面指南

https://mp.weixin.qq.com/s/2mjjfuEwSDfMB5ssAQDwKQ

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/175328
 
269 次点击