I am trying to recode a little ftrace which displays syscalls and relative call.
I can catch syscall but I am unable to catch relative call (I read about the PTRACE_PEEKTEXT return value, it works really well with sycall but not with relative call).
Here is my loop:
while (1)
{
ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL);
wait4(pid, &status, 0, NULL);
if (WIFEXITED(status))
break ;
ptrace(PTRACE_GETREGS, pid, NULL, ®s);
if (is_a_syscall(regs, pid))
printf("Syscall detected\n");
else if (is_a_relative_call(regs, pid) != -1)
printf("Relative call detected\n");
}
And here are the is_a_syscall
and is_a_relative_call
functions:
int is_a_syscall(struct user_regs_struct regs, pid_t pid)
{
long ret;
unsigned char primary;
unsigned char secondary;
ret = ptrace(PTRACE_PEEKTEXT, pid, regs.rip, 0);
primary = (unsigned)0xFF & ret;
secondary = ((unsigned)0xFF00 & ret) >> 8;
if ((primary == 0xCD && secondary == 0x80) || (primary == 0x0F && secondary == 0x05))
return (1);
return (0);
}
long is_a_relative_call(struct user_regs_struct regs, pid_t pid)
{
long ret;
unsigned char flag;
ret = ptrace(PTRACE_PEEKTEXT, pid, regs.rip + 1, 0);
flag = ret & 0xff;
if (flag == 0xe8)
return (ret);
else
return (-1);
}
The check of relative call is wrong (with some programs compiled with gcc it displays more than I want and with some programs written in asm I have 0 relative calls detected) but I am unable to find the good way to do that ?
Thank you