{"id":30984380,"url":"https://github.com/libdebug/libdebug","last_synced_at":"2025-09-12T12:05:48.516Z","repository":{"id":147563148,"uuid":"472866724","full_name":"libdebug/libdebug","owner":"libdebug","description":"A Python library to debug binary executables, your own way.","archived":false,"fork":false,"pushed_at":"2025-09-09T00:57:44.000Z","size":65979,"stargazers_count":258,"open_issues_count":31,"forks_count":20,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-09-09T02:58:59.597Z","etag":null,"topics":["ctf","ctf-tools","debugger","debugging","debugging-tool","dynamic-analysis","dynamic-analysis-tools","linux","malware-analysis","ptrace","python","reverse-engineering","reversing","scriptable"],"latest_commit_sha":null,"homepage":"https://libdebug.org/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/libdebug.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"ko_fi":"libdebug"}},"created_at":"2022-03-22T17:25:39.000Z","updated_at":"2025-09-08T19:10:52.000Z","dependencies_parsed_at":"2025-05-13T14:29:40.337Z","dependency_job_id":"e2533bed-0161-4e18-8c57-3034e4296cb3","html_url":"https://github.com/libdebug/libdebug","commit_stats":null,"previous_names":["libdebug/libdebug"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/libdebug/libdebug","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libdebug%2Flibdebug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libdebug%2Flibdebug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libdebug%2Flibdebug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libdebug%2Flibdebug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/libdebug","download_url":"https://codeload.github.com/libdebug/libdebug/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libdebug%2Flibdebug/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274808614,"owners_count":25353718,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-12T02:00:09.324Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ctf","ctf-tools","debugger","debugging","debugging-tool","dynamic-analysis","dynamic-analysis-tools","linux","malware-analysis","ptrace","python","reverse-engineering","reversing","scriptable"],"created_at":"2025-09-12T12:05:46.779Z","updated_at":"2025-09-12T12:05:48.500Z","avatar_url":"https://github.com/libdebug.png","language":"Python","readme":"![logo](https://github.com/libdebug/libdebug/blob/dev/media/libdebug_header.png?raw=true)\n# libdebug [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.13151549.svg)](https://doi.org/10.5281/zenodo.13151549)\n\nlibdebug is an open source Python library for programmatic debugging of userland binary executables. \n\nlibdebug provides a comprehensive set of building blocks designed to facilitate the development of debugging tools for different purposes, including reverse engineering and exploitation. **Build Your Own Debugger!**\n\nWith libdebug you have full control of your debugged executable. With it you can:\n- Access process memory and registers \n- Control the execution flow of the process\n- Handle and hijack syscalls\n- Catch and hijack signals\n- Interact with stdin, stdout, and stderr of the debugged process\n- Debug multithreaded and multiprocess applications with ease\n- Seamlessly switch to GDB for interactive analysis\n- Debug on Linux systems based on AMD64, AArch64, and i386\n\nWhen running the same executable multiple times, choosing efficient implementations can make the difference. For this reason, libdebug prioritizes performance.\n\n## Project Links\nHomepage: https://libdebug.org  \\\nDocumentation: https://docs.libdebug.org\n\n## Installation\n```bash\npython3 -m pip install libdebug\n```\n\n### Install from another branch\nIf 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`).\n\n```bash\npython3 -m pip install git+https://github.com/libdebug/libdebug.git@dev\n```\n\nPlease visit the [build guide](https://docs.libdebug.org/development/building_libdebug/) for more information on how to manually build libdebug from source.\n\n## Your first script\n\nNow 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:\n\n```python\n\nfrom libdebug import debugger\n\ndef my_callback(thread, bp) -\u003e None:\n\t# This callback will be called when the breakpoint is hit\n\tprint(f\"RDX is {hex(thread.regs.rdx)}\")\n\tprint(f\"This is the {bp.hit_count} time the breakpoint was hit\")\n\nd = debugger(\"./test\")\n\n# Start the process\n# By default, the process will stop at the entry point\nio = d.run()\n\nmy_breakpoint = d.breakpoint(\"function\", hardware=True, file=\"binary\")\nmy_callback_breakpoint = d.breakpoint(\"function2\", callback=my_callback, file=\"binary\")\n\n# Continue the execution\nd.cont()\n\n# Interact with the process\nio.sendline(b\"Hello world!\")\nio.recvuntil(b\"libdebug is like sushi\")\n\n# Print RAX. This will execute as soon as the process is stopped\nprint(f\"RAX is {hex(d.regs.rax)}\")\n\n# Write to memory\nd.memory[0x10ad, 8, \"binary\"] = b\"Hello!\\x00\\x00\"\n\n# Continue the execution\nd.cont()\n```\n\nThe above script will run the binary `test` in the working directory and set two breakpoints: one at the function `function` and another at `function2`. \n\nThe 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.\n\nThe 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.\n\nThere is so much more that can be done with libdebug. Please read the [documentation](https://docs.libdebug.org/) to find out more.\n\n## The cool stuff\n\nlibdebug offers many advanced features. Take a look at this script doing magic with signals:\n\n```python\nfrom libdebug import debugger, libcontext\n\nlibcontext.terminal = ['tmux', 'splitw', '-h']\n\n# Define signal catchers\ndef catcher_SIGUSR1(thread, catcher) -\u003e None:\n    thread.signal = 0x0\n    print(f\"SIGUSR1: Signal number {catcher}\")\n\ndef catcher_SIGINT(thread, catcher) -\u003e None:\n    print(f\"SIGINT: Signal number {catcher}\")\n\ndef catcher_SIGPIPE(thread, catcher) -\u003e None:\n    print(f\"SIGPIPE: Signal number {catcher}\")\n\ndef handler_geteuid(thread, handler) -\u003e None:\n\tthread.regs.rax = 0x0\n\n# Initialize the debugger\nd = debugger('/path/to/executable', continue_to_binary_entrypoint=False, aslr=False)\n\n# Start the process\nio = d.run()\n\n# Register signal catchers\ncatcher1 = d.catch_signal(\"SIGUSR1\", callback=catcher_SIGUSR1)\ncatcher2 = d.catch_signal(\"SIGINT\", callback=catcher_SIGINT)\ncatcher3 = d.catch_signal(\"SIGPIPE\", callback=catcher_SIGPIPE)\n\n# Register signal hijackings\nd.hijack_signal(\"SIGQUIT\", \"SIGTERM\")\nd.hijack_signal(\"SIGINT\", \"SIGPIPE\", recursive=True)\n\n# Define which signals to block\nd.signals_to_block = [\"SIGPOLL\", \"SIGIO\", \"SIGALRM\"]\n\n# Register a syscall handler\nd.handle_syscall(\"geteuid\", on_exit=handler_geteuid)\n\n# Register a breakpoint\nbp = d.breakpoint(\"function\", hardware=True, file=\"binary\")\n\n# Continue execution\nd.cont()\n\n# Interact with the process\nio.sendlineafter(b\"libdebug is like provola\", b\"Hello world!\")\n\n# Wait for the process to stop\nd.wait()\n\n# Disable the catchers after execution\ncatcher1.disable()\ncatcher2.disable()\ncatcher3.disable()\n\n# Register a new breakpoint\nbp = d.breakpoint(0xdeadc0de, hardware=True)\n\nd.cont()\nd.wait()\n\nd.gdb()\n```\n\n## Auto Interrupt on Command\nlibdebug 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` \n\n```python\nfrom libdebug import debugger\n\nd = debugger(\"/path/to/executable\", auto_interrupt_on_command=True)\n\nio = d.run()\n\nbp = d.breakpoint(\"function\", file=\"binary\")\n\nd.cont()\n\n# Read shortly after the cont is issued\n# The process is forcibly stopped to read the register\nvalue = d.regs.rax\nprint(f\"RAX is {hex(value)}\")\n\nsystem_offset = d.symbols.filter(\"system\")[0].start\nlibc_base = d.maps.filter(\"libc\")[0].base\n\nsystem_address = libc_base + system_offset\n\nd.memory[0x12ebe, 8, \"libc\"] = int.to_bytes(system_address, 8, \"little\")\n\nd.cont()\nd.wait()\n\n# Here we should be at the breakpoint\n\n# This value is read while the process is stopped at the breakpoint\nip_value = d.regs.rip\n\nprint(f\"RIP is {hex(ip_value)}\")\n\nd.kill()\n```\n\n## Attribution\nWe've published a poster on libdebug. If you use libdebug in your research, you can cite the associated poster paper:\n```bibtex\n@inproceedings{10.1145/3658644.3691391,\n\tauthor = {Digregorio, Gabriele and Bertolini, Roberto Alessandro and Panebianco, Francesco and Polino, Mario},\n\ttitle = {Poster: libdebug, Build Your Own Debugger for a Better (Hello) World},\n\tyear = {2024},\n\tisbn = {9798400706363},\n\tpublisher = {Association for Computing Machinery},\n\taddress = {New York, NY, USA},\n\turl = {https://doi.org/10.1145/3658644.3691391},\n\tdoi = {10.1145/3658644.3691391},\n\tbooktitle = {Proceedings of the 2024 on ACM SIGSAC Conference on Computer and Communications Security},\n\tpages = {4976–4978},\n\tnumpages = {3},\n\tkeywords = {debugging, reverse engineering, software security},\n\tlocation = {Salt Lake City, UT, USA},\n\tseries = {CCS '24}\n}\n```\n\nIf you intend to use libdebug in your projects, you can also cite the software using the following bibtex:\n```bibtex\n@software{libdebug_2024,\n\ttitle = {libdebug: {Build} {Your} {Own} {Debugger}},\n\tcopyright = {MIT Licence},\n\turl = {https://libdebug.org},\n\tpublisher = {libdebug.org},\n\tauthor = {Digregorio, Gabriele and Bertolini, Roberto Alessandro and Panebianco, Francesco and Polino, Mario},\n\tyear = {2024},\n\tdoi = {10.5281/zenodo.13151549},\n}\n```\n\n","funding_links":["https://ko-fi.com/libdebug"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibdebug%2Flibdebug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flibdebug%2Flibdebug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibdebug%2Flibdebug/lists"}