praydog/ttdshim

GitHub: praydog/ttdshim

ttdshim 是一个 WinDBG TTD 记录器的 DLL 代理垫片,通过挂钩内部机制修复指令模拟保真度缺陷并提供反反调试能力。

Stars: 2 | Forks: 0

# ttdshim 一个用于 Microsoft 时间旅行调试记录器(Time Travel Debugging recorder)的代理("垫片/shim")DLL, `TTDRecordCPU.dll`。它被部署在原始文件的位置(原始文件会被重命名为 `TTDRecordCPU_orig.dll`),重新导出记录器的 API,并将每个 导出的函数转发到原始文件——因此在 TTD 的其余部分看来,它的外观和行为 都与真正的记录器无异。 在这个直通(pass-through)层的基础上,它会挂钩(hook)到 TTD 的内部机制中,以改变记录的 行为。主要目标是修复 TTD 指令 模拟器中的记录保真度 bug:某些指令编码被错误地模拟,导致 记录的 trace 与 CPU 实际执行的结果产生偏差。附带的 `exploit` 目标就是此类偏差的一个最小概念验证。 ## 它的功能 - **DLL 代理 / 加载顺序。** 加载 `TTDRecordCPU_orig.dll`,将垫片 从 PEB 加载器列表中取消链接,并将原始模块的 PEB 条目重写回 `TTDRecordCPU.dll`,以便基于名称的查找能继续工作。`ttdshim.def` 中的每个导出都是一个精简的转发器,通过在 原始文件上调用 `GetProcAddress` 来解析(参见 `src/Main.cpp`)。 - **符号驱动的挂钩。** 通过 DIA SDK (kananlib) 从模块的 PDB 中解析 TTD 的内部(非导出)函数, 然后使用 safetyhook 安装内联/中间(inline/mid)挂钩。 内部 TTD 类型(`ThreadInfo`、`SmartContext`、 `X64EmulatorRegisters`、`Writer::Thread`、`INativeRecordVirtualCpu`、 `NtRuntime`、x86 解码器 / SCode 结构)均通过逆向工程重建, 以便垫片可以调用并检查实时的记录器状态。 - **模拟保真度修复(核心重点)。** 挂钩 x64 模拟器的 `TraceLookup` 并监视 TTD 模拟错误的编码—— `xchg eax, r8d` (`41 90`) 和 `xchg rax, r8` (`49 90`)。当发现这些指令时,会在原地将它们重写为模拟器可以 正确处理的等价指令序列,然后恢复 原始字节,从而使 trace 与实际 执行结果相匹配。 - **反反调试。** 中和常见的规避手段,以便目标仍然可以被 记录:吞掉 `NtSetInformationThread(ThreadHideFromDebugger)`, 阻止安装了 NULL `ProcessInstrumentationCallback` 的 `NtSetInformationProcess` 请求, 并通过挂钩 TTD 的 `BeforeSyscall` 来过滤模拟的 syscall。(也存在一个 `int 3` / `RtlDispatchException` 的跳过路径,但目前处于禁用状态。) ## 构建 ### 前置条件 - CMake 3.20 或更高版本 - Visual Studio 2022(或兼容的 C++ 编译器) - Windows SDK ### 构建说明 1. **使用构建脚本(推荐):** build.bat 2. **手动构建:** mkdir build cd build cmake .. -G "Visual Studio 17 2022" -A x64 cmake --build . --config Release 生成的 DLL 将位于 `build\Release\ttdshim.dll`。 ## 项目结构 - `Main.cpp` - 包含导出函数的主 DLL 实现 - `ttdshim.h` - 包含函数声明的头文件 - `ttdshim.def` - 指定导出的模块定义文件 - `CMakeLists.txt` - CMake 构建配置 - `build.bat` - 用于简化编译的构建脚本 ## 使用方法 通过将 Microsoft 的原始记录器重命名为 `TTDRecordCPU_orig.dll` 并 将此 DLL 放置在其旁边并命名为 `TTDRecordCPU.dll` 来进行部署。在第一次转发的 调用时,垫片会加载原始文件,修复 PEB,解析符号,并安装 其挂钩;从那时起,每个导出都会被转发到原始记录器,同时 `src/Hooks.cpp` 中的插桩(instrumentation)在底层运行。行为是通过 编辑这些挂钩来改变的,而不是 `src/Main.cpp` 中的转发器。 ## 致谢 [@kmx00](https://github.com/kmx00) - 首次提出这个想法,做出的贡献、头脑风暴,以及在分析受保护样本时发现了存在模拟偏差的问题
标签:Bash脚本, DOM解析, Windows, 云资产清单, 反调试, 逆向工程, 钩子