2017-04-14 708 views
0

我一直在研究迷你strace程序的重新编码,而不使用PTRACE_SYSCALL来熟悉寄存器。我使用ptrace(PTRACE_GETREGS,...)来设置user_reg_struct字段,我使用ptrace(PTRACE_PEEKDATA,...)从中读取。如何解释PTRACE_PEEKTEXT返回值

不是真的知道如何处理函数中使用它的数据的retur(系统调用等)做的,我开始寻找一些代码,我遇到的事情来,如:

int is_a_syscall() { 

struct user_reg_struct regs; 
unsigned short int ret; 

ret = ptrace(PTRACE_PEEKDATA, pid, regs.rip, 0); 
if (ret == 0xFFFF) { 
    perror("failed") 
    exit(1); } 
if (ret == 0x80CD || ret == 0x50F) 
    return (true); 
return (false); 
} 

现在可以有人向我解释什么是数字在if()语句,又名:

  • 0xFFFF的,我认为它与处理器的架构做,但我无法验证它
  • 0x80CD0x50F

我想知道它们是什么,在哪里可以找到他们,我能理解他们,我如何使用它们让我的系统调用和他们的论点。

回答

0

你的意思是这些与十进制(例如0x80CD = 32973)有什么关系,或者它们与ptrace()相关的语义是什么(例如0xFFFF可能意味着函数遇到错误)?

如果是前者,这些数字用表示的十六进制数表示。也就是说,数字范围由0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F组成的数字系统。

如果后者请查看man page for ptrace中的返回值部分

1

您包含的代码有点不符合常规,所以我会解释它的作用,然后展示一种不同的方式来实现它。

unsigned short int ret; 
ret = ptrace(PTRACE_PEEKDATA, pid, regs.rip, 0); 

Linux上的ptrace返回一个长而不是无符号的短。代码的作者只是查看ptrace返回的4或8个字节的低位2字节。由于x86是little-endian,这可以完成这项工作,但我将在稍后介绍另一种方法。

if (ret == 0xFFFF) { 
    perror("failed") 
    exit(1); } 

ptrace在失败时返回-1。由于代码仅存储返回值的低位2个字节,并将该值视为无符号,因此-1的测试使用0xFFFF代替。

由于ptrace(PTRACE_PEEKDATA, ...)即使成功也可以返回-1,所以最好还是看看errno(稍后我会进行介绍)。

if (ret == 0x80CD || ret == 0x50F) 
    return (true); 
return (false); 

您可以在像http://ref.x86asm.net/coder64.html这样的站点上找到操作码列表。 CDintCD80int 800F05syscall。这些是x86 Linux中用于执行系统调用的两个操作码。更多信息,请致电What is better “int 0x80” or “syscall”?

这里是另一种方式来检查系统调用指令(未经测试):

int is_a_syscall(regs) 
struct user_reg_struct regs; 
{ 
    long ret; 
    unsigned char primary, secondary; 
    extern int errno; 

    errno = 0; 
    ret = ptrace(PTRACE_PEEKTEXT, pid, regs.rip, 0); 
    if (ret == -1 && errno != 0) { 
     perror("failed") 
     exit(1); 
    } 
    primary = (unsigned)0xFF & ret; 
    secondary = ((unsigned)xFF00 & ret) >> 8; 
    if (primary == 0xCD && secondary == 0x80 || primary == 0x0F && secondary == 0x05) 
     return true; 
    return false; 
} 

我使用ptrace的返回值的整个宽度。如果它是-1并且已经设置了errno,则表明有错误。我也使用PTRACE_PEEKTEXT而不是PTRACE_PEEKDATA,虽然在x86上并不重要。位掩码用于获取主操作码和辅助操作码字节。

我该如何使用它们来获取我的系统调用及其参数。

对此,请参阅此详细答案:What are the calling conventions for UNIX & Linux system calls on x86-64