模块导入,大整数,大浮点数等
Cython程序分析_3
先把上次留下来的疑问给解决了。
后面不无脑复制太多C文件代码了,直接提取纲要,反正html注释里面代码给的很详细
代码1
1 | def func_ImportModule(): |
func_ImportModule()
import base64
1 | __pyx_t_1 = __Pyx_Import(__pyx_n_s_base64, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error) |
这次函数并没有被内联。不过即使内联了,也可以关注PyImport_ImportModuleLevelObject()
或者PyObject_CallFunctionObjArgs()
函数。
1 | // func_ImportModule() |
b64obj = base64.b64encode("testbase64".encode())
1 | // 纲要 |
IDA中
1 |
|
print(b64obj)
1 | __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_v_b64obj); if (unlikely(!__pyx_t_1)) |
1 | v14 = (*base64_b64encode_cp)-- == 1; |
print(type(b64obj))
1 | __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, ((PyObject *)Py_TYPE(__pyx_v_b64obj))) |
1 | // Py_TYPE() |
这样我们便能知道Py_TYPE()
的偏移是+8。
import hashlib
1 | __pyx_t_1 = __Pyx_Import(__pyx_n_s_hashlib, 0, 0) |
1 | v14 = (*v18)-- == 1i64; |
md5obj = hashlib.md5()
和上面base64.b64encode(xxx)
其实一样,不过那个是强制传入字节码来构建对象,这个可以后面再update()
上去。
1 | __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_hashlib, __pyx_n_s_md5); |
IDA中
1 | v3 = (_QWORD *)mod_hashlib; |
md5obj.update("testmd5".encode())
1 | __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_md5obj, __pyx_n_s_update); |
IDA中
1 | v14 = (*v4)-- == 1; |
print(md5obj.hexdigest())
1 | // md5obj.hexdigest |
1 | v14 = (*v4)-- == 1; |
func_BigInteger()
bigint_1 = .....(一个很大的数字)
1 | __Pyx_INCREF(__pyx_int_123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789); |
而__pyx_int_一个大数
的初始化则在InitGlobals()
中实现。当然此函数被内联了。
1 | int_verylong = PyLong_FromString(a12345678912345, 0i64, 0i64) |
调用了PyLong_FromString()
方法。所以说这个大数字会被搞成字符串存储。
1 | .data:000000018000A180 a12345678912345 db '12345678912345678912345678912345678912345678912345678912345678912' |
print(bigint_1)
1 | __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_v_bigint_1); |
IDA
1 | v1 = glob_func_print; |
print(bigint_1 * 2)
1 | __pyx_t_1 = PyNumber_Multiply(__pyx_v_bigint_1, __pyx_int_2); |
IDA
1 | v6 = (*v3)-- == 1i64; |
func_BigFloat()
高估了python的浮点精度,发现实际上也就是一般的IEEE浮点精度。
bigfloat = 1111111111111111111112222222222222222222222222222222222222222222222223333333333333333333333333333.9
1 | __pyx_v_bigfloat = 1111111111111111111112222222222222222222222222222222222222222222222223333333333333333333333333333.9; |
IDA中
这是一个固定数据。
1 | .rdata:0000000180007548 qword_180007548 dq 53E0A55DA8B14737h ; DATA XREF: sub_1800056C0+F↑r |
print(bigfloat)
1 | __pyx_t_1 = PyFloat_FromDouble(__pyx_v_bigfloat); |
1 | v0 = PyFloat_FromDouble(1.111111111111111e96); |
代码2
这个比较激进了。
python语法糖,算术表达式,转义字符串,元组,字典,集合
1 | def test3_2(): |
方便起见,直接在IDA函数里面注释,不逐行拆开来分析了。
test3_2()
1 | // 简化版 |
补充
1 |
|
并没有给予任何线索。
IDA中
1 | // write access to const memory has been detected, the output may be wrong! |
func_Calculation(input)
1 | // 简化 |
PyXXX_AddObjC()
函数我在博客2里面分析复数的时候遇到过。
1 | // write access to const memory has been detected, the output may be wrong! |
func_Str()
1 | __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_print, __pyx_tuple_, NULL); |
1 | // write access to const memory has been detected, the output may be wrong! |
字符串是'Ru\nnoob'
,已经被转义了,然后被print()
函数调用。
func_reverseWords()
1 | +024: inputWords = input.split(" ") |
1 | // write access to const memory has been detected, the output may be wrong! |
算了就到这里吧。元组啥的下次再看。
补充
转义字符串
1 | def f1(): |
C文件中
1 | static const char __pyx_k_Ru_noob[] = "Ru\nnoob"; |
这样确实证明了是会提前转义的。
二进制文件中
1 | .rdata:00000001800053F0 aRuNoob db 'Ru',0Ah ; DATA XREF: .data:00000001800077C0↓o |
- 本文作者: Taardis
- 本文链接: https://taardisaa.github.io/2022/01/27/Cython Reverse 3/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!