static RList *ios_dbg_maps(RDebug *dbg, int only_modules) { boolt contiguous = R_FALSE; ut32 oldprot = UT32_MAX; ut32 oldmaxprot = UT32_MAX; char buf[1024]; char module_name[MAXPATHLEN]; mach_vm_address_t address = MACH_VM_MIN_ADDRESS; mach_vm_size_t size = (mach_vm_size_t) 0; mach_vm_size_t osize = (mach_vm_size_t) 0; natural_t depth = 0; int tid = dbg->pid; task_t task = pid_to_task (tid); RDebugMap *mr = NULL; RList *list = NULL; int i = 0; if (only_modules) { return xnu_dbg_modules (dbg); } #if __arm64__ || __aarch64__ size = osize = 16384; // acording to frida #else size = osize = 4096; #endif #if 0 if (dbg->pid == 0) { vm_address_t base = get_kernel_base (task); eprintf ("Kernel Base Address: 0x%"PFMT64x"\n", (ut64)base); return NULL; } #endif kern_return_t kr; for (;;) { struct vm_region_submap_info_64 info; mach_msg_type_number_t info_count; info_count = VM_REGION_SUBMAP_INFO_COUNT_64; memset (&info, 0, sizeof (info)); kr = mach_vm_region_recurse (task, &address, &size, &depth, (vm_region_recurse_info_t) &info, &info_count); if (kr != KERN_SUCCESS) { //eprintf ("Cannot kern succ recurse\n"); break; } if (info.is_submap) { depth++; continue; } if (!list) { list = r_list_new (); //list->free = (RListFree*)r_debug_map_free; } { module_name[0] = 0; int ret = proc_regionfilename (tid, address, module_name, sizeof (module_name)); module_name[ret] = 0; } #if 0 oldprot = info.protection; oldmaxprot = info.max_protection; // contiguous pages seems to hide some map names if (mr) { if (address == mr->addr + mr->size) { if (oldmaxprot == info.max_protection) { contiguous = R_FALSE; } else if (oldprot != UT32_MAX && oldprot == info.protection) { /* expand region */ mr->size += size; contiguous = R_TRUE; } else { contiguous = R_FALSE; } } else { contiguous = R_FALSE; } } else contiguous = R_FALSE; //if (info.max_protection == oldprot && !contiguous) { #endif if (1) { #define xwr2rwx(x) ((x&1)<<2) | (x&2) | ((x&4)>>2) // XXX: if its shared, it cannot be read? snprintf (buf, sizeof (buf), "%s %02x %s%s%s%s%s %s depth=%d", r_str_rwx_i (xwr2rwx (info.max_protection)), i, unparse_inheritance (info.inheritance), info.user_tag? " user": "", info.is_submap? " sub": "", info.inheritance? " inherit": "", info.is_submap ? " submap": "", module_name, depth); //info.shared ? "shar" : "priv", //info.reserved ? "reserved" : "not-reserved", //""); //module_name); mr = r_debug_map_new (buf, address, address+size, xwr2rwx (info.protection), 0); if (mr == NULL) { eprintf ("Cannot create r_debug_map_new\n"); break; } mr->file = strdup (module_name); i++; r_list_append (list, mr); } if (size<1) { eprintf ("EFUCK\n"); size = osize; // f**k } address += size; size = 0; } return list; }
void genMemoryRegion(int pid, const vm_address_t &address, const vm_size_t &size, struct vm_region_submap_info_64 &info, const std::map<vm_address_t, std::string> &libraries, QueryData &results) { Row r; r["pid"] = INTEGER(pid); char addr_str[17] = {0}; sprintf(addr_str, "%016lx", address); r["start"] = "0x" + std::string(addr_str); sprintf(addr_str, "%016lx", address + size); r["end"] = "0x" + std::string(addr_str); char perms[5] = {0}; sprintf(perms, "%c%c%c", (info.protection & VM_PROT_READ) ? 'r' : '-', (info.protection & VM_PROT_WRITE) ? 'w' : '-', (info.protection & VM_PROT_EXECUTE) ? 'x' : '-'); // Mimic Linux permissions reporting. r["permissions"] = std::string(perms) + 'p'; char filename[PATH_MAX] = {0}; // Eventually we'll arrive at dynamic memory COW regions. // OS X will return a dyld_shared_cache[...] substitute alias. int bytes = proc_regionfilename(pid, address, filename, sizeof(filename)); if (info.share_mode == SM_COW && info.ref_count == 1) { // (psutil) Treat single reference SM_COW as SM_PRIVATE info.share_mode = SM_PRIVATE; } if (bytes == 0 || filename[0] == 0) { switch (info.share_mode) { case SM_COW: r["path"] = "[cow]"; break; case SM_PRIVATE: r["path"] = "[private]"; break; case SM_EMPTY: r["path"] = "[null]"; break; case SM_SHARED: case SM_TRUESHARED: r["path"] = "[shared]"; break; case SM_PRIVATE_ALIASED: r["path"] = "[private_aliased]"; break; case SM_SHARED_ALIASED: r["path"] = "[shared_aliased]"; break; default: r["path"] = "[unknown]"; } // Labeling all non-path regions pseudo is not 100% appropriate. // Practically, pivoting on non-meta (actual) paths is helpful. r["pseudo"] = "1"; } else { // The share mode is not a mutex for having a filled-in path. r["path"] = std::string(filename); r["pseudo"] = "0"; } r["offset"] = INTEGER(info.offset); r["device"] = INTEGER(info.object_id); // Fields not applicable to OS X maps. r["inode"] = "0"; // Increment the address/region request offset. results.push_back(r); // Submaps or offsets into regions may contain libraries mapped from the // dyld cache. for (const auto &library : libraries) { if (library.first > address && library.first < (address + size)) { r["offset"] = INTEGER(info.offset + (library.first - address)); r["path"] = library.second; r["pseudo"] = "0"; results.push_back(r); } } }