{"id":15060117,"url":"https://github.com/davidbuchanan314/dlinject","last_synced_at":"2025-05-15T08:11:36.161Z","repository":{"id":38806822,"uuid":"230845346","full_name":"DavidBuchanan314/dlinject","owner":"DavidBuchanan314","description":"Inject a shared library (i.e. arbitrary code) into a live linux process, without ptrace","archived":false,"fork":false,"pushed_at":"2025-02-09T12:32:07.000Z","size":50,"stargazers_count":786,"open_issues_count":4,"forks_count":79,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-05-11T00:12:16.139Z","etag":null,"topics":["assembly","ld-preload","linux","procfs","ptrace","python3","shellcode","shellcode-injection","x86-64"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DavidBuchanan314.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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}},"created_at":"2019-12-30T04:08:11.000Z","updated_at":"2025-05-06T12:12:02.000Z","dependencies_parsed_at":"2025-04-14T14:00:30.835Z","dependency_job_id":null,"html_url":"https://github.com/DavidBuchanan314/dlinject","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidBuchanan314%2Fdlinject","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidBuchanan314%2Fdlinject/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidBuchanan314%2Fdlinject/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidBuchanan314%2Fdlinject/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DavidBuchanan314","download_url":"https://codeload.github.com/DavidBuchanan314/dlinject/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254301613,"owners_count":22047905,"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","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":["assembly","ld-preload","linux","procfs","ptrace","python3","shellcode","shellcode-injection","x86-64"],"created_at":"2024-09-24T22:53:11.273Z","updated_at":"2025-05-15T08:11:31.148Z","avatar_url":"https://github.com/DavidBuchanan314.png","language":"Python","readme":"# dlinject.py\nInject a shared library (i.e. arbitrary code) into a live linux process, without ptrace. Inspired by [Cexigua](https://github.com/AonCyberLabs/Cexigua) and [linux-inject](https://github.com/gaffe23/linux-inject), among other things.\n\n[![asciicast](https://asciinema.org/a/290906.svg)](https://asciinema.org/a/290906)\n\n# Usage\n\n```\n    .___.__  .__            __               __\n  __| _/|  | |__| ____     |__| ____   _____/  |_  ______ ___.__.\n / __ | |  | |  |/    \\    |  |/ __ \\_/ ___\\   __\\ \\____ \u003c   |  |\n/ /_/ | |  |_|  |   |  \\   |  \\  ___/\\  \\___|  |   |  |_\u003e \u003e___  |\n\\____ | |____/__|___|  /\\__|  |\\___  \u003e\\___  \u003e__| /\\|   __// ____|\n     \\/              \\/\\______|    \\/     \\/     \\/|__|   \\/\n\nsource: https://github.com/DavidBuchanan314/dlinject\n\nusage: dlinject.py [-h] [--stopmethod {sigstop,cgroup_freeze,none}]\n                   pid /path/to/lib.so\n\nInject a shared library into a live process.\n\npositional arguments:\n  pid                   The pid of the target process\n  /path/to/lib.so       Path of the shared library to load (note: must be\n                        relative to the target process's cwd, or absolute)\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --stopmethod {sigstop,cgroup_freeze,none}\n                        How to stop the target process prior to shellcode\n                        injection. SIGSTOP (default) can have side-effects.\n                        cgroup freeze requires root. 'none' is likely to cause\n                        race conditions.\n\n```\n\n# Why?\n\n- Because I can.\n\n- There are various [anti-ptrace techniques](https://www.aldeid.com/wiki/Ptrace-anti-debugging), which this evades by simply not using ptrace.\n\n- I don't like ptrace.\n\n- Using `LD_PRELOAD` can sometimes be fiddly or impossible, if the process you want to inject into is spawned by another process with a clean environment.\n\n# How it Works\n\n- Send the stop signal to the target process. (optional)\n\n- Locate the `_dl_open()` symbol.\n\n- Retreive `RIP` and `RSP` via `/proc/[pid]/syscall`.\n\n- Make a backup of part of the stack, and the code we're about to overwrite with our shellcode, by reading from `/proc/[pid]/mem`.\n\n- Generate primary and secondary shellcode buffers.\n\n- Insert primary shellcode at `RIP`, by writing to `/proc/[pid]/mem`.\n\n- The primary shellcode:\n\n  - Pushes common registers to the stack.\n  - Loads the secondary shellcode via `mmap()`.\n  - Jumps to the secondary shellcode.\n\n- The secondary shellcode:\n\n  - Restores the stack and program code to their original states.\n  - Pivots the stack (so we don't touch the original one at all).\n  - Calls `_dl_open()` to load the user-specified library. Any constructors will be executed on load, as usual.\n  - Restores register state, un-pivots the stack, and jumps back to where it was at the time of the original `SIGSTOP`.\n \n# Limitations:\n\n- Sending `SIGSTOP` may cause unwanted side-effects, for example if another thread is waiting on `waitpid()`. The `--stopmethod=cgroup_freeze` option avoids this, but requires root (on most distros, at least).\n\n- I'm not entirely sure how this will interact with complex multi-threaded applications. There's certainly potential for breakage.\n\n- `x86-64` Linux only (for now - 32-bit support could potentially be added).\n\n- Requires root, or relaxed YAMA configuration (`echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope` is useful when testing).\n\n- If the target process is sandboxed (e.g. seccomp filters), it might not have permission to `mmap()` the second stage shellcode, or to `dlopen()` the library.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidbuchanan314%2Fdlinject","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidbuchanan314%2Fdlinject","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidbuchanan314%2Fdlinject/lists"}