英特尔 PIN 例程地址检索:Linux 与 Windows

Posted

技术标签:

【中文标题】英特尔 PIN 例程地址检索:Linux 与 Windows【英文标题】:Intel PIN Routine address retrieval: Linux vs. Windows 【发布时间】:2018-04-05 01:57:03 【问题描述】:

我是 PIN 的新手,所以也许对此有一个简单的解释。我对仅在 Windows 上返回的常规地址 PIN 感到困惑。我创建了一个最小的测试程序来说明我的观点。

我目前使用的是 PIN 2.14。我检查的应用程序是一个调试版本,在 Windows 上禁用了 ASLR。

首先考虑这个简单的应用程序,它调用一个空方法并打印该方法的地址:

#include "stdio.h"
class Test 
public:
  void method() 
;
void main() 
  Test t;
  t.method();
  printf("Test::method = 0x%p\n", &Test::method);

下面的 pin 工具会反汇编程序的主程序并打印 Test::method: 的地址

#include <pin.H>
#include "stdio.h"
VOID disassemble(IMG img, VOID *v)

  for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec))
  
    for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn))
    
      auto name = RTN_Name(rtn);
      if(name == "Test::method" || name == "_ZN4Test6methodEv") 
        printf("%s detected by PIN resides at 0x%p.\n", name.c_str(), RTN_Address(rtn));
      
      if (RTN_Name(rtn) != "main") continue;
      RTN_Open(rtn);
      for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins))     
        printf("%s\n", INS_Disassemble(ins).c_str());
      
      RTN_Close(rtn);
    
  

int main(int argc, char **argv)

  PIN_InitSymbols();
  PIN_Init(argc, argv);
  IMG_AddInstrumentFunction(disassemble, 0);
  PIN_StartProgram();
  return 0;

针对 Ubuntu 14.04.3 x64 VM 上的测试应用程序运行此 PIN 工具打印:

push rbp
mov rbp, rsp
push r13
push r12
push rbx
sub rsp, 0x18
lea rax, ptr [rbp-0x21]
mov rdi, rax
call 0x400820
mov r12d, 0x400820
mov r13d, 0x0
mov rcx, r12
mov rbx, r13
mov rax, r12
mov rdx, r13
mov rax, rdx
mov rsi, rcx
mov rdx, rax
mov edi, 0x4008b4
mov eax, 0x0
call 0x4006a0
mov eax, 0x0
add rsp, 0x18
pop rbx
pop r12
pop r13
pop rbp
ret 
_ZN4Test6methodEv detected by PIN resides at 0x0x400820.
Test::method = 0x0x400820

请注意,针对 t.method() 的调用以及通过 PIN 检索的函数地址和应用程序的输出都显示 Test::method 位于地址 0x0x400820。

我的 Windows 10 x64 机器上的输出是:

push rdi
sub rsp, 0x40
mov rdi, rsp
mov ecx, 0x10
mov eax, 0xcccccccc
rep stosd dword ptr [rdi]
lea rcx, ptr [rsp+0x24]
call 0x14000104b
lea rdx, ptr [rip-0x2b]
lea rcx, ptr [rip+0x74ca3]
call 0x1400013f0
xor eax, eax
mov edi, eax
mov rcx, rsp
lea rdx, ptr [rip+0x74cf0]
call 0x1400015f0
mov eax, edi
add rsp, 0x40
pop rdi
ret
Test::method detected by PIN resides at 0x0000000140001120.
Test::method = 0x000000014000104B

应用程序的输出和反汇编中的调用目标显示相同的值。但是PIN返回的例程地址不一样! 我对这种行为感到非常困惑。你知道如何解释吗?

感谢您的任何建议!

【问题讨论】:

【参考方案1】:

自己回答我的问题:

经过一段时间的探索,发现函数指针、调用目标以及PIN返回的例程地址都是有效的,最终调用了方法。

我最终查看了调用目标地址的内存反汇编,果然它看起来像这样:

0000000140001122 E9 D2 00 00 00       jmp         Test::method (014000104Bh)  

换句话说:PIN 似乎用跳转到自己的代码版本代替了原始方法。知道了这一点,我就可以再次关联原始函数指针和 PIN 例程地址,这就是我需要做的。

【讨论】:

以上是关于英特尔 PIN 例程地址检索:Linux 与 Windows的主要内容,如果未能解决你的问题,请参考以下文章

英特尔 PIN 工具:获取 EFLAGS 值的踪迹

如何使用 Intel Pin 工具生成分支列表?

在英特尔 PIN 中跟踪本机指令 [重复]

使用英特尔 pin 工具的堆栈分配大小

修改 PIN 中的应用指令

英特尔引脚:分析例程检测到 ah 寄存器而不是 rsp (REG_STACK_PTR)