The Embedded ELF Debugger
The Embedded ELF Debugger (e2dbg) is the implementation of a new concept of debugger that run inside the process to be debugged instead of being an external entity accessing from the outside the target address space. Instead of using system-specific API such as ptrace, the debugger is linked into a library that is getting injected in a process using the LD_PRELOAD environment variable. This makes e2dbg very efficient as it does not need context switching for inspecting the target process. The ERESI debugger can also be scripted in the same conditions as a complete ERESI interpreter is embedded into the debugger.
The main features of the Embedded ELF debugger are :
- Debugging on dynamic ELF binaries without using ptrace
- Runtime injection of software extension developed in C language.
- Runtime static and extern functions redirection.
- Breakpoints and stepping using the sigaction syscall.
- Possibility of registers reading and writing on such events.
- Instruction tracing until next event.
- Runtime access to the linkmap linked list of the runtime linker.
- Support for debugging of multithread processes.
- Backtracing capabilities including on multithread processes.
- Innovative '''unintrusive debugging''' technique : Allocation proxying
Allocation proxying is a technique that allow the embedded ELF debugger to run with its own dynamic memory allocator in the debuggee process. Thus the debugger can allocate memory dynamically without interfering with the real heap of the debuggee process, opening the door to debugging of heap related bugs. This feature is not a memory protection feature, as it was reported by third party people in various uninformed online security news portal.
e2dbg-diagram Figure 1: E2dbg in action
We report here the latest features of the embedded ELF debugger:
- June 17 2007 - E2dbg has been modified to start handling static binaries
- June 16 2007 - E2dbg has been ported on the Solaris Operating system
Portability of e2dbg
Some E2dbg features are more portable than others. The current state of portability is as follow:
|Runtime injection of C compiled code||Yes||Yes||Yes||WIP||Yes||No|
|Runtime static Function redirection||Yes||No||No||Yes||Yes||No|
|Runtime external Function redirection||Yes||Yes||Yes||Yes||Yes||No|
|Static ELF file debugging||WIP||No||No||No||No||No|
Unavailable features are the subject of contributions, if someone else has not taken over the implementation of the feature on the bts.
The Embedded ELF debugger depends on other components from the ERESI framework :
- libelfsh : the binary manipulation library, for runtime ET_REL injection, EXTPLT partial relinking, and function redirection.
- libasm : the disassembly engine, for full disassembly of binary code with or without symbols of mapped code.
- librevm : the Reverse Engineering Vector Machine, for dynamic analysis using the ERESI scripting language.
- libaspect : the types specification library, a lower-level component necessary for the ERESI language interpreter.
There is two part in e2dbg. The client part (e2dbg itself with its user interface) is not mapped in the debuggee process. But for all real analysis and debugging code, all those libraries are linked into a unique relocatable (.o) file before a unique libe2dbg.so is created and injected in the debuggee process. See libe2dbg page for more information.
Articles about e2dbg
The Embedded ELF debugger is the subject of two articles:
Next Generation Debuggers for Reverse Engineering
Classical debuggers make use of an interface provided by the operating system in order to access the memory of programs while they execute. As this model is dominating in the industry and the community, we show that our novel embedded architecture is more adapted when debuggee systems are hostile and protected at the operating system level. This alternative modelization is also more performant as the debugger executes from inside the debuggee program and can read the memory of the host process directly. We give detailed information about how to keep memory unintrusiveness using a new technique called allocation proxying. We reveal how we developed the organization of our multiarchitecture framework and its multiple modules so that they allow for graph-based binary code analysis, ad-hoc typing, compositional fingerprinting, program instrumentation, real-time tracing, multithread debugging and general hooking of systems. We reveal the reflective essence of our framework by embedding its internal structures in our own reverse engineering language, thus recalling concepts of aspect oriented programming.
Embedded ELF Debugging
This article presented the improvement and runtime extension to the Cerberus ELF interface by disclosing 7 new binary manipulation techniques on the ELF format. Beside the improvement of ALTPLT, the CFLOW technique allowed internal function redirection for INTEL and MIPS architectures, the EXTPLT technique allowed partial relinking of dynamic binary files, the EXTSTATIC technique allowed partial relinking of static binary files, ALTGOT gave a more portable technique for external function redirection on ALPHA, SPARC and MIPS architectures. Last but not least, the article explained how the framework turned into a very effective generic solution for in-process debugging, uncovering the foundations of the Embedded ELF debugger (e2dbg), making all those techniques also available in runtime, perfoming manipulations directly in memory, using a unified ELF API provided by libelfsh.