使用 Pin 进行检测时如何获取运行时内存区域信息?

逆向工程 动态分析 小工具
2021-06-17 17:10:46

我正在使用Pin一些针对x64 ELF二进制代码的执行监控任务

监控过程中,对于原代码的任何内存写/读操作,只要涉及到heap. 但是,给定一个内存地址,我不知道它是否指的是heap内存区域。

我能想到的一种可能的解决方案是,在每次内存操作之前,我获取目标进程的运行时内存区域信息,并检查当前内存地址是否在该区heap域内。这可以通过在 Pintool 中执行以下步骤来完成。

  1. 获取被监控进程的进程ID(这一步可以使用PinAPI Pin_GetPid
  2. 读取进程内存区域信息 /proc/XXX/maps
  3. 找到heap内存区域
  4. 检查当前地址是否在heap区域内

但是,这很乏味,我的测试表明这非常慢,因为内存大小heap在运行时可能会发生变化,这意味着我每次都需要在内存操作之前执行上述步骤。

所以我想知道,是否Pin有提供heap内存区域信息的API 或者有没有比上述更有效的解决方案?

==================== 更新 ============================ ===

在此处输入图片说明

1个回答

正如您所说的,您使用的是 ELF 代码,我假设您在 Linux 或其他 unix-y 系统下运行。并且proc/self/maps实际上,您不必getpid()使用/proc/XXX/maps)也暗示了 Linux。

我看到的一个问题是heap- 内存映射区域的定义如何,它们是否算作“堆”?Linux在某些情况下malloc使用mmap而不是扩展堆,这通常由brk(它本身可能只是围绕mmap/的包装器)来完成,mremap具体取决于您的 libc。

如果您想跟踪malloced 内存中的所有内容,我只需将地址与代码段的末尾进行比较(但要注意动态库;或者完全省略该比较,因为代码通常无法读取且无法写入无论如何)和堆栈指针的当前值。如果地址低于堆栈指针,则假设为堆。

如果您只想跟踪原始的brk托管堆中的内容,请在开始时仅读取一次内存映射,获取堆起始地址,并监视brk调用,在每个brk.

在 x64 上,“低于堆栈指针”必须持保留态度。在 16 位和 32 位 x86 处理器上,堆栈指针以下的任何内容都可能随时被硬件中断破坏,因此sp/esp是软件可以使用的障碍。但是,在 64 位处理器上,ABI 保证堆栈指针下方的 128 个字节不会被中断更改,因此编译器可以自由使用它们(并且会在叶函数中这样做)。这意味着,esp-0x80如果您正在处理 x64 代码,您确实需要将您的地址与地址进行比较