Ptrace hello (virtual) world

From vsd
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, &regs);
#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, &regs);
      }
#endif
      if (regs.orig_rax != __NR_execve)
        insyscall = 1 - insyscall;
      ptrace(PTRACE_SYSCALL,
          child, NULL, NULL);
    }
  }
  return 0;
}