2012-04-24 2 views
8

Я пытаюсь прочитать память процесса, используя task_for_pid/vm_read.Получение базового адреса процесса в Mac OSX

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

ответ

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

4

Поскольку вы вызываете current_task(), я предполагаю, что вы нацелены на свой собственный процесс во время выполнения. Таким образом, базовый адрес, который вы упомянули, должен быть динамическим базовым адресом, то есть статическим базовым адресом + слайдом изображения, вызванным ASLR, правильно? Основываясь на этом предположении, вы можете использовать «Аксесуары разделов и сегментов», чтобы получить статический базовый адрес вашего процесса, а затем использовать функции 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; 
} 

Надеюсь, это поможет!

+0

Привет, извинения за вопрос noob. Я попытался добавить этот код в новый файл C, который я добавил в файле dylib, который я создал, который прикрепляется к приложению, которое я сделал, но я не смог получить какой-либо вывод в консоль - должна ли она быть в файле на C++? Я пробовал оба, но я получаю некоторые ошибки сборки. Будет ли это работать в стиле dylib таким образом? Любые советы будут оценены! – Digeridoopoo

Смежные вопросы