【问题标题】:Ptracing syscalls跟踪系统调用
【发布时间】:2012-04-03 07:32:38
【问题描述】:

我有以下代码:

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
...

通常,当使用strace 跟踪 sshd 会话时,我总是在写入 shell 时获得对 read 和 write 系统调用的调用。但是有了这个函数,我并没有获得那个(我猜是假的)系统调用,只有(如你所见):1、0,等等......

有人可以帮助我吗?谢谢。

【问题讨论】:

  • 我猜,Linux 内核在退出时捕获 sys 调用,而不是在进入和退出时捕获。
  • 您希望在 eax/rax 寄存器中看到什么?您在寻找函数名称吗?

标签: c system-calls ptrace


【解决方案1】:

这是我的解决方案:

  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
    }

感谢您的回复!

【讨论】:

  • 我很想看看你的代码做了什么。你解决这个问题的方法也不同。如果您不介意可以与我们分享代码吗?您可以粘贴您的代码here
  • 这是一个 sshd 监视器。它还没有完成,因为我正在尝试为这个目标修补 openssh。谢谢你的关注。希望这会有所帮助。
  • 没有cmets?好吧,我认为它很久以前就过去了,这里有负面影响.. 不知道为什么,真的。总帐
  • 对不起兄弟.. 坚持了一个 Fk'd 的工作.. :( 很长时间我打开了一个终端 :'( 我看看 .. 谢谢你的光临 ..
【解决方案2】:

即使我也在同一个问题上苦苦挣扎。您的问题与this 完全相同 那里的答案解释得更漂亮。这是我的版本:
您的程序需要区分系统调用入口和系统调用出口。
为此维护一个变量。看看这个code。这里的变量in_syscall 也是如此。
希望这对您有所帮助。
下次在发布问题之前,请在此处进行基础研究(重新搜索)。也为您节省了很多时间;)也是我们的:D

【讨论】:

  • @user1189104:注意检查您发布的问题的答案?? :P
  • 非常感谢您的回答,我以不同和相似的方式解决了我的问题,当我完成另一个无法正常工作的问题时,我将发布我解决的代码。非常感谢。 P.D:下次我会在那个论坛上搜索,别担心。谢谢!
  • 看,自从我问这个问题已经过去很久了。最后我可以解决这个问题,但是做了一些老把戏。由于 ptrace 手册中不支持所有命名的选项,因此没有一种简单的方法可以做到这一点。我不记得确切地我必须做什么,但肯定不是一个正常的 - 手册中描述的 - 编程。并且没有办法知道是捕获 syscall_entry 还是 syscall_exit,所以......但是谢谢你。现在的 Ptrace 仍然不是很强大。
猜你喜欢
  • 2017-01-04
  • 2011-08-02
  • 2012-04-03
  • 2011-04-20
  • 1970-01-01
  • 2012-06-20
  • 2015-07-02
  • 2013-10-15
  • 2016-11-13
相关资源
最近更新 更多