Skip to content

Instantly share code, notes, and snippets.

@NSEcho
Last active June 21, 2023 20:50
Show Gist options
  • Save NSEcho/24491137604df1683beac93fe90c782d to your computer and use it in GitHub Desktop.
Save NSEcho/24491137604df1683beac93fe90c782d to your computer and use it in GitHub Desktop.
Enumerate all loaded modules using mach_ API and dyld_image_info struct
#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);
}
}
@NSEcho
Copy link
Author

NSEcho commented Jun 12, 2023

This mimics Frida functionality for Process.enumerateModules()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment