A DbgEng-based debugger and TitanEngine-compatible backend for x64dbg. The
playground target provides a small command-line debugger; the
DbgEngTitanEngine target builds the TitanEngine.dll compatibility shim
consumed by x64dbg.
The shim supports live x64 and x86 launch and attach sessions, x64dbg event
translation, short/long-INT3 and UD2 software breakpoints, DbgEng data/hardware
breakpoints, page-guard memory breakpoints, stepping, filtered/raw memory-read operations, full
x64 AVX/AVX-512 contexts, non-current thread selection, repeatable sessions,
and common process/thread controls. It also supports immutable x64/x86
user-minidump sessions with synthetic process/thread identities, captured
memory maps, contexts, modules, threads, stored exceptions, and repeatable
teardown. TTD .run sessions additionally support exact positions, forward
and reverse execution, trace exceptions, timeline changes, logical code/data
breakpoints, interruptible runs, and a navigable recorded-process-exit event
through the ordinary EXIT_PROCESS callback. RequestPause maps live sessions
to DbgEng's native interrupt and TTD sessions to cursor interruption; callers
observe the same pause callback without selecting either mechanism. Forward
run, step-into, and step-over use the ordinary TitanEngine exports; any x86
WOW64 transition workaround is owned by StepInto and controlled through the
engine option rather than a session capability. The replay-specific execution
ABI contains only ReplayRunBack and ReplayStepBack. TTD step-over is implemented
behind the ordinary TitanEngine StepOver export: the adapter discovers a
recorded call's return address and owns a current-thread temporary watchpoint,
so peer-thread executions are ignored without a replay-specific public
breakpoint flag. Single-step filters stale
current-position watchpoint notifications, and forward step cannot cross a
published process-exit boundary into sparse raw post-exit state. Event,
initialization, and explicitly opened process/thread handles
are tracked in an authoritative ownership registry. Page-guard rearming
suspends peer target threads during the hidden
single instruction so concurrent accesses cannot escape while the guard is
temporarily clear.
- Process launching and debugging
- Breakpoint management (set/clear)
- Execution control (run, step over, step into)
- Register inspection
- Memory reading with hex output
- Event-driven debugging with proper callback handling
The project uses CMake for building:
cmake -B build -A x64
cmake --build build --config Debug
cmake -B build32 -A Win32
cmake --build build32 --config DebugParent projects can set DBGENG_BUILD_TOOLS=OFF to build only the
DbgEngTitanEngine adapter. The adapter is always emitted as
DbgEng/TitanEngine.dll, matching x64dbg's engine layout.
Important: After building, copy the DbgEng DLLs beside the adapter (and to the root output directory when using the standalone tools):
copy dbgeng\*.dll build\Debug\DbgEng\
copy dbgeng\*.dll build\Debug\When the shim is loaded by x64dbg, x64dbg's root dbghelp.dll must match this
DbgEng distribution. Windows binds DbgEng to an already-loaded dbghelp.dll;
an older x64dbg copy causes LoadLibrary(dbgeng.dll) to fail with
ERROR_PROC_NOT_FOUND.
Two replay probes are built alongside the other targets:
build\Release\replay_probe.exe artifact.dmp
build\Release\shim_replay_probe.exe artifact.dmp
build\Release\shim_replay_probe.exe artifact.runThe first inventories the raw DbgEng dump session. The second validates the TitanEngine-compatible minidump or TTD boundary, including exact seek and forward/reverse movement for traces.
build\Debug\playground.exe <executable_path>Example:
build\Debug\playground.exe build\Debug\testapp.exeThe debugger supports the following commands:
runorr- Resume execution until next breakpoint or program terminationsto- Step over (execute one instruction, stepping over function calls)sti- Step into (execute one instruction, stepping into function calls)
bp 0xaddress- Set a breakpoint at the specified address- Example:
bp 0x140001234
- Example:
bc 0xaddress- Clear/remove a breakpoint at the specified address- Example:
bc 0x140001234
- Example:
regs- Display current register values- Shows common x64 registers: rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, r8-r15, rip
read 0xaddress size- Read memory at specified address- Example:
read 0x140001000 64 - Displays memory in hex format, 16 bytes per row
- Example:
helporh- Show available commandsquitorq- Exit the debugger
> build\Debug\playground.exe build\Debug\testapp.exe
Process created: testapp.exe (base: 0x0000000140000000)
Initial breakpoint hit at 0x00007fff900e07a0
Debugger started. Process created.
Type 'help' for available commands.
(dbg) bp 0x140001234
Breakpoint set at 0x0000000140001234
(dbg) run
Running...
Breakpoint hit at 0x0000000140001234
(dbg) regs
Registers:
rax = 0x0000000000000000
rbx = 0x0000000000000000
rcx = 0x0000000000000001
rdx = 0x0000000000000000
rsi = 0x0000000000000000
rdi = 0x0000000000000000
rbp = 0x0000000000000000
rsp = 0x000000000012ff40
r8 = 0x0000000000000000
r9 = 0x0000000000000000
r10 = 0x0000000000000000
r11 = 0x0000000000000000
r12 = 0x0000000000000000
r13 = 0x0000000000000000
r14 = 0x0000000000000000
r15 = 0x0000000000000000
rip = 0x0000000140001234
(dbg) read 0x140001234 32
0000000140001234: 48 89 5c 24 08 48 89 74 24 10 57 48 83 ec 20 48
0000000140001244: 8b da 48 8b f1 48 8b 0d 45 2f 00 00 48 85 c9 75
(dbg) sto
Single step completed at 0x0000000140001238
(dbg) bc 0x140001234
Breakpoint removed at 0x0000000140001234
(dbg) quit
The debugger is built using the following components:
- IDebugClient5 - Primary interface for session management (chosen for compatibility with deployed DbgEng versions)
- IDebugControl - Execution control and command processing
- IDebugDataSpaces - Memory access operations
- IDebugRegisters - Register read/write operations
- IDebugSymbols - Symbol resolution
- IDebugSystemObjects - Process/thread management
- DebugEventCallbacks - Handles debug events (breakpoints, exceptions, process events)
- Proper event callback implementation with appropriate return values
- Automatic detection of breakpoint hits, single steps, and exceptions
- Simple command parser with case-insensitive commands
- Address parsing supporting both
0xprefixed and plain hex addresses - Error handling for invalid commands and parameters
- Uses 64-bit addressing throughout for compatibility
- Memory reads display 16 bytes per row in hex format
- Proper error handling for invalid memory addresses
- Software breakpoints using
DEBUG_BREAKPOINT_CODE - Automatic breakpoint tracking and cleanup
- Support for multiple breakpoints
- Comprehensive HRESULT checking for all DbgEng API calls
- Meaningful error messages for common failure scenarios
- Graceful cleanup on errors and exit
- Single-threaded design following DbgEng requirements
- Proper event loop with
WaitForEvent()calls - Synchronous command execution
This is a simple prototype debugger with the following limitations:
- No symbol loading or symbolic breakpoints
- No disassembly display
- No stack trace functionality
- No multi-threading support
- No remote debugging capabilities
- The
playgroundUI is x64-oriented; the TitanEngine compatibility shim also supports x86 targets
- Microsoft DbgEng API (Windows Debugging Tools)
- Visual Studio 2022 or compatible C++ compiler
- CMake 3.15 or later
- Windows 10/11
src/playground/playground.cpp- Main debugger implementationsrc/testapp/testapp.cpp- Test application for debuggingdbgeng/- Required DbgEng DLLsCMakeLists.txt- Build configuration
- Ensure DbgEng DLLs are copied to the output directory
- Check that you're running on a supported Windows version
- Verify Visual C++ Redistributable is installed
- Ensure the address is valid and executable
- Check that the process is actually reaching that code path
- Verify the address format (use
0xprefix)
- Verify the address is valid and accessible
- Check that the process is still running
- Ensure the size parameter is reasonable (1-1024 bytes)