在Mac OSX中获取进程基地址

10

我试图使用task_for_pid/vm_read读取进程的内存。

uint32_t sz;
pointer_t buf;
task_t task;
pid_t pid = 9484;
kern_return_t error = task_for_pid(current_task(), pid, &task);
vm_read(task, 0x10e448000, 2048, &buf, &sz);

在这种情况下,我读取了前2048个字节。

当我知道进程的基地址时,这是可行的(使用gdb“info shared”可以找到,在这种情况下为0x10e448000),但是在运行时如何找到基地址(不使用gdb查看它)?

2个回答

8

回答自己的问题。我能够使用 mach_vm_region_recurse 获取基地址,如下所示。偏移量落在 vmoffset 中。如果有更好的方式,欢迎评论!

#include <stdio.h>
#include <mach/mach_init.h>
#include <sys/sysctl.h>
#include <mach/mach_vm.h>

 ...

    mach_port_name_t task;
    vm_map_offset_t vmoffset;
    vm_map_size_t vmsize;
    uint32_t nesting_depth = 0;
    struct vm_region_submap_info_64 vbr;
    mach_msg_type_number_t vbrcount = 16;
    kern_return_t kr;

    if ((kr = mach_vm_region_recurse(task, &vmoffset, &vmsize,
                 &nesting_depth,
                 (vm_region_recurse_info_t)&vbr,
                 &vbrcount)) != KERN_SUCCESS) 
    {
        printf("FAIL");
    }

2
非常有用的代码片段,适用于一个文档不全的函数。 - Matt
1
从命令行执行这段代码可能会很有用: sample $pid 1 2>/dev/null | grep "Load Address" - sdsykes

6

由于您在调用current_task()函数,我假设您是在运行时针对自己的进程进行操作。因此,您所提到的基址应该是动态基址,即静态基址与ASLR引起的镜像偏移量之和,对吗?根据这个假设,您可以使用“Section and Segment Accessors”获取您的进程的静态基址,然后使用dyld函数获取镜像偏移量。以下是代码片段:

#import <Foundation/Foundation.h>
#include </usr/include/mach-o/getsect.h>
#include <stdio.h>
#include </usr/include/mach-o/dyld.h>
#include <string.h>

uint64_t StaticBaseAddress(void)
{
    const struct segment_command_64* command = getsegbyname("__TEXT");
    uint64_t addr = command->vmaddr;
    return addr;
}

intptr_t ImageSlide(void)
{
    char path[1024];
    uint32_t size = sizeof(path);
    if (_NSGetExecutablePath(path, &size) != 0) return -1;
    for (uint32_t i = 0; i < _dyld_image_count(); i++)
    {
        if (strcmp(_dyld_get_image_name(i), path) == 0)
            return _dyld_get_image_vmaddr_slide(i);
    }
    return 0;
}

uint64_t DynamicBaseAddress(void)
{
    return StaticBaseAddress() + ImageSlide();
}

int main (int argc, const char *argv[])
{
    printf("dynamic base address (%0llx) = static base address (%0llx) + image slide (%0lx)\n", DynamicBaseAddress(), StaticBaseAddress(), ImageSlide());
    while (1) {}; // you can attach to this process via gdb/lldb to view the base address now :)
    return 0;
}

希望这能帮助到您!

抱歉,我是个新手,我的问题是:我尝试将这段代码添加到一个新的C文件中,该文件位于我创建的dylib文件内,该dylib文件附加到我制作的应用程序中,但我无法在控制台中获得任何输出。它应该放在C++文件中吗?我尝试了两种方法,但都出现了一些构建错误。这种方式在dylib中是否有效?有什么提示吗? - Digeridoopoo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接