Чтение и изменение данных системного вызова с помощью ptrace - PullRequest
0 голосов
/ 12 марта 2020

Я пытаюсь сделать простую вещь (только для обучения), я sh перехватываю clock_gettime на 64-битном linux, считываю вывод и изменяю его так, чтобы возвращать фиктивную дату / время в трассировку ( /bin/date).

Что я делаю:

   ptrace(PTRACE_GETREGS, pid, NULL, &regs);
   if(regs.orig_rax==228){  // this is the clock_gettime syscall number in 64 bit linux
     unsigned long p1=ptrace(PTRACE_PEEKDATA, pid, regs.rcx, NULL); // rcx is ARG1
     printf("ARG1: 0x%lx\n",p1);
   }

Теперь, если я правильно понял (явно нет), regs.rcx должен указывать на структуру c с временным интервалом, поэтому я должен прочитать первое длинное int этой структуры, которое является временем в секундах (unixtime). Но я читаю 0.

Кроме того, printf вызывается дважды, один раз входя в системный вызов и второй раз выходя из него. Итак, это нормально, это 0 при входе, но не должно быть при выходе. Infact strace показывает это правильно:

strace 2>&1 date|grep CLOCK

clock_gettime(CLOCK_REALTIME, {tv_sec=1583960872, tv_nsec=403163000}) = 0

Как я могу сделать то же самое?

1 Ответ

0 голосов
/ 12 марта 2020

обнаружил ошибку .. неправильный регистр .. это был RSI

 ptrace(PTRACE_GETREGS, pid, NULL, &regs);
   if(regs.orig_rax==228){  // this is the clock_gettime syscall number in 64 bit linux
     unsigned long p1=ptrace(PTRACE_PEEKDATA, pid, regs.rsi, NULL); // rsi is ARG2
     printf("ARG2: 0x%lx\n",p1);
   }

для x86_64:

#define SYSCALL_ENTRY ((long)RET == -ENOSYS)
#define REGS_STRUCT struct user_regs_struct

#define SYSCALL (regs.orig_rax)
#define ARG1 (regs.rdi)
#define ARG2 (regs.rsi)
#define ARG3 (regs.rdx)
#define ARG4 (regs.r10)
#define ARG5 (regs.r8)
#define ARG6 (regs.r9)
#define RET (regs.rax)
...