It’s a shot in the dark, but I’d guess this is designed to work with programs that neuter themselves or commit suicide if you ptrace them, as is common for mildly sophisticated malware or (less often) CTF challenges.
a) the program has to actively run its check while being ptraced to notice. If you attach to the program (which pauses it), inject your code, run your code, and then detach, the program's own code will not notice it's being ptraced, no?
b) if you want to run the program's own code while being ptraced, can't you just stop on the ptrace syscall and lie about its result? I think `strace -e inject=ptrace:errno=0` will avoid the program in that wiki page from realizing it's being traced. (You can use seccomp-bpf for this if you don't want to take the performance overhead of stopping on every syscall.)
Depends on if all threads were put into a paused state. Also, the program that's being debugged might have spawned some additional processes that will be checking if the parent is being ptraced.
Replace "self" with the PID you want to check if it is being traced:
$ cat /proc/self/status | grep Tracer
TracerPid: 0As such, I never truly understood the semantics behind PTRACE_TRACEME, and I'm not sure what bad things will happen if you use that when the parent isn't expecting to ptrace the child.
The problem with PTRACE_TRACEME is that if you do it to yourself and recieve a signal, you're put into ptrace stop there's and there's no way out of it unless the parent knows how to get you out of it (using ptrace, of course). Sending signals will not work, even SIGKILL; somewhat humorously, on iOS, if you attempt to do the equivalent (using the similar PT_TRACE_ME) and oops yourself, the entire system will slowly grind to a halt as it tries to (at least, I think…) SIGKILL your process for a variety of reasons and fails, at some point locking up waiting for process termination.
The readme states that the (primary) shell code is written at the EIP location, so no return hijacking is required.
It looks like the gVisor approach for containers (reimplementing parts of the kernel syscalls in userspace and disallowing the rest)
On a normal Linux system, /proc/$pid/mem is protected by the same kernel permission check as ptrace, and a Linux security module like Yama, the thing that disables ptracing unrelated processes on Ubuntu etc., will also block this tool (which the README mentions). It seems like it's mostly useful for cases where people are blocking the ptrace syscall (like Docker's default syscall filter, maybe?) and not loading an LSM.
Cool demonstration that blocking the ptrace syscall isn't sufficient. By the way, blocking /proc too isn't sufficient either: there's the process_vm_writev and process_vm_readv syscalls that work like writing/reading /proc/$pid/mem. I think it's harder to write a robust tool using only those syscalls, but I wouldn't bet on it being impossible.
If you really want to do syscall filtering to confine an untrusted process (as opposed to reducing attack surface from potential bugs in otherwise-permissible syscalls, which is I think Docker's goal), you need to start from empty and allow syscalls instead of starting from full and blocking them. Alternatively, maybe just run the untrusted code as another user account or something.