我正在尝试使用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看它吗?
答案 0 :(得分: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");
}
答案 1 :(得分:5)
因为你正在调用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;
}
希望它有所帮助!