Отслеживание системных вызовов

У меня есть следующий код:

void
attach_to_pid (int pid, char *username, int pts)
{
  int sys_call_nr = 0;
  struct user_regs_struct regs;
  ptrace (PTRACE_ATTACH, pid, 0, 0);
  waitpid (pid, 0, WCONTINUED);
  ptrace (PTRACE_SETOPTIONS, pid, 0,
          PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXIT);
  while (true)
    {
      ptrace (PTRACE_SYSCALL, pid, 0, 0);
      int status;
      waitpid (pid, &status, WCONTINUED);
      if (status == (SIGTRAP | PTRACE_EVENT_EXIT << 8))
        break;
      ptrace (PTRACE_GETREGS, pid, 0, &regs);
#ifdef __i386__
      sys_call_nr = regs.eax;
#elif __x86_64__
      sys_call_nr = regs.rax;
#else
#error "Unsupported architecture."
#endif
      if (sys_call_nr == __NR_write)
        {
          printf ("read!");
        }
      ptrace (PTRACE_SYSCALL, pid, 0, 0);
      waitpid (pid, &status, WCONTINUED);
ptrace(PTRACE_GETREGS,pid,0,&regs);
printf("%d = %d\n",sys_call_nr,regs.eax);
//ptrace(PTRACE_CONT, pid, 0 , 0);
    }
  ptrace (PTRACE_DETACH, pid, 0, 0);
}

Я получаю странные результаты, а именно:

-514 = -38
-514 = -38
1 = -38
0 = -38
...

Обычно при отслеживании сеанса sshd с помощью strace я всегда получаю вызовы системных вызовов чтения и записи при записи в оболочку. Но с этой функцией я не получаю эти (поддельные, я думаю) системные вызовы, только (как вы можете видеть): 1, 0 и так далее...

Кто-нибудь может мне помочь? Спасибо.


person user1189104    schedule 18.03.2012    source источник
comment
Я предполагаю, что ядро ​​​​Linux перехватывает системные вызовы при выходе, а не при входе и выходе.   -  person user1189104    schedule 19.03.2012
comment
Что именно вы ожидаете увидеть в регистре eax/rax? Вы ищете имена функций?   -  person Multimedia Mike    schedule 19.03.2012


Ответы (2)


Даже я боролся с той же проблемой. И ваш вопрос является точной копией это Ответ там более красиво объяснен. Это моя версия:
Ваша программа должна различать вход системного вызова и выход системного вызова.
Создайте для этого переменную. Ознакомьтесь с этим кодом. Здесь переменная in_syscall делает то же самое.
Надеюсь, это поможет вам.
В следующий раз проведите фундаментальное исследование (повторный ПОИСК) здесь, прежде чем публиковать вопрос. ТАКЖЕ ЭКОНОМИТ МНОГО ВАШЕГО ВРЕМЕНИ ;) и нашего тоже :D

person kidd0    schedule 20.03.2012
comment
@ user1189104: Не забудьте проверить ответы на вопросы, которые вы разместили ?? :П - person kidd0; 22.03.2012
comment
Большое спасибо за ваш ответ, я решил свою проблему другим и похожим способом, я опубликую свой решенный код, когда закончу другую проблему, которая не работает, как я надеюсь. Большое спасибо. П.Д.: В следующий раз я поищу на этом форуме, не волнуйтесь. Спасибо! - person user1189104; 27.03.2012
comment
Слушай, прошло много времени с тех пор, как я спросил об этом. Наконец-то я смог решить проблему, но прибегнув к некоторым старым приемам. Поскольку в руководстве по ptrace поддерживаются не все названные параметры, простого способа сделать это не было. Я не помню точно, что я должен был сделать, но точно не было обычной, описанной в руководстве, программой. И не было никакого способа узнать, поймал ли syscall_entry или syscall_exit, так что... но все равно спасибо. Ptrace в настоящее время продолжает оставаться не очень мощным. - person user1189104; 02.09.2012

Вот мое решение:

  struct user_regs_struct regs /*_on_entry, regs_on_exit*/ ;
  ptrace (PTRACE_ATTACH, pid, 0, 0);
  waitpid (pid, 0, WCONTINUED);
  while (true)
    {
      ptrace (PTRACE_SYSCALL, pid, 0, 0);
      int status;
      wait (&status);
#ifdef __i386__
      int eax = ptrace (PTRACE_PEEKUSER, pid, ORIG_EAX * 4, 0);
      ptrace (PTRACE_GETREGS, pid, 0, &regs);
      ptrace (PTRACE_SYSCALL, pid, 0, 0);
      waitpid (pid, &status, WCONTINUED);
      if (eax == __NR_read && regs.ebx == 10)
        {
          int *buffer = (int *) malloc (regs.eax + 3);
          int i = 0;
          for (int j = 0; i < regs.eax; i += 4, j++)
            {
              buffer[j] = ptrace (PTRACE_PEEKTEXT, pid, regs.ecx + i, 0);
            }
          if (regs.edx % 4)     // rest of chunk.
            {
              buffer[i] =
                ptrace (PTRACE_PEEKUSER, pid, regs.ecx + 2 * i - regs.eax, 0);
            }
          write (1, buffer, regs.eax);
          free (buffer);
        }
#elif __x86_64__
#else
#error "Unsupported architecture."
#endif
    }

Спасибо за ответы!

person user1189104    schedule 26.03.2012
comment
Мне интересно посмотреть, что делает ваш код. И ваш подход к этой проблеме также отличается. Если вы не возражаете, можете ли вы поделиться с нами кодом? Вы можете вставить свой код здесь - person kidd0; 28.03.2012
comment
Это монитор sshd. И это не закончено, потому что я пытаюсь пропатчить openssh для этой цели. Спасибо за интерес. Надеюсь это поможет. - person user1189104; 29.03.2012
comment
Без комментариев? Хорошо, я думаю, что это прошло давно, и здесь были негативные моменты.. не знаю, почему, правда. ГЛ - person user1189104; 02.09.2012
comment
Сорри, братан.. застрял с работой Fk'd.. :( долго я открывал терминал :'( я посмотрю .. спасибо, что вернулся .. - person kidd0; 22.09.2012