2012-04-24 16 views
8

में प्रक्रिया आधार पता प्राप्त करना मैं 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 बाइट पढ़े।

यह काम करता है जब मैं प्रक्रिया के मूल पते को जानता हूं (जिसे मैं जीडीबी "जानकारी साझा" का उपयोग कर पा सकता हूं - इस मामले में 0x10e448000), लेकिन मैं रनटाइम पर मूल पता कैसे ढूंढूं (इसे देखे बिना जीडीबी के साथ)?

उत्तर

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

कमांड लाइन से यह उपयोगी हो सकता है: नमूना $ pid 1 2>/dev/null | grep "लोड पता" – sdsykes

4

चूंकि आप current_task() को कॉल कर रहे हैं, मुझे लगता है कि आप रनटाइम पर अपनी प्रक्रिया का लक्ष्य रख रहे हैं। तो आपके द्वारा उल्लिखित आधार पता गतिशील आधार पता होना चाहिए, यानी स्थिर आधार पता + एएसएलआर के कारण छवि स्लाइड, सही? इस धारणा के आधार पर, आप अपनी प्रक्रिया के स्थैतिक आधार पते को प्राप्त करने के लिए "सेक्शन और सेगमेंट एक्सेसर्स" का उपयोग कर सकते हैं और फिर छवि स्लाइड प्राप्त करने के लिए 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

नमस्ते, नोब प्रश्न के लिए क्षमा चाहते हैं - मैंने इस कोड को एक नई सी फ़ाइल में जोड़ने का प्रयास किया जिसे मैंने एक डाइलिब फ़ाइल के अंदर जोड़ा जो मैंने बनाया है जो मैंने बनाया है ऐप से जोड़ता है लेकिन मुझे कोई आउटपुट नहीं मिल सका कंसोल - क्या यह इसके बजाय एक सी ++ फ़ाइल में होना चाहिए? मैंने दोनों की कोशिश की लेकिन मुझे कुछ बिल्ड त्रुटियां मिल गईं। क्या यह इस तरह से एक डाइलिब में काम करेगा? किसी भी युक्तियां की सराहना की जाएगी! – Digeridoopoo