小标
2019-03-14
来源 :
阅读 2081
评论 0
摘要:本文主要向大家介绍了C/C++知识点之C/C++知识点之ios遍历模块的方式,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。
本文主要向大家介绍了C/C++知识点之C/C++知识点之ios遍历模块的方式,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

方式一:
通过mach_vm_region系统API
#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"" ""//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);
}本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!
喜欢 | 0
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号