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

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

问题描述

我想要做的事情我觉得很简单,我只是不确定如何去做。



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



使用GDB获取此信息非常简单。您可以简单地连接到流程,然后输入信息共享。这是我想知道的确切信息类型。如:


数字基本名称
类型地址原因| |源
| |

| | | | | |

1 Adium

- 0x1000 exec YY /Applications/Adium.app/Contents/MacOS/Adium
(抵消0x0)2 dyld

- 0x8fe00000 dyld YY / usr / lib / dyld在0x8fe00000(偏移
0x0)前缀为__dyld_3 WebCore
F 0x95b6a000 dyld YY
/System/Library/Frameworks/WebKit.framework/版本/ A /框架/ WebCore.framework /版本/ A / WebCore
在0x95b6a000(抵消0x95b6a000)

知道如何以编程方式做到这一点?显然,模块加载的地方是动态的,所以我需要确定它的位置。

解决方案

首先使用task_for_pid 。

然后使用task_info找到dyld all images info address:

  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)
{
//检索dyld_info.all_image_info_addr;
}

这个地址将指向内存中的一个struct dyld_all_image_infos:

  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:

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

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

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

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



在检索完所有的dyld图像信息条目之后,您可能还想按地址对它们进行排序。



我不推荐使用它的vmmap实现来查看newosxbook的代码。它已过时(因为它仍然使用DYLD_ALL_IMAGE_INFOS_OFFSET_OFFSET),并且它会执行一些不必要的暴力操作。


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.

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
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.

解决方案

First use task_for_pid() to obtain a task port.

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;
}

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;
    // ...
}

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;
};

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).

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).

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.

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

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)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆