c++ - 英特尔 PIN 例程地址检索 : Linux vs. Windows

标签 c++ c intel-pin

我是 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);
}

下面的引脚工具将反汇编程序的主程序并打印 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返回的例程地址不一样!
我对这种行为感到非常困惑。您知道如何解释吗?

感谢您的任何建议!

最佳答案

自己回答我的问题:

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

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

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

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

关于c++ - 英特尔 PIN 例程地址检索 : Linux vs. Windows,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46907650/

相关文章:

c++ - 如何使 C++(共享)库与 clang 和 GCC 兼容?

python - Cython:如何使用用户定义的 C++ 类转换?

c++ - 循环中的 SDL_GL_SwapBuffers() = 卡住?

c - 无法找到导致此错误的原因

c++ - 密码 : identify MOV and indirect memory operand

c++ main 函数,如果命令行参数包含 *,则 argc 值很奇怪

c - C语言中的点积函数

c - Windows CE 上的 libcurl - curl_easy_perform(...) 不返回

python - 使用 python 编译 pin 工具时出错,出现错误 C2872 : 'UINT32' : ambiguous symbol

intel-pin - 英特尔引脚 : getting instruction memory write\read size