Skip to content

Home


Static Badge    DOI    PyPI - Downloads

Quick Start

Welcome to libdebug! This powerful Python library can be used to debug your binary executables programmatically, providing a robust, user-friendly interface. Debugging multithreaded and multiprocess applications can be a nightmare, but libdebug has you covered. Hijack and manage signals and syscalls through a simple API.

Did you know?

With libdebug, you can easily interact with the standard input, output, and error of the debugged process. This means you can send data to and receive data from the process programmatically, making it easier to automate your debugging tasks.

Supported Systems

libdebug currently supports Linux under the x86_64, x86 and ARM64 architectures. Other operating systems and architectures are not supported at this time.

Installation

Installing libdebug is as simple as running the following command:

python3 -m pip install libdebug

If you want to test your installation when installing from source, we provide a suite of tests that you can run:

Testing your installation
git clone https://github.com/libdebug/libdebug
cd libdebug/test
python run_suite.py

For more advanced users, you can also build libdebug from source. Please refer to the Building libdebug from source page for more information.

Your First Script

Now that you have libdebug installed, you can start using it in your scripts. Here is a simple example of how to use libdebug to debug an executable:

libdebug's Hello World!
from libdebug import debugger

def callback(thread, bp) -> None:
    # This callback will be called when the breakpoint is hit
    print(f"RDX is {hex(thread.regs.rdx)}")
    print(f"This is the {bp.hit_count} time the breakpoint was hit")

d = debugger("./test") # (1)!

# Start the process
io = d.run() # (2)!

my_breakpoint = d.breakpoint("function", hardware=True, file="binary") # (3)!
my_callback_breakpoint = d.bp("f2", callback=callback, file="binary") # (4)!

# Continue the execution
d.cont() # (5)!

# Interact with the process
io.sendline(b"Hello world!") # (6)!
io.recvuntil(b"libdebug is like sushi") # (7)!

# Print RAX. This will execute as soon as the process is stopped
print(f"RAX is {hex(d.regs.rax)}") # (8)!

# Write to memory
d.memory[0x10ad, 8, "binary"] = b"Hello!\x00\x00" # (9)!
  1. A debugger is created for the test executable
  2. The process is spawned and the entry point is reached
  3. A breakpoint without a callback is set on the function function in the binary
  4. A breakpoint with a callback is set on the function f2 in the binary. Here, we use an alias for d.breakpoint()
  5. A continuation command is issued, execution resumes
  6. Send Hello world! to the standard input of the process
  7. Wait for the process to print libdebug is like sushi on the standard output
  8. The value of the RAX register is read and printed when the process is stopped at the my_breakpoint breakpoint
  9. A memory write is performed at address 0x10ad in the binary

The above script will run the binary test in the working directory and set two breakpoints: one at the function function and another at f2.

The first breakpoint has no callback, so it will just stop the execution and wait for your script to interact with the process. When the process stops at this breakpoint, you can read and write memory, access registers, and so on. In the example, we print the value of the RAX register and write a string to memory. Then, we continue the execution of the process.

The second breakpoint has a callback that will be called when the breakpoint is hit. Inside a callback, you can interact with the process, read and write memory, access registers, and so on. At the end of the callback, libdebug will automatically continue the execution of the process.

Conflicts with other Python packages

Using pwntools alongside libdebug

The current version of libdebug is incompatible with pwntools.

While having both installed in your Python environment is not a problem, starting a process with pwntools in a libdebug script will cause unexpected behaviors as a result of some race conditions.

Examples of some known issues include:

  • ptrace not intercepting SIGTRAP signals when the process is run with pwntools. This behavior is described in Issue #48.
  • Attaching libdebug to a process that was started with pwntools with shell=True will cause the process to attach to the shell process instead. This behavior is described in Issue #57.

Using libdebug with pwntools

  • 🚫 DONT! (please just don't even try)

    from libdebug import debugger
    from pwn import *
    
    io = process("./provola") # (1)!
    d.attach(io.pid)
    [...]
    leak = u64(io.recvline())
    value = 0xbadf00d
    fmtstr = fmtstr_payload(6, {leak: value})
    io.sendline(fmtstr.encode()) # (2)!
    
    1. The process is started with pwntools, then libdebug is attached to it
    2. The payload is sent to the process using pwntools
  • ✅ DO (if you need to)

    from libdebug import debugger
    from pwn import fmtstr_payload, u64
    
    d = debugger("./provola") # (1)!
    io = d.run()
    [...]
    leak = u64(io.recvline())
    value = 0xbadf00d
    fmtstr = fmtstr_payload(6, {leak: value})
    io.sendline(fmtstr.encode()) # (2)!
    
    1. The process is started with libdebug
    2. The payload is sent to the process using libdebug

Older versions of the documentation

The documentation for versions of libdebug older that 0.7.0 has to be accessed manually at http://docs.libdebug.org/archive/VERSION, where VERSION is the version number you are looking for.

Cite Us

We have a poster on libdebug. If you use libdebug in your research, you can cite the associated poster paper:

@inproceedings{10.1145/3658644.3691391,
author = {Digregorio, Gabriele and Bertolini, Roberto Alessandro and Panebianco, Francesco and Polino, Mario},
title = {Poster: libdebug, Build Your Own Debugger for a Better (Hello) World},
year = {2024},
isbn = {9798400706363},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/3658644.3691391},
doi = {10.1145/3658644.3691391},
booktitle = {Proceedings of the 2024 on ACM SIGSAC Conference on Computer and Communications Security},
pages = {4976–4978},
numpages = {3},
keywords = {debugging, reverse engineering, software security},
location = {Salt Lake City, UT, USA},
series = {CCS '24}
}

Need to cite libdebug as software used in your work? This is the way to cite us:

@software{libdebug_2024,
    title = {libdebug: {Build} {Your} {Own} {Debugger}},
    copyright = {MIT Licence},
    url = {https://libdebug.org},
    publisher = {libdebug.org},
    author = {Digregorio, Gabriele and Bertolini, Roberto Alessandro and Panebianco, Francesco and Polino, Mario},
    year = {2024},
    doi = {10.5281/zenodo.13151549},
}