Skip to main content

A Python library for the debugging of binary executables.

Project description

logo

libdebug DOI

libdebug is an open source Python library to automate the debugging of a binary executable.

With libdebug you have full control of the flow of your debugged executable. With it you can:

  • Access process memory and registers
  • Control the execution flow of the process
  • Handle and hijack syscalls
  • Catch and hijack signals
  • Debug multithreaded applications with ease
  • Seamlessly switch to GDB for interactive analysis
  • Multiarch: currently supports Linux AMD64 and AArch64 and i386 (both native and in 32-bit compatibility mode)

When running the same executable multiple times, choosing efficient implementations can make the difference. For this reason, libdebug prioritizes performance.

Project Links

Homepage: https://libdebug.org
Documentation: https://docs.libdebug.org

Installation Requirements:

Ubuntu:
sudo apt install -y python3 python3-dev libdwarf-dev libelf-dev libiberty-dev linux-headers-generic libc6-dbg
Debian:
sudo apt install -y python3 python3-dev libdwarf-dev libelf-dev libiberty-dev linux-headers-generic libc6-dbg
Arch Linux:
sudo pacman -S python libelf libdwarf gcc make debuginfod
Fedora:
sudo dnf install -y python3 python3-devel kernel-devel binutils-devel libdwarf-devel

Installation

python3 -m pip install libdebug

PyPy3 is supported but not recommended, as it performs worse on most of our tests.

If you want to stay up to date with the most cutting-edge features (and you don't mind being on an unstable branch) you can install from a different branch (e.g., dev).

python3 -m pip install git+https://github.com/libdebug/libdebug.git@dev

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 a binary:

from libdebug import debugger

d = debugger("./test")

# Start debugging from the entry point
d.run()

my_breakpoint = d.breakpoint("function")

# Continue the execution until the breakpoint is hit
d.cont()

# Print RAX
print(f"RAX is {hex(d.regs.rax)}")

# Write to memory
d.memory[0x10ad, 8, "binary"] = b"Hello!\x00\x00"

# Continue the execution
d.cont()

The above script will run the binary test in the working directory and stop at the function corresponding to the symbol "function". It will then print the value of the RAX register and kill the process.

There is so much more that can be done with libdebug. Please read the documentation to find out more.

The cool stuff

libdebug offers many advanced features. Take a look at this script doing magic with signals:

from libdebug import debugger, libcontext

libcontext.terminal = ['tmux', 'splitw', '-h']

# Define signal catchers
def catcher_SIGUSR1(t: ThreadContext, catcher: SignalCatcher) -> None:
    t.signal = 0x0
    print(f"SIGUSR1: Signal number {catcher}")

def catcher_SIGINT(t: ThreadContext, catcher: SignalCatcher) -> None:
    print(f"SIGINT: Signal number {catcher}")

def catcher_SIGPIPE(t: ThreadContext, catcher: SignalCatcher) -> None:
    print(f"SIGPIPE: Signal number {catcher}")

def handler_geteuid(t: ThreadContext, handler: SyscallHandler) -> None:
	t.regs.rax = 0x0

# Initialize the debugger
d = debugger('/path/to/executable', continue_to_binary_entrypoint=False, aslr=False)

# Register signal catchers
catcher1 = d.catch_signal("SIGUSR1", callback=catcher_SIGUSR1)
catcher2 = d.catch_signal("SIGINT", callback=catcher_SIGINT)
catcher3 = d.catch_signal("SIGPIPE", callback=catcher_SIGPIPE)

# Register signal hijackings
d.hijack_signal("SIGQUIT", "SIGTERM")
d.hijack_signal("SIGINT", "SIGPIPE", recursive=True)

# Define which signals to block
d.signals_to_block = ["SIGPOLL", "SIGIO", "SIGALRM"]

d.handle_syscall("geteuid", on_exit=handler_geteuid)

# Continue execution
d.cont()

# Disable the catchers after execution
catcher1.disable()
catcher2.disable()
catcher3.disable()

bp = d.breakpoint(0xdeadc0de, hardware=True)

d.cont()
d.wait()

d.gdb()

Auto Interrupt on Command

libdebug also allows you to make all commands execute as soon as possible, without having to wait for a stopping event. To enable this mode, you can use the auto_interrupt_on_command=True

from libdebug import debugger

d = debugger("/path/to/executable", auto_interrupt_on_command=True)

pipes = d.run()

bp = d.breakpoint("function")

d.cont()

# Read shortly after the cont is issued
# The process is forcibly stopped to read the register
value = d.regs.rax
print(f"RAX is {hex(value)}")

system_offset = d.symbols.filter("system")[0].start
libc_base = d.maps.filter("libc")[0].base

system_address = libc_base + system_offset

d.memory[0x12ebe, 8, "libc"] = int.to_bytes(system_address, 8, "little")

d.cont()
d.wait()

# Here we should be at the breakpoint

# This value is read while the process is stopped at the breakpoint
ip_value = d.regs.rip

print(f"RIP is {hex(ip_value)}")

d.kill()

Attribution

If you intend to use libdebug in your work, please cite this repository using the following biblatex:

@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},
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

libdebug-0.7.0.tar.gz (98.4 kB view details)

Uploaded Source

File details

Details for the file libdebug-0.7.0.tar.gz.

File metadata

  • Download URL: libdebug-0.7.0.tar.gz
  • Upload date:
  • Size: 98.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.10.12

File hashes

Hashes for libdebug-0.7.0.tar.gz
Algorithm Hash digest
SHA256 e3df44e06b9bc880e583e48f81d63f8b3adbbbfb363722e06467c5f1269df332
MD5 e59b859caa4ce06f4aa7c2d7deee4017
BLAKE2b-256 84ed178bb9e787f0cb4673209c3e565adea70aea6824b8f420d2d3fec49e5164

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page