Last active
June 21, 2023 20:50
-
-
Save NSEcho/24491137604df1683beac93fe90c782d to your computer and use it in GitHub Desktop.
Enumerate all loaded modules using mach_ API and dyld_image_info struct
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
#include <mach-o/loader.h> | |
#include <mach-o/dyld.h> | |
#include <mach-o/dyld_images.h> | |
#include <mach-o/nlist.h> | |
#include <mach/mach_vm.h> | |
#include <mach/mach_error.h> | |
#include <stdlib.h> | |
void check(kern_return_t); | |
mach_vm_address_t read_memory(task_t task, vm_address_t addr, mach_msg_type_number_t size); | |
int main(void) { | |
task_t task; | |
kern_return_t kr; | |
mach_msg_type_number_t count; | |
task_dyld_info_data_t dyldInfo; | |
struct dyld_all_image_infos * all_image_infos; | |
struct dyld_image_info * infoArray; | |
uint32_t infoArrayCount; | |
int i; | |
task = mach_task_self(); | |
count = TASK_DYLD_INFO_COUNT; | |
kr = task_info(task, TASK_DYLD_INFO, (task_info_t*)&dyldInfo, &count); | |
check(kr); | |
all_image_infos = (struct dyld_all_image_infos*)dyldInfo.all_image_info_addr; | |
infoArray = (struct dyld_image_info*)all_image_infos->infoArray; | |
infoArrayCount = all_image_infos->infoArrayCount; | |
for (i = 0; i <= infoArrayCount; i++) { | |
void * base; | |
void * load_address; | |
unsigned char * name; | |
unsigned long size; | |
struct mach_header_64 * hdr; | |
struct load_command * cmds; | |
if (i != infoArrayCount) { | |
count = sizeof(struct mach_header_64); | |
hdr = (struct mach_header_64*)read_memory(task, | |
(mach_vm_address_t)infoArray[i].imageLoadAddress, count); | |
count = 255; | |
name = (unsigned char*)read_memory(task, | |
(mach_vm_address_t)infoArray[i].imageFilePath, count); | |
load_address = (void*)infoArray[i].imageLoadAddress; | |
} else { // fill data for /usr/lib/dyld | |
count = sizeof(struct mach_header_64); | |
hdr = (struct mach_header_64*)read_memory(task, | |
(mach_vm_address_t)all_image_infos->dyldImageLoadAddress, count); | |
name = "/usr/lib/dyld"; | |
load_address = (void*)all_image_infos->dyldImageLoadAddress; | |
} | |
cmds = malloc(hdr->sizeofcmds); | |
count = hdr->sizeofcmds; | |
cmds = (struct load_command*)read_memory(task, (mach_vm_address_t)load_address+sizeof(struct mach_header_64), count); | |
void * p = cmds; | |
int j; | |
for (j = 0; j < hdr->ncmds; j++) { | |
struct load_command * lc = p; | |
if (lc->cmd == LC_SEGMENT_64) { | |
struct segment_command_64 * sc = p; | |
if (strcmp(sc->segname, "__TEXT") == 0) { | |
size = sc->vmsize; | |
} | |
} | |
p += lc->cmdsize; | |
} | |
base = (void*)load_address; | |
printf("[%d] %s %p (%lu)\n", i, name, base, size); | |
} | |
return 0; | |
} | |
mach_vm_address_t read_memory(task_t task, vm_address_t addr, mach_msg_type_number_t size) | |
{ | |
vm_offset_t read_memory; | |
mach_msg_type_number_t count = size; | |
kern_return_t kr; | |
kr = mach_vm_read(task, addr, size, &read_memory, &count); | |
check(kr); | |
return (vm_address_t)read_memory; | |
} | |
void check(kern_return_t kr) | |
{ | |
if (kr != KERN_SUCCESS) { | |
fprintf(stderr, "error ocurred: %s\n", mach_error_string(kr)); | |
exit(1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This mimics Frida functionality for
Process.enumerateModules()