游戏名为Terminus Zombie Survivors, 使用pygame游戏引擎制作(python37)

  1. 游戏中的数据Cheat Engine无法搜索, 因为每次数据变动都会重新分配内存, 没有固定地址
  2. 语言包解压, 用关键字搜索游戏文件夹, 无法搜索到, 搜索游戏进程可以搜索到, 数据应该被压缩
  3. 主资源文件改名再运行, 关键字还是可以搜索到, 说明核心脚本在其他位置
  4. 检查主exe文件, 发现尾部有压缩数据
  5. 跟踪数据读取过程找到 PyMarshal_ReadObjectFromString
  6. 对PyMarshal_ReadObjectFromString Hook然后提起数据
@file.python37.dll#PyMarshal_ReadObjectFromString

$dat = $Param1;
$size = $Param2;

LogFileFormat("V:\\python.log", "%6d size: %6d\r\n", $RunId, $size);
OutputString("%6d size: %6d\r\n", $RunId, $size);

$filename = "V:\\pythonHook\\" + $RunId + "_" + $size + ".dat";
WriteFile($filename, 0, $dat, $size);
  1. 提取后的数据并不完整, 只有部分脚本, 找到其他函数 PyImport_ExecCodeModuleObject, PyEval_EvalCodeWithName等都不合适
  2. 在PyMarshal_ReadObjectFromString 调用的一个核心解释函数, 在这个函数Hook
@file.python37.dll#0x20186EED

$class = $ecx
$start = ReadMem($class+0x0c, 4);
$end = ReadMem($class+0x10, 4);

$dat = $start;
$size = $end-$start;

LogFileFormat("V:\\python.log", "%6d size: %6d\r\n", $RunId, $size);
OutputString("%6d size: %6d\r\n", $RunId, $size);

$filename = "V:\\pythonHook\\" + $RunId + "_" + $size + ".dat";
WriteFile($filename, 0, $dat, $size);
  1. 脚本基本提取完成, 600多个文件左右, 格式为pyc
  2. 安装python3.7 安装uncompyle6
    python3.7必须使用安装版本, 并安装上pip, 安装uncompyle6时就会自动下载安装依赖库
    uncompyle6 无法直接py文件使用, 必须使用库的安装方式并使用, 另外无法对整个文件夹反编译
  3. Hook提取的文件为pyc格式, 但是没有包含头, 需要从其他文件复制一个头过去(16byte)
  4. 找到需要修改的pyc文件反编译, uncompyle6参数-a可以看到指令, 但是没有16进制代码, 可以查看表 python3.x 虚拟机指令表
  5. 固化修改可以修改dll的代码 20186EED
20186EED    E87EEFFFFF      call    20185E70
20186EF2    8BF0            mov     esi, eax
20186EF4    85F6            test    esi, esi
修改
20186EED   /E9F8690300      jmp     201BD8EA

201BD8E4  - FF25C0E31B20    jmp     dword ptr [201BE3C0]
            000000000000
修改
201BD8E4  - FF25C0E31B20    jmp     dword ptr [201BE3C0]             
201BD8EA    EB0A            jmp     201BD8F6
201BD8EC    E87F85FCFF      call    20185E70
201BD8F1  ^ E9FC95FCFF      jmp     20186EF2
201BD8F6    8B4110          mov     eax, dword ptr [ecx+10]
201BD8F9    8B510C          mov     edx, dword ptr [ecx+0C]
201BD8FC    2BC2            sub     eax, edx
201BD8FE    3D00AE0000      cmp     eax, 0AE00
201BD903  ^ 75E7            jnz     201BD8EC
201BD905    81C29B290000    add     edx, 299B
201BD90B    813A64036E02    cmp     dword ptr [edx], 26E0364
201BD911  ^ 75D9            jnz     201BD8EC
201BD913    C6420503        mov     byte ptr [edx+05], 03
201BD917    C64264C8        mov     byte ptr [edx+64], 0C8
201BD91B    90              nop
201BD91C  ^ EBCE            jmp     201BD8EC