我试图对使用Python附带的“冻结”或“ pfreeze”实用程序编译的EXE进行反向工程(不要与“ cx_freeze”混淆)。 EXE内有一个名为PyImport_FrozenModules的内存阵列。程序启动时,该数组将填充程序的字节码(aka .pyo / .pyc文件)。我已经对此进行了几个月的研究,但现在我处于停滞状态。我需要找到一种从该数组中提取字节码的方法。该程序最初连接到服务器,因此一旦执行EXE,它将在崩溃前运行约10-20秒。要延长10-20秒,我需要暂停程序(使用“ Process Explorer”很容易做到)

我需要帮助的实际上是转储PyImport_FrozenModules,因此我可以获取.pyc并从那里继续。

我已经可以到达它:
链接:http://gyazo.com/83bcde5240df7fb9ec34e7e3de7699ba

作者在ollydbg这样的调试器中加载exe,找到导入行,然后将其设置为NOP'S。
有人说我必须为此编写脚本,而其他人则说这比我想象的要容易。我只是不知道从哪里开始。

任何帮助都将受到赞赏。谢谢。

评论

我了解到您可以在“所有名称”中轻松找到功能。还要在哪里,如何以及何时计算不同版本的python的python幻数?

#1 楼

在这种情况下,应该这样做。

步骤1:将可执行文件加载到Ollydbg之类的调试器中。

步骤2:在内存转储窗口中,导航至PyImport_FrozenModules通过按Ctrl + G

步骤3:PyImport_FrozenModules是一个指针,该指针已初始化为指向struct _frozen记录的数组。请按照dump中的指针操作。

步骤4:现在您处于一个_frozen结构数组的位置。此结构定义为

struct _frozen {
    char *name;
    unsigned char *code;
    int size;
};


上述数组由其所有成员均为null的结构终止。

步骤5:在上述结构中,第一个成员是指向冻结模块名称的指针,第二个成员是指向模块字节码的指针。 (这是您正在寻找的东西)。最后一个成员将为您提供字节码的大小(以字节为单位)。使用大小将字节码转储到文件中。

步骤6:刚转出的字节码不包含pyc文件的魔术头值(对于python 2.7,这是03 F3 0D 0A,后跟4个字节的时间戳)
添加标头,现在文件应该是可反编译的。

要使上述过程自动化,您也可以编写一个脚本。


UPDATE

这是一个PyCommand(免疫调试器)脚本)以转储冻结的模块。加载所有冻结的模块后,需要运行脚本。为此,您可以在功能PyImport_ImportFrozenModule()上设置断点,以便可以在每个冻结的模块加载时对其进行跟踪。如果您是Immunity Debugger的新手,请参见此内容。
import immlib

DESC = 'PyCommand to dump frozen python modules'
PYTHONMAGIC = '\x03\xF3\x0D\x0A\x00\x00\x00\x00' # Change this value according to the version of python used. The value given here is for Python 2.7

'''
Run this pycommand when all frozen modules are loaded.
This will dump each frozen module in a .pyc file in 
immunity debugger installation directory
'''

def main(args):
    imm = immlib.Debugger()
    addr = imm.getAddress('PyImport_FrozenModules')
    structAddr = imm.readLong(addr)

    while True:
        ptrToName = imm.readLong(structAddr)
        ptrToCode = imm.readLong(structAddr + 4)
        sizeOfCode = imm.readLong(structAddr + 8)
        structAddr += 12

        # The array is terminated by a structure whose members are null
        if ptrToName == 0 and ptrToCode == 0 and sizeOfCode == 0:
            break

        if sizeOfCode > 0 and sizeOfCode < 2147483647:            
            moduleName = imm.readString(ptrToName)
            moduleCode = imm.readMemory(ptrToCode, sizeOfCode)

            # You can change the output path here
            open(moduleName + '.pyc', 'wb').write(PYTHONMAGIC + moduleCode) 

    return '[*] Frozen modules dumped'


转储冻结的模块后,请对生成的pyc文件使用反编译器。您可以为此使用Easy Python Decompiler。

评论


非常感谢你的答复。我只是停留在“ struct_frozen”数组上。另外,当您说“将字节码转储到文件中”时,我不确定您的意思。谢谢。

– ThatOneGuy
2014年7月15日在16:13



@ThatOneGuy我的意思是在Ollydbg内存转储窗口中,选择包含字节码的范围,然后右键单击->备份->将数据保存到文件。这样,您可以转储字节码。

– 0xec
2014年7月15日在16:24



我被困在这,我的坏。告诉我这是否正确:我将在Dissasembler gyazo.com/f9e8c1db5bd63b314658cc901792a184中找到此行,然后右键单击并单击“跟随转储”,然后从那里继续。那是对的吗?我为他的新手和紧张感到抱歉。

– ThatOneGuy
2014年7月15日在16:43



例如,我将右键单击并单击“跟随转储”,然后从转储中复制字节,并且仅获得十六进制值,如:00401299 A1 C4 20 40 00

– ThatOneGuy
14年7月15日在17:08

@ThatOneGuy您在评论中发布的图像不正确。您需要在内存转储窗口中关注PyImport_FrozenModules

– 0xec
2014年7月15日在17:17