Nuitka 分析记录
Nuitka 分析记录
参考链接
goatmilkkk/nuitka-helper: Symbol Recovery Tool for Nuitka Binaries
Introduction 介绍
- Python-to-C Compiler Python 到 C 编译器
2 versions — Standard & Commercial
两个版本 — 标准版和商业版
Commercial version obfuscates strings & data files
商业版本混淆了字符串和数据文件
- Statically translates Python to C w/o adding or reducing features for maximum compatibility
将 Python 静态转换为 C,无需添加或减少功能,以实现最大兼容性
Code objects, stack frame etc. are preserved
代码对象、堆栈框架等被保留
Python byte code (i.e. co_code), however, gets erased
然而,Python 字节码(即 co_code )被删除
- Uses libpython and static C files of its own to execute in the same way as CPython does
使用 libpython 和其自身的静态 C 文件以与 CPython 相同的方式执行
Binary relies on python3XX.dll as a dependency
二进制依赖 python3XX.dll 作为依赖项
Nuitka & CPython library code gets embedded into the binary
Nuitka 和 CPython 库代码嵌入到二进制文件中
Problematic since it adds clutter to the decompiler output
有问题,因为它会使反编译器的输出变得混乱
--onefile Unpacking 拆包
We can find main by searching for the "NUITKA_ONEFILE_PARENT" string
我们可以通过搜索 “NUITKA_ONEFILE_PARENT” 字符串来找到main
| Packed Files 打包文件 | Compressed Resource w/ KAY File Header 带有 KAY 文件头的压缩资源 |
|---|---|
| Compression Algorithm 压缩算法 | Facebook’s ZSTD |
main
NUITKA_PRINT_TIMING("ONEFILE: Checking header for compression.");
char header[3];
readChunk(&header, sizeof(header));
if (header[0] != 'K' || header[1] != 'A') {
fatalErrorHeaderAttachedData();
}
NUITKA_PRINT_TIMING("ONEFILE: Header is OK.");
// The 'X' stands for no compression, 'Y' is compressed, handle that.
#if _NUITKA_ONEFILE_COMPRESSION_BOOL == 1
if (header[2] != 'Y') {
fatalErrorHeaderAttachedData();
}
initZSTD();
input.src = payload_current;
input.pos = 0;
// TODO: Ought to assert that this doesn't truncate anything.
input.size = (size_t)payload_size;
assert(payload_size > 0);
#else
initPayloadData
static void initPayloadData(void) {
initPayloadData2();
#if !defined(__APPLE__) && !defined(_WIN32)
const off_t size_end_offset = exe_file_mapped.file_size;
NUITKA_PRINT_TIMING("ONEFILE: Determining payload start position.");
assert(sizeof(payload_size) == sizeof(unsigned long long));
memcpy(&payload_size, payload_data + size_end_offset - sizeof(payload_size), sizeof(payload_size));
unsigned long long start_pos = size_end_offset - sizeof(payload_size) - payload_size;
payload_current += start_pos;
payload_data += start_pos;
#endif
}
static void initPayloadData2(void) {
HRSRC windows_resource = FindResource(NULL, MAKEINTRESOURCE(27), RT_RCDATA);
payload_data = (const unsigned char *)LockResource(LoadResource(NULL, windows_resource));
payload_current = payload_data;
payload_size = SizeofResource(NULL, windows_resource);
}
工具:
extremecoders-re/nuitka-extractor: Tool to extract nuitka compiled executables
unpackBlobConstants
global_constants
字符串'sentinel'定位
void createGlobalConstants(void)
{
_object *v0; // rbx
_object *v1; // rbx
_object *v2; // rbx
_object *v3; // rbx
__int64 v4; // rdx
_object *v5; // rax
if ( !_sentinel_value )
{
_sentinel_value = (_object *)PyCapsule_New(27LL, "sentinel", 0LL);
if ( !_sentinel_value )
wassert(L"_sentinel_value", L"__constants.cpp", 0x8Du);
Py_SysVersionInfo = (_object *)PySys_GetObject("version_info");
loadConstantsBlob(global_constants, s);
PySys_SetObject("executable", qword_1401660C8);
PySys_SetObject("prefix", qword_1401660D0);
PySys_SetObject("exec_prefix", qword_1401660D0);
PySys_SetObject("base_prefix", qword_1401660D0);
PySys_SetObject("base_exec_prefix", qword_1401660D0);
PyStructSequence_InitType(&Nuitka_VersionInfoType, &Nuitka_VersionInfoDesc);
Nuitka_dunder_compiled_value = (_object *)PyStructSequence_New(&Nuitka_VersionInfoType);
v0 = Nuitka_dunder_compiled_value;
if ( !Nuitka_dunder_compiled_value )
wassert(L"Nuitka_dunder_compiled_value != NULL", L"__constants.cpp", 0x60u);
//这里可得到Nuitka版本信息 0.8.2
//PyStructSequence_SET_ITEM(Nuitka_dunder_compiled_value, 0, PyInt_FromLong(%(nuitka_version_major)s));
v0[1].ob_type = (_typeobject *)PyLong_FromLong(0LL);//nuitka_version_major
v1 = Nuitka_dunder_compiled_value;
//PyStructSequence_SET_ITEM(Nuitka_dunder_compiled_value, 1, PyInt_FromLong(%(nuitka_version_minor)s));
v1[2].ob_refcnt = PyLong_FromLong(8LL);//nuitka_version_minor
v2 = Nuitka_dunder_compiled_value;
//PyStructSequence_SET_ITEM(Nuitka_dunder_compiled_value, 2, PyInt_FromLong(%(nuitka_version_micro)s));
v2[2].ob_type = (_typeobject *)PyLong_FromLong(2LL);//nuitka_version_micro
v3 = Nuitka_dunder_compiled_value;
v3[3].ob_refcnt = PyUnicode_FromString("release", v4);
………………
}
#ifdef __IDE_ONLY__
extern PyObject **global_constants;
// ()
#define const_tuple_empty global_constants[1]
// {}
#define const_dict_empty global_constants[2]
// 0
#define const_int_0 global_constants[3]
// 1
#define const_int_pos_1 global_constants[4]
// -1
#define const_int_neg_1 global_constants[5]
// 0.0
#define const_float_0_0 global_constants[6]
// -0.0
#define const_float_minus_0_0 global_constants[7]
// 1.0
#define const_float_1_0 global_constants[8]
// -1.0
#define const_float_minus_1_0 global_constants[9]
// ''
#define const_str_empty global_constants[10]
// b''
#define const_bytes_empty global_constants[10]
// '__module__'
#define const_str_plain___module__ global_constants[11]
// '__class__'
#define const_str_plain___class__ global_constants[12]
// '__class_getitem__'
#define const_str_plain___class_getitem__ global_constants[12]
// '__name__'
#define const_str_plain___name__ global_constants[13]
// '__main__'
#define const_str_plain___main__ global_constants[13]
// '__package__'
#define const_str_plain___package__ global_constants[14]
// '__metaclass__'
#define const_str_plain___metaclass__ global_constants[15]
// '__abstractmethods__'
#define const_str_plain___abstractmethods__ global_constants[15]
// '__dict__'
#define const_str_plain___dict__ global_constants[16]
// '__doc__'
#define const_str_plain___doc__ global_constants[17]
// '__file__'
#define const_str_plain___file__ global_constants[18]
// '__path__'
#define const_str_plain___path__ global_constants[19]
// '__enter__'
#define const_str_plain___enter__ global_constants[20]
// '__exit__'
#define const_str_plain___exit__ global_constants[21]
// '__builtins__'
#define const_str_plain___builtins__ global_constants[22]
// '__all__'
#define const_str_plain___all__ global_constants[23]
// '__cmp__'
#define const_str_plain___cmp__ global_constants[24]
// '__init__'
#define const_str_plain___init__ global_constants[24]
// '__iter__'
#define const_str_plain___iter__ global_constants[25]
// '__compiled__'
#define const_str_plain___compiled__ global_constants[26]
// 'inspect'
#define const_str_plain_inspect global_constants[27]
// 'compile'
#define const_str_plain_compile global_constants[28]
// 'getattr'
#define const_str_plain_getattr global_constants[28]
// 'range'
#define const_str_plain_range global_constants[29]
// 'open'
#define const_str_plain_open global_constants[30]
// 'close'
#define const_str_plain_close global_constants[30]
// 'throw'
#define const_str_plain_throw global_constants[30]
// 'throw'
#define const_str_plain_send global_constants[30]
// 'sum'
#define const_str_plain_sum global_constants[31]
// 'format'
#define const_str_plain_format global_constants[32]
// '__import__'
#define const_str_plain___import__ global_constants[33]
// 'bytearray'
#define const_str_plain_bytearray global_constants[34]
// 'staticmethod'
#define const_str_plain_staticmethod global_constants[35]
// 'classmethod'
#define const_str_plain_classmethod global_constants[36]
// 'name'
#define const_str_plain_name global_constants[37]
// 'globals'
#define const_str_plain_globals global_constants[38]
// 'locals'
#define const_str_plain_locals global_constants[39]
// 'fromlist'
#define const_str_plain_fromlist global_constants[40]
// 'level'
#define const_str_plain_level global_constants[41]
// 'read'
#define const_str_plain_read global_constants[42]
// '__newobj__'
#define const_str_plain___newobj__ global_constants[44]
// '.'
#define const_str_dot global_constants[45]
// '__getattr__'
#define const_str_plain___getattr__ global_constants[46]
// '__setattr__'
#define const_str_plain___setattr__ global_constants[47]
// '__delattr__'
#define const_str_plain___delattr__ global_constants[48]
// 'exc_type'
#define const_str_plain_exc_type global_constants[49]
// 'exc_value'
#define const_str_plain_exc_value global_constants[50]
// 'exc_traceback'
#define const_str_plain_exc_traceback global_constants[51]
// 'xrange'
#define const_str_plain_xrange global_constants[52]
// 'site'
#define const_str_plain_site global_constants[53]
// 'type'
#define const_str_plain_type global_constants[54]
// 'len'
#define const_str_plain_len global_constants[55]
// 'range'
#define const_str_plain_range global_constants[29]
// 'repr'
#define const_str_plain_repr global_constants[56]
// 'int'
#define const_str_plain_int global_constants[57]
// 'iter'
#define const_str_plain_iter global_constants[58]
// 'long'
#define const_str_plain_long global_constants[59]
// 'end'
#define const_str_plain_end global_constants[60]
// 'file'
#define const_str_plain_file global_constants[61]
// 'print'
#define const_str_plain_print global_constants[62]
// '__spec__'
#define const_str_plain___spec__ global_constants[63]
// '_initializing'
#define const_str_plain__initializing global_constants[64]
// parent
#define const_str_plain_parent global_constants[65]
// types
#define const_str_plain_types global_constants[66]
// '__loader__'
#define const_str_plain___loader__ global_constants[67]
// '__match_args__'
#define const_str_plain___match_args__ global_constants[67]
// '__args__'
#define const_str_plain___args__ global_constants[67]
[+]console dll inject success!
to ShowHexInputDialog
[#]offset:92320800
[-]base:00007FF7F16A0000
[#]consts[0]
[-]PyObject* 000001FBA0F00048
[-]ob_type* 00007FFF1D11A370
Type: tuple
[#]consts[1]
[-]PyObject* 000001FBA2ADEB38
[-]ob_type* 00007FFF1D10F1E0
Type: dict
[#]consts[2]
[-]PyObject* 00007FFF1D187C20
[-]ob_type* 00007FFF1D117C10
Type: int
int: 0
[#]consts[3]
[-]PyObject* 00007FFF1D187C40
[-]ob_type* 00007FFF1D117C10
Type: int
int: 1
[#]consts[4]
[-]PyObject* 00007FFF1D187C00
[-]ob_type* 00007FFF1D117C10
Type: int
int: -1
[#]consts[5]
[-]PyObject* 000001FBA0FAC6B0
[-]ob_type* 00007FFF1D1165F0
Type: float
float: 0.000000
[#]consts[6]
[-]PyObject* 000001FBA0FAC4D0
[-]ob_type* 00007FFF1D1165F0
Type: float
float: -0.000000
[#]consts[7]
[-]PyObject* 000001FBA0FAC6D0
[-]ob_type* 00007FFF1D1165F0
Type: float
float: 1.000000
[#]consts[8]
[-]PyObject* 000001FBA0FAC6F0
[-]ob_type* 00007FFF1D1165F0
Type: float
float: -1.000000
[#]consts[9]
[-]PyObject* 000001FBA0F35270
[-]ob_type* 00007FFF1D11A9B0
Type: str
str:
[#]consts[10]
[-]PyObject* 000001FBA0F001E0
[-]ob_type* 00007FFF1D10D9F0
Type: bytes
[#]consts[11]
[-]PyObject* 000001FBA0F04970
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __module__
[#]consts[12]
[-]PyObject* 000001FBA0F04530
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __class__
[#]consts[13]
[-]PyObject* 000001FBA0F048B0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __name__
[#]consts[14]
[-]PyObject* 000001FBA0F2FAB0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __package__
[#]consts[15]
[-]PyObject* 000001FBA2ADF5F0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __metaclass__
[#]consts[16]
[-]PyObject* 000001FBA0F052B0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __abstractmethods__
[#]consts[17]
[-]PyObject* 000001FBA0F049B0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __dict__
[#]consts[18]
[-]PyObject* 000001FBA0F045F0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __doc__
[#]consts[19]
[-]PyObject* 000001FBA0F5D2B0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __file__
[#]consts[20]
[-]PyObject* 000001FBA0F5E2F0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __path__
[#]consts[21]
[-]PyObject* 000001FBA0F1F730
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __enter__
[#]consts[22]
[-]PyObject* 000001FBA0F1F770
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __exit__
[#]consts[23]
[-]PyObject* 000001FBA0F66AF0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __builtins__
[#]consts[24]
[-]PyObject* 000001FBA0F66270
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __all__
[#]consts[25]
[-]PyObject* 000001FBA0F034B0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __init__
[#]consts[26]
[-]PyObject* 000001FBA2ADF630
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __cmp__
[#]consts[27]
[-]PyObject* 000001FBA0F03370
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __iter__
[#]consts[28]
[-]PyObject* 000001FBA2ADF670
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __compiled__
[#]consts[29]
[-]PyObject* 000001FBA0F38DB0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: inspect
[#]consts[30]
[-]PyObject* 000001FBA0F3AAF0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: compile
[#]consts[31]
[-]PyObject* 000001FBA0F43770
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: range
[#]consts[32]
[-]PyObject* 000001FBA0F7BC70
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: open
[#]consts[33]
[-]PyObject* 000001FBA0F431B0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: sum
[#]consts[34]
[-]PyObject* 000001FBA0F14E70
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: format
[#]consts[35]
[-]PyObject* 000001FBA0F3A8B0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __import__
[#]consts[36]
[-]PyObject* 000001FBA0F433F0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: bytearray
[#]consts[37]
[-]PyObject* 000001FBA0F43870
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: staticmethod
[#]consts[38]
[-]PyObject* 000001FBA0F43470
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: classmethod
[#]consts[39]
[-]PyObject* 000001FBA0F14570
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: keys
[#]consts[40]
[-]PyObject* 000001FBA0F38C30
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: name
[#]consts[41]
[-]PyObject* 000001FBA0F3ACB0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: globals
[#]consts[42]
[-]PyObject* 000001FBA0F3AEF0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: locals
[#]consts[43]
[-]PyObject* 000001FBA0F66330
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: fromlist
[#]consts[44]
[-]PyObject* 000001FBA0F61AF0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: level
[#]consts[45]
[-]PyObject* 000001FBA0F85830
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: read
[#]consts[46]
[-]PyObject* 000001FBA0F3AC70
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: getattr
[#]consts[47]
[-]PyObject* 000001FBA0F5E2B0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __cached__
[#]consts[48]
[-]PyObject* 000001FBA0F2FAF0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __loader__
[#]consts[49]
[-]PyObject* 000001FBA0F43070
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: print
[#]consts[50]
[-]PyObject* 000001FBA0F45670
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: end
[#]consts[51]
[-]PyObject* 000001FBA0F5ABB0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: file
[#]consts[52]
[-]PyObject* 000001FBA0F43430
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: bytes
[#]consts[53]
[-]PyObject* 000001FBA0F5DDF0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: .
[#]consts[54]
[-]PyObject* 000001FBA0F28A30
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: send
[#]consts[55]
[-]PyObject* 000001FBA0F28A70
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: throw
[#]consts[56]
[-]PyObject* 000001FBA0F1FCF0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: close
[#]consts[57]
[-]PyObject* 000001FBA2ADF6B0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: site
[#]consts[58]
[-]PyObject* 000001FBA0F43970
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: type
[#]consts[59]
[-]PyObject* 000001FBA0F3AEB0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: len
[#]consts[60]
[-]PyObject* 000001FBA0F430B0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: repr
[#]consts[61]
[-]PyObject* 000001FBA0F43670
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: int
[#]consts[62]
[-]PyObject* 000001FBA0F3AE70
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: iter
[#]consts[63]
[-]PyObject* 000001FBA0F2FB30
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __spec__
[#]consts[64]
[-]PyObject* 000001FBA0F5D530
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: _initializing
[#]consts[65]
[-]PyObject* 000001FBA0F5DE70
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: parent
[#]consts[66]
[-]PyObject* 000001FBA2ADF6F0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: types
[#]consts[67]
[-]PyObject* 000001FBA0F51F30
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __main__
[#]consts[68]
[-]PyObject* 000001FBA0F568F0
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: __class_getitem__
[#]consts[69]
[-]PyObject* 000001FBA2ADF730
[-]ob_type* 00007FFF1D11A9B0
Type: str
str: python.exe
modulecode_main_
通过字符串__main__ 引用定位Nuitka_MetaPathBasedLoaderEntry,进而得到modulecode__main__
.data:0000000140162AC0 ; Nuitka_MetaPathBasedLoaderEntry meta_path_loader_entries[2]
.data:0000000140162AC0 meta_path_loader_entries Nuitka_MetaPathBasedLoaderEntry <offset aMain, \
.data:0000000140162AC0 ; DATA XREF: setupMetaPathBasedLoader(void)+40↑o
.data:0000000140162AC0 ; setupMetaPathBasedLoader(void):loc_14000176E↑o ... ; "__main__" modulecode___main__(_object *,Nuitka_MetaPathBasedLoaderEntry const *)
.data:0000000140162AC0 offset ?modulecode___main__@@YAPEAU_object@@PEAU1@PEBUNuitka_MetaPathBasedLoaderEntry@@@Z,\
.data:0000000140162AC0 0, 0, 10h,
Nuitka_MetaPathBasedLoaderEntry
struct Nuitka_MetaPathBasedLoaderEntry {
// Full module name, including package name.
char const *name;
// Entry function if compiled module, otherwise NULL.
module_initfunc python_initfunc;
// For bytecode modules, start and size inside the constants blob.
int bytecode_index;
int bytecode_size;
// Flags: Indicators if this is compiled, bytecode or shared library.
int flags;
// For accelerated mode, we need to be able to tell where the module "__file__"
// lives, so we can resolve resource reader paths, not relative to the binary
// but to code location without loading it.
#if defined(_NUITKA_FREEZER_HAS_FILE_PATH)
#if defined _WIN32
wchar_t const *file_path;
#else
char const *file_path;
#endif
#endif
};
Nuitka_Function_New
创建python c_code object,后续CALL_FUNCTION_xxx 调用
// Make a function with context.
#if PYTHON_VERSION < 0x300
extern struct Nuitka_FunctionObject *Nuitka_Function_New(function_impl_code c_code, PyObject *name,
PyCodeObject *code_object, PyObject *defaults,
PyObject *module, PyObject *doc,
struct Nuitka_CellObject **closure, Py_ssize_t closure_given);
#else
extern struct Nuitka_FunctionObject *Nuitka_Function_New(function_impl_code c_code, PyObject *name, PyObject *qualname,
PyCodeObject *code_object, PyObject *defaults,
PyObject *kw_defaults, PyObject *annotations, PyObject *module,
PyObject *doc, struct Nuitka_CellObject **closure,
Py_ssize_t closure_given);
#endif
_MAKE_COMPILED_FRAME(旧版本MAKE_FRAME)
主要用于存储当前行号,有助于调试。
PyCode_New ==> 定位makeCodeObject
返回值交叉引用定位_MAKE_COMPILED_FRAME
V2.8rc9
static struct Nuitka_FrameObject *_MAKE_COMPILED_FRAME(PyCodeObject *code, PyObject *module, PyObject *f_locals,
Py_ssize_t locals_size) {
V0.8.2
static struct Nuitka_FrameObject *MAKE_FRAME(PyCodeObject *code, PyObject *module, bool is_module,
Py_ssize_t locals_size)
CALL_FUNCTION_xxx
通过字符串takes exactly one argument 定位CALL_FUNCTION_xxx
也可通过compiled_function 定位Nuitka_Function_Type 进而定位CALL_FUNCTION_xxx
.data:0000000140163050 struct _typeobject Nuitka_Function_Type _typeobject <<<1, 0>, 0>, offset aCompiledFuncti, 0D0h, 8, \
.data:0000000140163050 ; DATA XREF: Nuitka_GC_NewVar:loc_14000849C↑o
.data:0000000140163050 ; Nuitka_Function_Check↑o ...
.data:0000000140163050 offset Nuitka_Function_tp_dealloc, 0, 0, 0, 0, \ ; "compiled_function"
.data:0000000140163050 offset Nuitka_Function_tp_repr, 0, 0, 0, \
.data:0000000140163050 offset Nuitka_Function_tp_hash, \
.data:0000000140163050 offset Nuitka_Function_tp_call, 0, 0, 0, 0, 44000h, 0, \
.data:0000000140163050 offset Nuitka_Function_tp_traverse, 0, 0, 80h, 0, 0, \
.data:0000000140163050 offset Nuitka_Function_methods, 0, \
.data:0000000140163050 offset Nuitka_Function_getset, 0, 0, \
.data:0000000140163050 offset Nuitka_Function_descr_get, 0, 78h, 0, 0, 0, 0, 0, \
.data:0000000140163050 0, 0, 0, 0, 0, 0, 0, 0>
other
交叉引用字符串 __main__ ,可定位到unpackBlobConstants,可通过dump参数PyObject **output获得常量信息。
不要去解析.bytecode 的常量对象
#include "pch.h"
#include <stdio.h>
#include <Python.h>
#pragma comment(lib,"python37.lib")
FILE* LogStream = 0;
int myprintf(char const* const _Format, ...) {
if (!LogStream) {
fopen_s(&LogStream, "py_consts.log", "w");
}
va_list _ArgList;
__crt_va_start(_ArgList, _Format);
auto _Result = _vfprintf_l(stdout, _Format, NULL, _ArgList);
if (LogStream) {
_Result = _vfprintf_l(LogStream, _Format, NULL, _ArgList);
fflush(LogStream);
}
__crt_va_end(_ArgList);
return _Result;
}
void ParsePyType(PyObject* obj) {
if (PyLong_Check(obj)) {
long val = PyLong_AsLong(obj);
myprintf("int: %ld\n", val);
}
else if (PyBytes_Check(obj)) {
const char* s = PyBytes_AsString(obj);
myprintf("bytes: %s\n", s);
}
else if (PyByteArray_Check(obj)) {
const char* s = PyByteArray_AsString(obj);
myprintf("bytearray: %s\n", s);
}
else if (PyUnicode_Check(obj)) {
const char* s = PyUnicode_AsUTF8(obj);
myprintf("str: %s\n", s);
}
else if (PyFloat_Check(obj)) {
double d = PyFloat_AsDouble(obj);
myprintf("float: %lf\n", d);
}
else if (PyTuple_Check(obj)) {
Py_ssize_t size = PyTuple_Size(obj);
for (Py_ssize_t i = 0; i < size; i++) {
PyObject* item = PyTuple_GetItem(obj, i); // 值是borrowed reference
myprintf("tuple[%lld]==>", i);
ParsePyType(item);
Py_DECREF(item);
}
}
else if (PyDict_Check(obj)) {
PyObject* key, * value;
Py_ssize_t pos = 0;
while (PyDict_Next(obj, &pos, &key, &value)) {
myprintf("key:");
ParsePyType(key);
myprintf("value:");
ParsePyType(value);
Py_DECREF(key);
Py_DECREF(value);
}
}
else if (PySet_Check(obj)) {
PyObject* iter = PyObject_GetIter(obj);
PyObject* item;
int i = 0;
while ((item = PyIter_Next(iter))) {
myprintf("set[%d]==>", i++);
ParsePyType(item);
Py_DECREF(item);
}
Py_DECREF(iter);
}
else if (PyList_Check(obj)) {
Py_ssize_t size = PyList_Size(obj);
for (Py_ssize_t i = 0; i < size; i++) {
PyObject* item = PyList_GetItem(obj, i); // borrowed
myprintf("list[%lld]==>", i);
ParsePyType(item);
//const char* s = PyUnicode_AsUTF8(PyObject_Str(item));
//mylog("List item %zd: %s\n", i, s);
}
}
}
void PrintType(PyObject* obj) {
myprintf("[-]PyObject* %p\n", obj);
if (obj->ob_type) {
myprintf("[-]ob_type* %p\n", obj->ob_type);
myprintf("Type: %s\n", obj->ob_type->tp_name);
ParsePyType(obj);
}
}
//int mod_consts_offset = 0x166B10;//test
void do_test(long long offset) {
if (!hmod) {
hmod = GetModuleHandleA(0);
}
myprintf("[-]base:%p\n", (void*)hmod);
PyObject** array = (PyObject**)((char*)hmod + offset);
int i = 0;
try
{
while (*array) {
//todo:check *array addr
if (((uint64_t)*array & 0xffff) == 0 || ((uint64_t)*array & 0xffff000000000000) != 0) {
myprintf("[!]error PyObject*:%p\n", *array);
break;
}
myprintf("\n\n[#]consts[%d]\n", i++);
PrintType(*array);
array++;
}
}
catch (const std::exception&)
{
myprintf("error!");
}
if (LogStream) {
fclose(LogStream);
LogStream = 0;
}
}

浙公网安备 33010602011771号