static int fpm_mach_vm_read_page(vm_offset_t page) /* {{{ */ { kern_return_t kr; kr = mach_vm_read(target, page, fpm_pagesize, &local_page, &local_size); if (kr != KERN_SUCCESS) { zlog(ZLOG_ERROR, "failed to read vm page: mach_vm_read(): %s (%d)", mach_error_string(kr), kr); return -1; } return 0; }
bool ZGReadBytes(ZGMemoryMap processTask, ZGMemoryAddress address, void **bytes, ZGMemorySize *size) { ZGMemorySize originalSize = *size; vm_offset_t dataPointer = 0; mach_msg_type_number_t dataSize = 0; bool success = false; if (mach_vm_read(processTask, address, originalSize, &dataPointer, &dataSize) == KERN_SUCCESS) { success = true; *bytes = (void *)dataPointer; *size = dataSize; } return success; }
int main(int ac, char **av) { kern_return_t kr; task_t mytask; uint32_t sz; unsigned long startaddr,endaddr,i=0,numpages=0; unsigned char **outbuff; FILE *fp; if(ac != 5) { printf("usage: %s <pid> <output file> <start address> <end address>\n",av[0]); exit(1); } if(task_for_pid(mach_task_self(),atoi(av[1]),&mytask)) { printf("[!] error: could not attach to pid.\n"); exit(1); } if(task_suspend(mytask) != KERN_SUCCESS) { printf("[!] Failed suspending task, trying again.\n"); exit(1); } sscanf(av[3],"%lx",&startaddr); sscanf(av[4],"%lx",&endaddr); numpages = ((endaddr - startaddr) / PAGESIZE); fp = fopen(av[2],"w+"); if(fp == NULL){ printf("[!] error: opening output file.\n"); exit(1); } for(i=0; i<=numpages; i++) { /* kern_return_t vm_read (vm_task_t target_task, vm_address_t address, vm_size_t size, size data_out, target_task data_count); */ sz = 4; //printf("[+] reading from 0xx%lx\n",startaddr); if(mach_vm_read(mytask,(unsigned long)startaddr,PAGESIZE,&outbuff,&sz) != KERN_SUCCESS) { printf("error: reading from process\n"); exit(1); } if(fwrite(outbuff,PAGESIZE,1,fp) != 1) { printf("error: writing to file\n"); exit(1); } startaddr+=PAGESIZE; } fclose(fp); if(task_resume(mytask) != KERN_SUCCESS) { printf("[!] Failed resuming task, trying again.\n"); exit(1); } return 0; }
static int mach_xfer_memory_block (CORE_ADDR memaddr, char *myaddr, int len, int write, task_t task) { vm_size_t pagesize = child_get_pagesize (); vm_offset_t mempointer; /* local copy of inferior's memory */ mach_msg_type_number_t memcopied; /* for vm_read to use */ kern_return_t kret; CHECK_FATAL ((memaddr % pagesize) == 0); CHECK_FATAL ((len % pagesize) == 0); if (!write) { kret = mach_vm_read (task, memaddr, len, &mempointer, &memcopied); if (kret != KERN_SUCCESS) { #ifdef DEBUG_MACOSX_MUTILS mutils_debug ("Unable to read region at 0x%8.8llx with length %lu from inferior: %s (0x%lx)\n", (uint64_t) memaddr, (unsigned long) len, MACH_ERROR_STRING (kret), kret); #endif return 0; } if (memcopied != len) { kret = vm_deallocate (mach_task_self (), mempointer, memcopied); if (kret != KERN_SUCCESS) { warning ("Unable to deallocate memory used by failed read from inferior: %s (0x%ux)", MACH_ERROR_STRING (kret), kret); } #ifdef DEBUG_MACOSX_MUTILS mutils_debug ("Unable to read region at 0x%8.8llx with length %lu from inferior: " "vm_read returned %lu bytes instead of %lu\n", (uint64_t) memaddr, (unsigned long) len, (unsigned long) memcopied, (unsigned long) len); #endif return 0; } memcpy (myaddr, ((unsigned char *) 0) + mempointer, len); kret = vm_deallocate (mach_task_self (), mempointer, memcopied); if (kret != KERN_SUCCESS) { warning ("Unable to deallocate memory used by read from inferior: %s (0x%ulx)", MACH_ERROR_STRING (kret), kret); return 0; } } else { kret = mach_vm_write (task, memaddr, (pointer_t) myaddr, len); if (kret != KERN_SUCCESS) { #ifdef DEBUG_MACOSX_MUTILS mutils_debug ("Unable to write region at 0x%8.8llx with length %lu from inferior: %s (0x%lx)\n", (uint64_t) memaddr, (unsigned long) len, MACH_ERROR_STRING (kret), kret); #endif return 0; } } return len; }
static int mach_xfer_memory_remainder (CORE_ADDR memaddr, char *myaddr, int len, int write, task_t task) { vm_size_t pagesize = child_get_pagesize (); vm_offset_t mempointer; /* local copy of inferior's memory */ mach_msg_type_number_t memcopied; /* for vm_read to use */ CORE_ADDR pageaddr = memaddr - (memaddr % pagesize); kern_return_t kret; CHECK_FATAL (((memaddr + len - 1) - ((memaddr + len - 1) % pagesize)) == pageaddr); if (!write) { kret = mach_vm_read (task, pageaddr, pagesize, &mempointer, &memcopied); if (kret != KERN_SUCCESS) { #ifdef DEBUG_MACOSX_MUTILS mutils_debug ("Unable to read page for region at 0x%8.8llx with length %lu from inferior: %s (0x%lx)\n", (uint64_t) pageaddr, (unsigned long) len, MACH_ERROR_STRING (kret), kret); #endif return 0; } if (memcopied != pagesize) { kret = vm_deallocate (mach_task_self (), mempointer, memcopied); if (kret != KERN_SUCCESS) { warning ("Unable to deallocate memory used by failed read from inferior: %s (0x%lx)", MACH_ERROR_STRING (kret), (unsigned long) kret); } #ifdef DEBUG_MACOSX_MUTILS mutils_debug ("Unable to read region at 0x%8.8llx with length %lu from inferior: " "vm_read returned %lu bytes instead of %lu\n", (uint64_t) pageaddr, (unsigned long) pagesize, (unsigned long) memcopied, (unsigned long) pagesize); #endif return 0; } memcpy (myaddr, ((unsigned char *) 0) + mempointer + (memaddr - pageaddr), len); kret = vm_deallocate (mach_task_self (), mempointer, memcopied); if (kret != KERN_SUCCESS) { warning ("Unable to deallocate memory used to read from inferior: %s (0x%ulx)", MACH_ERROR_STRING (kret), kret); return 0; } } else { /* We used to read in a whole page, then modify the page contents, then write that page back out. I bet we did that so we didn't break up page maps or something like that. However, in Leopard there's a bug in the shared cache implementation, such that if we write into it with whole pages the maximum page protections don't get set properly and we can no longer reset the execute bit. In 64 bit Leopard apps, the execute bit has to be set or we can't run code from there. If we figure out that not writing whole pages causes problems of it's own, then we will have to revisit this. */ #if defined (TARGET_POWERPC) vm_machine_attribute_val_t flush = MATTR_VAL_CACHE_FLUSH; /* This vm_machine_attribute only works on PPC, so no reason to keep failing on x86... */ kret = vm_machine_attribute (mach_task_self (), mempointer, pagesize, MATTR_CACHE, &flush); #ifdef DEBUG_MACOSX_MUTILS if (kret != KERN_SUCCESS) { mutils_debug ("Unable to flush GDB's address space after memcpy prior to vm_write: %s (0x%lx)\n", MACH_ERROR_STRING (kret), kret); } #endif #endif kret = mach_vm_write (task, memaddr, (pointer_t) myaddr, len); if (kret != KERN_SUCCESS) { #ifdef DEBUG_MACOSX_MUTILS mutils_debug ("Unable to write region at 0x%8.8llx with length %lu to inferior: %s (0x%lx)\n", (uint64_t) memaddr, (unsigned long) len, MACH_ERROR_STRING (kret), kret); #endif return 0; } } return len; }