ios遍曆模組的方式

來源:互聯網
上載者:User

標籤:roo   頭部   add   output   gap   rup   ken   who   ice   

方式一:
通過mach_vm_region系統API
參考代碼:https://github.com/davidrhodus/misc/blob/master/iOS-internals/vmmap.c

#include <mach/vm_map.h>#include <stdio.h>#include <mach-o/dyld_images.h>/** * vmmap(1) clone for OS X and iOS * ------------------------------- * * This is a simple example of using the mach_vm_region_info APIs in order to  * obtain a process‘ (technically, a task‘s) virtual memory address space, in a * manner akin to /proc/[pid]/maps on Linux. * * The process is simple - get the task port, then call mach_vm_region_info until * you‘ve exhausted the address space (in iOS this happens around 0x40000000,  * where the commpage is). On iOS 6, for some peculiar reason the task port is * invalidated after each call, so the quick workaround here solves the problem * by regetting the port. The actual mach error code to check for is in the header * files, though the code simply tries regetting. * * N.B - For this code to work, you MUST provide the entitlements to allow  * task-for-pid to work, else you‘ll fail with error 5. The entitlements are in  * the output in Chapter 3, but for those of you who haven‘t bought the book, it would be: *--- Cut here <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict>        <key>com.apple.springboard.debugapplications</key>        <true/>        <key>get-task-allow</key>        <true/>        <key>proc_info-allow</key>        <true/>        <key>task_for_pid-allow</key>        <true/>        <key>run-unsigned-code</key>        <true/></dict></plist>--- Ok, enough :-) * *  so - copy the above XML to a file, say, "ent.xml", and be sure to run "ldid -Sent.xml vmmap" *  before trying to run this. You can download the binary (already thus signed) if you‘re lazy *  (and trust me, because you *will* need root on your i-Device for this) * *  As the book clearly states, once you have the task port, the world is your oyster. You can *  control the entire virtual memory space, reading and writing it as you please. Stay tuned *  for the corrupt tool (which will be provided soon in binary form) * */int g_pid = 0; // required in iOS 6 (read below) /* 03/08/13 - Added List of Mach-O images: */struct dyld_image_info *g_dii = NULL;int     g_imageCount;//讀取進程記憶體資料unsigned char *readProcessMemory (int pid, mach_vm_address_t addr, mach_msg_type_number_t *size){    // Helper function to read process memory (a la Win32 API of same name)    // To make it easier for inclusion elsewhere, it takes a pid, and    // does the task_for_pid by itself. Given that iOS invalidates task ports    // after use, it‘s actually a good idea, since we‘d need to reget anyway    task_t  t;    //擷取進程中的任務    task_for_pid(mach_task_self(),pid, &t);        mach_msg_type_number_t  dataCnt = size;        vm_offset_t readMem;    // Use vm_read, rather than mach_vm_read, since the latter is different    // in iOS.        //擷取記憶體        kern_return_t kr = vm_read(t,        // vm_map_t target_task,  任務                     addr,     // mach_vm_address_t address, 任務中對應地址                     *size,     // mach_vm_size_t size                     &readMem,     //vm_offset_t *data,                     size);     // mach_msg_type_number_t *dataCnt        if (kr) {                // DANG..                fprintf (stderr, "Unable to read target task‘s memory @%p - kr 0x%x\n" , addr, kr);                 return NULL;                }    return ( (unsigned char *) readMem);}kern_return_t mach_vm_read (vm_map_t, mach_vm_address_t, mach_vm_size_t, vm_offset_t *, mach_msg_type_number_t *);//暴利搜尋記憶體void findListOfBinaries(task_t  t, mach_vm_address_t    addr, int size){        kern_return_t kr;        mach_msg_type_number_t  dataCnt = size;        // 讀取指定記憶體位址上指定大小的內容        unsigned char *readData = readProcessMemory (g_pid, addr, &dataCnt);        int machsig = 0xfeedface;    // Checking only 0xfeedfa is a simple way to catch both 64-bit (facf) and 32-bit (face) headers        // Machine endianness is automatically taken care of, too..    // 判斷是否是macho頭    if (readData && memcmp (readData + 1, ((unsigned char *) &machsig) + 1 , 3) == 0)    {        // This is a Mach header        int i = 0;        // A MUCH better way would be to iterate through the LC and find the name of dyld        // but this would require my machlib.c (closed source) and really get the same result.        // This works because on both iOS and OS X dyld is at /usr/lib.        for (i = 0; i <dataCnt; i++)        {               // 迴圈比較記憶體內容是否是"lib/dyld"            if (memcmp(readData+i, "lib/dyld", 8) == 0)            {                unsigned int dyld_all_image_infos_offset ;                int imageCount = 0;                // 拷貝匯入模組資訊                memcpy (&dyld_all_image_infos_offset, readData+DYLD_ALL_IMAGE_INFOS_OFFSET_OFFSET, sizeof (unsigned int));                 struct dyld_all_image_infos *dyldaii ;                 // Safeguard: should check that dyld_all_image_infos_offset is < size..                if (dyld_all_image_infos_offset > size)                {                    // This is to be expected, since the dyld_all_image_infos is in a data region                    //printf ("Offset %x is greater than region size : %x\n", dyld_all_image_infos_offset, size);                    dataCnt = sizeof(dyld_all_image_infos);                    readData = readProcessMemory (g_pid, addr + dyld_all_image_infos_offset , &dataCnt);                    if (!readData) { return;}                    dyldaii = (struct dyld_all_image_infos *) readData;                }                else                {                    dyldaii = (struct dyld_all_image_infos *) (readData +dyld_all_image_infos_offset);                }                printf ("Version: %d, %d images at offset %p\n",                        dyldaii->version, dyldaii->infoArrayCount, dyldaii->infoArray);                // Go to dyldaii->infoArray address                imageCount = dyldaii->infoArrayCount;                // 儲存匯入模組資訊                dataCnt = imageCount * sizeof(struct dyld_image_info);                g_dii = (struct dyld_image_info *) malloc (dataCnt);                g_imageCount = imageCount;                readData = readProcessMemory(g_pid, dyldaii->infoArray, &dataCnt);                if (!readData) { return;}                struct dyld_image_info *dii = (struct dyld_image_info *) readData;                // We don‘t need i anymore, anyway                for (i = 0; i < imageCount; i++)                    {                        dataCnt = 1024;                        char *imageName = readProcessMemory (g_pid, dii[i].imageFilePath, &dataCnt);                        if (imageName) g_dii[i].imageFilePath = strdup(imageName);                        else g_dii[i].imageFilePath = NULL;                        g_dii[i].imageLoadAddress = dii[i].imageLoadAddress;                    }                break;            }        }    }} /* End 03/08/13 */char *behavior_to_text (vm_behavior_t b){  switch (b)    {        case VM_BEHAVIOR_DEFAULT: return("default");        case VM_BEHAVIOR_RANDOM:  return("random");        case VM_BEHAVIOR_SEQUENTIAL: return("fwd-seq");        case VM_BEHAVIOR_RSEQNTL: return("rev-seq");        case VM_BEHAVIOR_WILLNEED: return("will-need");        case VM_BEHAVIOR_DONTNEED: return("will-need");        case VM_BEHAVIOR_FREE: return("free-nowb");        case VM_BEHAVIOR_ZERO_WIRED_PAGES: return("zero-wire");        case VM_BEHAVIOR_REUSABLE: return("reusable");        case VM_BEHAVIOR_REUSE: return("reuse");        case VM_BEHAVIOR_CAN_REUSE: return("canreuse");        default: return ("?");    }}//記憶體屬性char *protection_bits_to_rwx (vm_prot_t p){  // previous version of this somehow lost the "p&", always returning rwx..  static char returned[4];  returned[0] = (p &VM_PROT_READ    ? ‘r‘ : ‘-‘);  returned[1] = (p &VM_PROT_WRITE   ? ‘w‘ : ‘-‘);  returned[2] = (p & VM_PROT_EXECUTE ? ‘x‘ : ‘-‘);  returned[3] = ‘\0‘; // memory leak here. No biggy  return (strdup(returned));}//當前記憶體狀態const char *unparse_inheritance (vm_inherit_t i){  switch (i)    {    case VM_INHERIT_SHARE:      return "share";    case VM_INHERIT_COPY:      return "copy";    case VM_INHERIT_NONE:      return "none";    default:      return "???";    }}macosx_debug_regions (task_t task, mach_vm_address_t address, int max){  kern_return_t kret;  mach_vm_address_t prev_address;  /* @TODO: warning - potential overflow here - gotta fix this.. */  vm_region_basic_info_data_t prev_info,info;  mach_vm_size_t size, prev_size;  mach_port_t object_name;  mach_msg_type_number_t count;  //模組總共讀的塊數  int nsubregions = 0;  // 已遍曆的模組數  int num_printed = 0;  count = VM_REGION_BASIC_INFO_COUNT_64;  kret = mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO,             (vm_region_info_t) &info, &count, &object_name);  if (kret != KERN_SUCCESS)    {      printf ("mach_vm_region: Error %d - %s", kret, mach_error_string(kret));      return;    }  //儲存上一次遍曆的模組資訊  memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_t));  prev_address = address;  prev_size = size;  // 已擷取1塊  nsubregions = 1;  for (;;)    {      int print = 0;      int done = 0;      address = prev_address + prev_size;      /* Check to see if address space has wrapped around. */      // 遍曆模組結束      if (address == 0)    {         print = done = 1;    }      if (!done)        {          // Even on iOS, we use VM_REGION_BASIC_INFO_COUNT_64. This works.          count = VM_REGION_BASIC_INFO_COUNT_64;          // 讀取從address開始的第一個正確的模組資訊,注意這裡可能不是一個模組頭          kret =            mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO,                          (vm_region_info_t) &info, &count, &object_name);          if (kret != KERN_SUCCESS)            {        /* iOS 6 workaround - attempt to reget the task port to avoiD */        /* "(ipc/send) invalid destination port" (1000003 or something) */        task_for_pid(mach_task_self(),g_pid, &task);        // 重新擷取一遍        kret =            mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO,                              (vm_region_info_t) &info, &count, &object_name);        }       if (kret != KERN_SUCCESS)    {        fprintf (stderr,"mach_vm_region failed for address %p - Error: %x\n", address,(kret));              size = 0;    if (address >= 0x4000000) return;              print = done = 1;            }        }      // 如果上一個記憶體起始地址+記憶體大小!=當前的地址,說明是新的模組      if (address != prev_address + prev_size)        print = 1;      // 如果記憶體屬性不同,說明是新的模組      if ((info.protection != prev_info.protection)          || (info.max_protection != prev_info.max_protection)          || (info.inheritance != prev_info.inheritance)          || (info.shared != prev_info.reserved)          || (info.reserved != prev_info.reserved))        print = 1;      //如果是新的模組,擷取它的其它資訊      if (print)        {      int   print_size;      char *print_size_unit;          if (num_printed == 0)            printf ("Region ");          else            printf ("   ... ");       findListOfBinaries(task, prev_address, prev_size);      /* Quick hack to show size of segment, which GDB does not */      print_size = prev_size;      if (print_size > 1024) { print_size /= 1024; print_size_unit = "K"; }      if (print_size > 1024) { print_size /= 1024; print_size_unit = "M"; }      if (print_size > 1024) { print_size /= 1024; print_size_unit = "G"; }      /* End Quick hack */          printf (" %p-%p [%d%s](%s/%s; %s, %s, %s) %s",                           (prev_address),                           (prev_address + prev_size),               print_size,               print_size_unit,                           protection_bits_to_rwx (prev_info.protection),                           protection_bits_to_rwx (prev_info.max_protection),                           unparse_inheritance (prev_info.inheritance),                           prev_info.shared ? "shared" : "private",                           prev_info.reserved ? "reserved" : "not-reserved",               behavior_to_text (prev_info.behavior));          if (nsubregions > 1)            printf (" (%d sub-regions)", nsubregions);          printf ("\n");          // 把此次記憶體資訊儲存起來          prev_address = address;          prev_size = size;          memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_t));          nsubregions = 1;          num_printed++;        }      else        {          //如果不是新的模組,只增加模組大小          prev_size += size;          nsubregions++;        }      if ((max > 0) && (num_printed >= max))    {     printf ("Max %d num_printed %d\n", max, num_printed);        done = 1;    }      if (done)        break;    }}void main(int argc, char **argv){    struct vm_region_basic_info vmr;    kern_return_t   rc;    mach_port_t task;    mach_vm_size_t  size = 8;    vm_region_info_t    info = (vm_region_info_t) malloc(10000);    mach_msg_type_number_t  info_count;    mach_port_t     object_name;    //初始值設為1    mach_vm_address_t   addr =1;    int pid;    //需要提供參數1為目標進程的PID        if (!argv[1]) { printf ("Usage: %s <PID>\n"); exit (1);}        //把參數1轉換成pid    pid = atoi(argv[1]);    g_pid = pid; // req for iOS 6    // 擷取目標進程的task    rc = task_for_pid(mach_task_self(),pid, &task);    if (rc) { fprintf (stderr, "task_for_pid() failed with error %d - %s\n", rc, mach_error_string(rc)); exit(1); }    printf ("RC %d - Task: %d\n",rc, task);    macosx_debug_regions (task, addr, 1000);    int i ;    for ( i = 0; i < g_imageCount; i++)    {        printf("Image: %s loaded @%p\n",            g_dii[i].imageFilePath, g_dii[i].imageLoadAddress);    }    printf("Done\n");}

方式二:
通過_dyld_getimage*系列API

標頭檔:dyld.h函數原型://擷取當前進程載入的模組數。uint32_t                    _dyld_image_count(void);//擷取記憶體中某個模組的頭部指標。const struct mach_header*   _dyld_get_image_header(uint32_t image_index);//擷取記憶體中某個模組的slide值。intptr_t                    _dyld_get_image_vmaddr_slide(uint32_t image_index);// 擷取記憶體中某個模組的名稱。const char*                 _dyld_get_image_name(uint32_t image_index);實現:#importint32_t nModNums= _dyld_image_count();const char *pszModName = NULL;intptr_t pModSlide = 0;const struct mach_header* pModHeader = NULL;for (uint32_t i = 0; i < nModNums; i++){pModSlide  = _dyld_get_image_vmaddr_slide(i);pszModName = _dyld_get_image_name(i);pModHeader = _dyld_get_image_header(i);}

ios遍曆模組的方式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.