Ptrace hello (virtual) world
Jump to navigation
Jump to search
Different experiments can be enabled/disabled by swapping "#if 0" and "#if 1" lines.
#define _GNU_SOURCE
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/user.h>
#include <asm/ptrace-abi.h>
#include <asm/unistd.h> /* For SYS_write etc */
int main(int argc, char *argv[1])
{ pid_t child;
int status;
int insyscall = 0;
child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
argv++;
execvp(argv[0], argv);
}
else {
while(1) {
wait(&status);
if(WIFEXITED(status))
break;
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, child, NULL, ®s);
#if 0
printf("SYSCALL %lld, INOUT %d %x\n",regs.orig_rax,insyscall,status);
#endif
#if 0
if(regs.orig_rax == __NR_write) {
if(insyscall == 0) {
printf("write("
"%lld, 0x%llx, %lld) = ", regs.rdi, regs.rsi, regs.rdx);
}
else { /* Syscall exit */
printf("%lld\n", regs.rax);
}
}
#endif
#if 0
if(regs.orig_rax == __NR_write) {
if(insyscall == 0 && regs.rsi != 0) {
char s[sizeof(long long)+1];
*((long long *)s) = ptrace(PTRACE_PEEKDATA, child, regs.rsi, 0);
s[sizeof(long long)] = 0;
//printf("string - %s\n", s);
if (strncmp(s,"ciao",4) == 0) {
s[0]='m';
}
ptrace(PTRACE_POKEDATA, child, regs.rsi, *((long long *)s));
}
}
#endif
#if 1
if(regs.orig_rax == __NR_getpid && insyscall == 1) {
regs.rax = 42;
ptrace(PTRACE_SETREGS, child, NULL, ®s);
}
#endif
if (regs.orig_rax != __NR_execve)
insyscall = 1 - insyscall;
ptrace(PTRACE_SYSCALL,
child, NULL, NULL);
}
}
return 0;
}