Reputation: 77
Can you please tell me why child prints -38 instead of 999? I would like to change system call data returned to the caller. So I set 999 to make getpid to return 999 but it returns -38. I compiled and run on Linux Ubuntu x86_64
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <syscall.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(int argc, char **argv)
{
int pid = fork();
if (pid == 0) { //child
ptrace(PTRACE_TRACEME, 0, 0, 0);
kill(getpid(), SIGSTOP);
int r = getpid();
printf("child pid %d from child\n", r);
} else { //parent
printf("child pid %d from parent\n", pid);
waitpid(pid, 0, 0);
ptrace(PTRACE_SYSCALL, pid, 0, 0);
waitpid(pid, 0, 0);
struct user_regs_struct uregs;
ptrace(PTRACE_GETREGS, pid, 0, &uregs);
if (uregs.orig_rax == SYS_getpid) {
puts("Yes! It is getpid.");
uregs.orig_rax = 999;
ptrace(PTRACE_SETREGS, pid, 0, &uregs);
ptrace(PTRACE_CONT, pid, 0, 0);
} else {
puts("NO!!! It is not getpid.");
}
}
return 0;
}
Upvotes: 1
Views: 387
Reputation: 77
Thanks to @Alex
I have modified my example to make it work as I want to. And I want to parent to replace return value of getpid() which the child called.
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <syscall.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(int argc, char **argv)
{
int pid = fork();
if (pid == 0) { //child
ptrace(PTRACE_TRACEME, 0, 0, 0);
int r = getpid();
printf("stopping pid %d\n", r);
kill(r, SIGSTOP);
r = getpid();
printf("child pid %d from child, errno %s\n", r, strerror(errno));
} else { //parent
printf("child pid %d from parent\n", pid);
waitpid(pid, 0, 0);
//
// stopped before to call getpid()
//
ptrace(PTRACE_SYSCALL, pid, 0, 0);
waitpid(pid, 0, 0);
struct user_regs_struct regs;
//
// get registers to check if we are at right systemcall - getpid
//
ptrace(PTRACE_GETREGS, pid, 0, ®s);
if (regs.orig_rax != SYS_getpid) {
puts("NO!!! It is not getpid.");
exit(1);
}
//
// execute getpid() and stop right after exit of getpid()
//
ptrace(PTRACE_SYSCALL, pid, 0, 0);
waitpid(pid, 0, 0);
ptrace(PTRACE_GETREGS, pid, 0, ®s);
//
// change return value to 999
//
regs.rax = 999;
ptrace(PTRACE_SETREGS, pid, 0, ®s);
}
return 0;
}
Upvotes: 1