使用ptrace解析调用和Ret。

时间:2016-04-26 12:29:33

标签: c assembly x86-64 ptrace

我尝试使用ptrace解析可执行文件中的所有Calls和Rets。 符合x64opcode,我发现调用的操作码:0xe8 Rets:0xc3,0xc2,0xca,0xcb

由于我解析了它们,我发现了比呼叫更多的Rets。

我追踪的程序:

void func()                                                                                    
{                                                                                              
  write(1, "i", 1);                                                                            
}                                                                                              

int main(int ac)                                                                               
{                                                                                              
  func();                                                                                      
  return(0);                                                                                   
}

有我的示踪剂:

int                     tracer(t_info *info)                                                   
{                                                                                              
  int                   status;                                                                
  long                  ptr;                                                                   
  int                   ret = 0;                                                                                 
  int                   call = 0;                                                                                


  waitpid(info->pid, &status, 0);                                                              
  while (WIFSTOPPED(status))                                                                   
    {                                                                                          
      ptrace(PTRACE_GETREGS, info->pid, NULL, info->regs);                                     
      ptr = ptrace(PTRACE_PEEKDATA, info->pid, info->regs->rip);                               
      if (((ptr & 0x000000ff) == 0xe8)) // Opcode for call                                                              
        {                                                                                      
          call++;                                                                              
        }                                                                                      
      else if (((ptr & 0x000000ff) == 0xc3) // Opcodes for rets                                
               || ((ptr & 0x000000ff) == 0xc2)                                                 
               || ((ptr & 0x000000ff) == 0xca)                                                 
               || ((ptr & 0x000000ff) == 0xcb))                                                
        {                                                                                      
          ret++;                                                                               
        }                                                                                      
      ptrace(PTRACE_SINGLESTEP, info->pid, 0, 0);                                              
      waitpid(info->pid, &status, 0);                                                          
    }                                                                                          
  printf("Calls: %i\nRets: %i\nDiff: %i\n", call, ret, call - ret);                                             
  return (0);                                                                                  
}

有我的输出:

Calls: 656
Rets: 666
Diff: -10

为什么没有相同数量的 rets 来电? 我错过了一些操作码吗? 是否有不返回的功能?

1 个答案:

答案 0 :(得分:4)

例如,您错过了间接调用,例如

LEFT JOIN ... WHERE right.PK IS NULL

使用其他操作码。 Libc标准初始化例程使用这些。根据表达式,可能有几个操作码,有两个例子:

callq *(<expr>)

可能并不容易。使用像libbfd和libopcodes这样的库来解码指令可能会更容易和更清晰