Zero-Dependency x64 Call Stack Unwinder & Micro-Debugger
Eulogy is an out-of-process, purely C++ based execution engine designed to perform deep forensic analysis on running x64 threads. It acts as a surgical micro-debugger, freezing a target process and manually reversing the mathematical stack operations (UWOP) to reconstruct the exact call chain.
It does not rely on heavy third-party disassemblers (like Capstone) or invasive DLL injections. Eulogy reads raw memory, parses the PE Exception Directory (.pdata), handles complex compiler optimizations (Chained Unwinds), and dumps the exact machine code bytes the CPU was executing at the time of suspension.
⚠️ DISCLAIMER: This project is provided strictly for educational purposes, defensive malware analysis, and reverse engineering research. Suspending active threads and reading volatile memory inherently carries the risk of causing target instability or deadlocks. The author (thyrn90) assumes no responsibility for unauthorized use or system crashes.
-
Zero-Dependency Hex Dumping: Eulogy extracts and prints the raw 15-byte x64 instructions (OpCodes) directly from the target's memory. This bypasses encryption/packers and provides immediate context without requiring external disassembler libraries.
-
Chained Unwind Navigation: Heavily optimized C++ libraries (like ucrtbase.dll) split their stack frames across multiple tables. Eulogy perfectly tracks UNW_FLAG_CHAININFO and RBP (Frame Pointers) to navigate these complex Microsoft CRT bottlenecks without crashing.
-
L1 Stack Caching (Zero Syscall Overhead): Instead of choking the CPU with constant Ring-3 to Ring-0 context switches (ReadProcessMemory), Eulogy implements a 4KB bulk-read caching mechanism with a Guard Page fallback, reading the stack directly from its own local memory at lightning speed.
-
O(log n) Binary Search: Locates the exact RUNTIME_FUNCTION entry within the .pdata directory in milliseconds, preventing O(n) iteration lag on massive executable files.
-
Strict RAII & ABI Alignment: Built with absolute respect for the Windows x64 ABI. Features alignas(16) on CPU contexts to prevent silent ERROR_NOACCESS API failures, and strictly manages thread handles to prevent zombie locks.
When Eulogy attaches to a target, it doesn't just list addresses—it tears through the Windows Kernel APIs, standard C++ libraries, and lands directly inside the target's proprietary code.
An active trace of a target compiled with MinGW.
Key Forensic Details in the Trace:
The Kernel Descent (Frames 0-1): The trace starts at ntdll!ZwReadFile, showing the exact moment the thread was interacting with the OS kernel.
Defeating the CRT (Frames 2-5): Eulogy successfully aligns the RBP register and tracks the chained unwind operations through ucrtbase.dll, a point where many amateur unwinders fail.
The Naked Payload (Frame 8): Eulogy reaches the stripped, undocumented function (subject!UnknownFunction). It dumps the raw execution bytes: b8 00 00 00 00 48 81 c4 70 02... (which translates to MOV EAX, 0 and ADD RSP, 270h—a standard function epilogue).
Eulogy requires no external package managers. It uses pure Windows APIs.
- Compile the Source: Using MinGW / GCC (Ensure C++17 standard is enabled):
g++ -std=c++17 -O2 main.cpp -o eulogy.exe -ldbghelp
(Note: dbghelp is only linked to resolve human-readable symbol names, not to perform the actual stack unwinding).
- Execute the Trace: Find your target's Process ID (PID) and pass it to Eulogy.
./eulogy.exe <Target_PID>
A professional tool acknowledges its boundaries. Eulogy is built for speed and stealth, which comes with inherent architectural trade-offs:
Header Stomping Vulnerability: Eulogy relies on VirtualQueryEx to locate the AllocationBase and subsequently parse the DOS/NT headers (MZ/PE). If the target malware utilizes aggressive Reflective DLL Injection or actively wipes its own headers from memory (Header Stomping), the .pdata directory cannot be located.
OS-Level Deadlocks: Eulogy uses SuspendThread to capture the CPU context. If the target thread is suspended while holding a critical OS lock (e.g., inside the Windows Heap Manager), it may cause a deadlock. This is an unavoidable reality of User-Mode (Ring-3) debugging.
Stripped Symbols: While Eulogy will perfectly calculate the RVA and dump the raw OpCodes, the function names (like UnknownFunction) will remain unresolved if the target does not have an accompanying PDB file.
This project is licensed under the MIT License - see the LICENSE file for details.
