以编程方式确定在另一个进程中加载​​了哪些模块?(OS X)

Determining programmatically what modules are loaded in another process? (OS X)(以编程方式确定在另一个进程中加载​​了哪些模块?(OS X))

本文介绍了以编程方式确定在另一个进程中加载​​了哪些模块?(OS X)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做的事情我觉得很简单,我只是不确定该怎么做.

What I'm trying to do I feel is pretty straightforward, I'm just not sure exactly how to do it.

具体来说,我只想获取在另一个进程中加载​​的模块(共享/动态库)列表.以及获取该模块在给定进程中的起始地址.

Specifically I just want to get a list of modules (shared/dynamic libraries) that are loaded in another process. As well as get the starting address of where that module is in the given process.

使用 GDB 获取这些信息非常简单.您只需连接到该进程,然后键入信息共享".这正是我想获得的信息类型.如:

It's very straightforward to get this information with GDB. You simple connect to the process, and type "info shared." That is the exact type of information I would like to get to. Such as:

Num Basename
类型地址原因 ||来源||
||||||
1 亚丁
- 0x1000 执行 Y Y/Applications/Adium.app/Contents/MacOS/Adium(偏移量 0x0)2 dyld
- 0x8fe00000 dyld Y Y/usr/lib/dyld at 0x8fe00000(偏移量0x0) 前缀为__dyld_" 3 WebCoreF 0x95b6a000 dyld Y Y/System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/WebCore在 0x95b6a000(偏移量 0x95b6a000)

Num Basename
Type Address Reason | | Source | |
| | | | | |
1 Adium
- 0x1000 exec Y Y /Applications/Adium.app/Contents/MacOS/Adium (offset 0x0) 2 dyld
- 0x8fe00000 dyld Y Y /usr/lib/dyld at 0x8fe00000 (offset 0x0) with prefix "__dyld_" 3 WebCore F 0x95b6a000 dyld Y Y /System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/WebCore at 0x95b6a000 (offset 0x95b6a000)

有人知道如何以编程方式执行此操作吗?显然模块加载的位置是动态的,所以我需要确定它的位置.

Does anyone know how to do this programmatically? Obviously where modules load is dynamic so I need to determine where it's located.

推荐答案

首先使用task_for_pid()获取任务端口.

First use task_for_pid() to obtain a task port.

然后使用task_info找到dyld所有图片信息地址":

Then find the "dyld all images info address" using task_info:

struct task_dyld_info dyld_info;
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
if (task_info(task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count) == KERN_SUCCESS)
{
    // retrieve dyld_info.all_image_info_addr;
}

这个地址会指向内存中的一个结构体dyld_all_image_infos:

This address will point to a struct dyld_all_image_infos in memory:

struct dyld_all_image_infos {
    uint32_t version;
    uint32_t infoArrayCount;
    const struct dyld_image_info* infoArray;
    // ...
}

infoArrayCount 和 infoArray 条目在这里很重要.您必须检索这些值(使用 mach_vm_read)并遍历 infoArray.每个条目都是一个 struct dyld_image_info:

The infoArrayCount and infoArray entries are important here. You have to retrieve these values (use mach_vm_read) and iterate through the infoArray. Each entry is a struct dyld_image_info:

struct dyld_image_info {
    const struct mach_header* imageLoadAddress;
    const char* imageFilePath;
    uintptr_t imageFileModDate;
};

在这个结构中,您有兴趣将值检索到 imageLoadAddress(内存中库的地址)和 imageFilePath(内存中以 NULL 结尾的文件路径的地址).

In this struct, you are interested in retrieving the values to imageLoadAddress (an address to the library in memory) and imageFilePath (an address to the NULL terminated file path in memory).

重要提示:以上结构中标记为指针或 uintptr_t 的字段具有不同的字节大小,具体取决于正在运行的进程是 32 位还是 64 位.您可以通过查看 dyld_info.all_image_info_format 是 TASK_DYLD_ALL_IMAGE_INFO_32 还是 TASK_DYLD_ALL_IMAGE_INFO_64 来确定指针大小(应该可以,但我自己没有测试过).

Important note: the fields that are marked as a pointer or as uintptr_t in the structs above have a different byte size depending on whether the running process is 32 or 64 bit. You may be able to determine pointer size by seeing if dyld_info.all_image_info_format is TASK_DYLD_ALL_IMAGE_INFO_32 or TASK_DYLD_ALL_IMAGE_INFO_64 (should work, but I have not tested this myself).

最后,这仍然不包括动态链接器本身的条目.要检索它,我发现的一种方法是遍历 vm 区域(即 mach_vm_region),并找到第一个看起来像是 mach dylinker 的区域(检查 MH_DYLINKER 作为文件类型;参见 mach-o 文件格式了解更多信息).最后我记得检查,gdb 和/或 lldb 也有这样做的功能.解析 mach 标头也是判断进程是 32 位还是 64 位的一种可能方法.

Lastly, this will still not include an entry to the dynamic linker itself. To retrieve that, one way I've found is to iterate through the vm regions (i.e, mach_vm_region), and find the first region that looks like it's a mach dylinker (check for MH_DYLINKER as the file type; see mach-o file format for more info). Last I recall checking, gdb and/or lldb have a function for doing this too. Parsing the mach header is also one possible way to tell if the process is 32 or 64 bit.

在您检索到所有 dyld 图像信息条目后,您可能还想按地址对其进行排序.

After you retrieve all the dyld image info entries, you may also want to sort them by address.

我建议不要查看 newosxbook 的 vmmap 实现代码.它已经过时了(因为它仍然使用 DYLD_ALL_IMAGE_INFOS_OFFSET_OFFSET),并且它做了一些不必要的暴力破解.

I recommend not looking at newosxbook's code for its vmmap implementation. It is outdated (since it still uses DYLD_ALL_IMAGE_INFOS_OFFSET_OFFSET), and it does some unnecessary brute-forcing.

这篇关于以编程方式确定在另一个进程中加载​​了哪些模块?(OS X)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:以编程方式确定在另一个进程中加载​​了哪些模块?(OS X)