mdb is a lightweight debugger designed to demonstrate the inner workings of debugging tools using the ptrace syscall. It supports essential debugging capabilities, making it an excellent educational tool for those looking to understand how debuggers function at a low level.
- Add breakpoints by function symbol or memory address.
- List, delete, and manage breakpoints.
- Step through instructions or continue execution.
- Disassemble code dynamically.
Clone the repository and change directory:
git clone https://github.com/kallenosf/minimal-debugger.git
cd minimal-debugger- Build the Docker image:
docker build -t minimal-debugger .- Run the container:
docker run --rm -it minimal-debugger- Once you have shell access inside the container, run the debugger:
./mdb [binary_to_debug]All files are copied inside the container, so any binary you want to debug/analyze, must be copied in the project's directory prior to building and running the container.
There is a tiny sample binary named debug-me inside the binaries directory. You can use it to test the debugger. It's source code, debug-me.c is also inside the binaries directory.
./mdb binaries/debug-meIf you want to compile the debugger from the source code, you need to install two libraries:
libelf-dev: Allows reading and writing of ELF files on a high levellibcapstone-dev: Lightweight multi-architecture disassembly framework
pacman -S libelf
pacman -S capstoneapt install gcc make libelf-dev libcapstone-devOnce you have installed these dependencies:
makemakecompiles also a sample binary nameddebug-meinside thebinariesdirectory
or
gcc mdb.c -o mdb -lelf -lcapstoneThen, you can run the debugger:
./mdb [binary_to_debug]To remove the compiled binary and other generated files, run:
make cleanTo start debugging with mdb, specify the binary you want to debug when launching the program. For example:
./mdb binaries/debug-meOnce loaded, mdb provides a command-line interface with the following commands:
./mdb binaries/debug-me
MINIMAL DEBUGGER
====================
Binary loaded: binaries/debug-me
--------------------
Supported Commands:
1. Add breakpoint command: b <function symbol>
2. Add breakpoint command: b *<address in hex>
3. List all existing breakpoints command: l
4. Delete a breakpoint command: d <b number>
5. Run the programm command: r
6. Continue the execution command: c
7. Execute just a single instruction command: si
8. Disassemble next 48 bytes command: disas
9. Disassemble next <n> bytes command: disas <n>
10. Exit mdb command: q
(mdb)
- Add a Breakpoint by Function Symbol (Sets a breakpoint at the entry point of the main function):
b main
- Add a Breakpoint by Memory Address (Sets a breakpoint at the specified address):
b *0x401000- List All Existing Breakpoints:
l- Delete a Breakpoint:
d 1- Continue Execution:
c- Single-Step Execution:
si- Disassemble Next 48 Bytes:
disas- Disassemble Next
nBytes:
disas 64- Exit the debugger:
q- Position-Independent Executables (PIEs):
- Breakpoints by function symbols are unsupported for PIE binaries because the debugger cannot calculate relative addresses at runtime.
- Workaround: Use memory addresses (e.g., b *0x401000) to set breakpoints if you know the absolute address.
- Dynamic Linking and Symbols:
mdbdoes not currently support dynamically linked symbols, meaning symbols from shared libraries may not be accessible.- Workaround: Consider disassembling shared libraries manually or using absolute addresses.