本帖最后由 zaoshang123 于 2026-3-6 10:38 编辑
DiE 检查,是 Nuitka 单文件模式打包的 python 程序
用 ProcessMonitor 监控程序,发现它会把资源解压到 temp 文件夹
从这些 dll(pyd)的名字来看,crackme_hard.dll 最有可能是我们需要的。
用 ida 打开,从导出表里找到 run_code,这就是入口函数。
由于单文件模式每次解压的位置不同,调试 crackme_hard.dll 不方便,可以自己写一个 loader
#include <windows.h>
#include <stdio.h>
int main(int argc, char** argv)
{
HANDLE hDll = LoadLibraryA("crackme_hard.dll");
printf("%p\n", hDll);
typedef int(__stdcall * ENTRYFUNC)(int, char **);
ENTRYFUNC run_code = (ENTRYFUNC)GetProcAddress(hDll, "run_code");
run_code(argc, argv);
}
测试一下,没有问题
接下来不太好定位,搜索 "print" "write" 都找不到。最后在 AI 的帮助下,在 PyImport_ExecCodeModuleEx 下断点,发现它导入了 os, stat, collections.abc ... 之后, 来到了 sub_7FFA1CDAB340
在里面一步步跟进,里面的大部分 qword 全局变量是一个指针,指向一个 python 对象,其中这个对象偏移 +8 的位置表明了这个 python 对象的类型
字符串类型(PyUnicode_Type)偏移 +40 的位置是这个字符串的内容
根据 python 类型重命名这些全局变量,代码清晰多了
AI 对于 sub_7FFA1CDAB340 的解释:
这段代码是 Python 模块的初始化函数,用于在 C 层面动态创建 Python 模块,并定义其中的类和方法。它通过 Python/C API 构建了一个名为 CrackMeCore 的类,包含多个方法(如 __init__、_decrypt_char、verify 等),并将这些方法注册到模块的字典中。函数最后返回模块对象,供 Python 解释器使用。
观察上图的 606 行,sub_7FFD23297880 很有可能就是 CrackMeCore.verify 这个函数,在这里下断点。
先验证一下:把返回结果从 Py_FalseStruct 改为 Py_TrueStruct(就在 Py_FalseStruct 上面),输出 checksum mismatch,说明函数找对了,但是需要进一步找到验证的逻辑
在 AI 的帮助下,找到的验证逻辑为:先判断长度是否是 30
然后和正确的 flag 一个一个字符比较
正确的 flag 通过 CrackMeCore._get_char_at_position() 方法访问(第一个字符是'5')
输入的 flag 通过下标访问(第一个字符是'1')
接下来提取 flag。修改 python_object_subscript 的返回值,指向正确的 flag,输出就得到了答案
from idautils import cpu
cpu.rax = cpu.r13
b = ida_bytes.get_bytes(cpu.rax + 40, 1)
print(f'flag byte: {b}')
|