Nuitka 分析记录

Nuitka 分析记录

参考链接

Nuitka-reversing

goatmilkkk/nuitka-helper: Symbol Recovery Tool for Nuitka Binaries

Nuitka Analysis. Разбираем Nuitka и крякаем софт! | Сайт читов, скриптов и кодов для онлайн игр - YouGame.Biz

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

Nuitka/nuitka/build/static_src/HelpersConstantsBlob.c at 0af50dad14419f46105a121a39db133dd7a2792b · Nuitka/Nuitka

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;
	}
}
posted @ 2025-06-23 22:19  DirWangK  阅读(216)  评论(0)    收藏  举报