{"id":51037162,"url":"https://github.com/praydog/ttdshim","last_synced_at":"2026-06-22T07:30:28.460Z","repository":{"id":365097228,"uuid":"1053330720","full_name":"praydog/ttdshim","owner":"praydog","description":"Instrumenting WinDBG's TTD (Time Travel Debugging)","archived":false,"fork":false,"pushed_at":"2026-06-15T20:32:17.000Z","size":200,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-15T22:17:27.154Z","etag":null,"topics":["cmkr","proxy-dll","reverse-engineering","time-travel-debugging","ttd","windbg","x86-64"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/praydog.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-09T09:52:06.000Z","updated_at":"2026-06-15T21:48:03.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/praydog/ttdshim","commit_stats":null,"previous_names":["praydog/ttdshim"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/praydog/ttdshim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/praydog%2Fttdshim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/praydog%2Fttdshim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/praydog%2Fttdshim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/praydog%2Fttdshim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/praydog","download_url":"https://codeload.github.com/praydog/ttdshim/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/praydog%2Fttdshim/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34639699,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cmkr","proxy-dll","reverse-engineering","time-travel-debugging","ttd","windbg","x86-64"],"created_at":"2026-06-22T07:30:26.379Z","updated_at":"2026-06-22T07:30:28.453Z","avatar_url":"https://github.com/praydog.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ttdshim\n\nA proxy (\"shim\") DLL for Microsoft's Time Travel Debugging recorder,\n`TTDRecordCPU.dll`. It is deployed in place of the original (which is renamed to\n`TTDRecordCPU_orig.dll`), re-exports the recorder's API, and forwards every\nexported function to the original — so to the rest of TTD it looks and behaves\nlike the genuine recorder.\n\nOn top of that pass-through it hooks into TTD's internals to change how recording\nbehaves. The main goal is to fix recording-fidelity bugs in TTD's instruction\nemulator: certain instruction encodings are emulated incorrectly, so the\nrecorded trace diverges from what the CPU actually executed. The bundled\n`exploit` target is a minimal proof-of-concept of one such divergence.\n\n## What it does\n\n- **DLL proxying / load order.** Loads `TTDRecordCPU_orig.dll`, unlinks the shim\n  from the PEB loader list, and rewrites the original module's PEB entry back to\n  `TTDRecordCPU.dll` so name-based lookups keep working. Every export in\n  `ttdshim.def` is a thin forwarder resolved via `GetProcAddress` on the\n  original (see `src/Main.cpp`).\n- **Symbol-driven hooking.** Resolves TTD's internal (non-exported) functions\n  from the module's PDB via the DIA SDK (kananlib), then installs inline/mid\n  hooks with safetyhook. Internal TTD types (`ThreadInfo`, `SmartContext`,\n  `X64EmulatorRegisters`, `Writer::Thread`, `INativeRecordVirtualCpu`,\n  `NtRuntime`, the x86 decoder / SCode structures) are reconstructed from\n  reverse engineering so the shim can call into and inspect live recorder state.\n- **Emulation-fidelity fix (the main point).** Hooks the x64 emulator's\n  `TraceLookup` and watches for the encodings TTD mis-emulates —\n  `xchg eax, r8d` (`41 90`) and `xchg rax, r8` (`49 90`). When seen, it rewrites\n  them in place to equivalent instruction sequences the emulator handles\n  correctly, then restores the original bytes, so the trace matches real\n  execution.\n- **Anti-anti-debugging.** Neutralizes common evasions so a target can still be\n  recorded: `NtSetInformationThread(ThreadHideFromDebugger)` is swallowed,\n  `NtSetInformationProcess` requests that install a NULL\n  `ProcessInstrumentationCallback` are blocked, and emulated syscalls are\n  filtered via a hook on TTD's `BeforeSyscall`. (An `int 3` /\n  `RtlDispatchException` skip path also exists but is currently disabled.)\n\n\u003e Status: this is an active reverse-engineering / research project, not a\n\u003e finished tool. Much of the per-instruction instrumentation\n\u003e (`src/InstructionInstrumentation.*`) is generated scaffolding, and several\n\u003e hook paths are commented out or experimental.\n\n## Building\n\n### Prerequisites\n- CMake 3.20 or later\n- Visual Studio 2022 (or compatible C++ compiler)\n- Windows SDK\n\n### Build Instructions\n\n1. **Using the build script (recommended):**\n   ```batch\n   build.bat\n   ```\n\n2. **Manual build:**\n   ```batch\n   mkdir build\n   cd build\n   cmake .. -G \"Visual Studio 17 2022\" -A x64\n   cmake --build . --config Release\n   ```\n\nThe resulting DLL will be located at `build\\Release\\ttdshim.dll`.\n\n## Project Structure\n\n- `Main.cpp` - Main DLL implementation with exported functions\n- `ttdshim.h` - Header file with function declarations\n- `ttdshim.def` - Module definition file specifying exports\n- `CMakeLists.txt` - CMake build configuration\n- `build.bat` - Build script for easy compilation\n\n## Usage\n\nDeploy by renaming Microsoft's original recorder to `TTDRecordCPU_orig.dll` and\ndropping this DLL in beside it as `TTDRecordCPU.dll`. On the first forwarded\ncall the shim loads the original, repairs the PEB, resolves symbols, and installs\nits hooks; from then on every export is forwarded to the original recorder while\nthe instrumentation in `src/Hooks.cpp` runs underneath. Behaviour is changed by\nediting those hooks, not the forwarders in `src/Main.cpp`.\n\n## Acknowledgements\n\n[@kmx00](https://github.com/kmx00) - Coming up with this idea in the first place, contributions, brainstorming, identifying that there was an emulation divergence when looking at a protected sample\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpraydog%2Fttdshim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpraydog%2Fttdshim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpraydog%2Fttdshim/lists"}