format code

This commit is contained in:
nganhkhoa 2023-07-12 13:37:54 +07:00
parent 4016abf40d
commit f88861a87e
10 changed files with 505 additions and 452 deletions

View File

@ -23,4 +23,3 @@ func NewRewriteImportsWithKeepSymbolsAction(symbols []string) *rewriteImports {
symbols,
}
}

View File

@ -2,17 +2,17 @@ package macho
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"math/rand"
"time"
"strings"
"encoding/binary"
"time"
log "github.com/sirupsen/logrus"
"ios-wrapper/pkg/protomodel"
. "ios-wrapper/pkg/ios"
"ios-wrapper/pkg/protomodel"
)
// #include "fixups.h"

View File

@ -22,12 +22,10 @@ int custom_strcmp(const char *p1, const char *p2) {
return c1 - c2;
}
int custom_strncmp(const char *s1, const char *s2, register size_t n)
{
int custom_strncmp(const char *s1, const char *s2, register size_t n) {
register unsigned char u1, u2;
while (n-- > 0)
{
while (n-- > 0) {
u1 = (unsigned char)*s1++;
u2 = (unsigned char)*s2++;
if (u1 != u2)
@ -310,7 +308,8 @@ void print_macho_summary(const void *header) {
uint64_t size = *((uint64_t *)sections_ptr + 5);
uint32_t fileoffset = *((uint32_t *)sections_ptr + 6 * 2);
printf(" Section %s\n", sections_ptr);
printf(" addr=0x%llx size=0x%llx fileoffset=0x%x\n", addr, size, fileoffset);
printf(" addr=0x%llx size=0x%llx fileoffset=0x%x\n", addr, size,
fileoffset);
}
}
if (cmd == LC_SYMTAB) {
@ -327,15 +326,18 @@ void print_macho_summary(const void *header) {
uint64_t value;
};
uint64_t symtab_start = (uint64_t)symoff - linkedit_fileoffset + slide + linkedit_vmaddr;
uint64_t stroff_start = (uint64_t)stroff - linkedit_fileoffset + slide + linkedit_vmaddr;
uint64_t symtab_start =
(uint64_t)symoff - linkedit_fileoffset + slide + linkedit_vmaddr;
uint64_t stroff_start =
(uint64_t)stroff - linkedit_fileoffset + slide + linkedit_vmaddr;
printf(" symtab: offset=0x%x nsym=0x%x\n", symoff, nsym);
for (int j = 0; j < nsym; j++) {
struct symbol_t *symtab = (struct symbol_t *)symtab_start;
struct symbol_t symbol = symtab[j];
char *name = (char *)stroff_start + symbol.strx;
printf(" %s %llx => %p\n", name, symbol.value, (void*)(symbol.value + slide));
printf(" %s %llx => %p\n", name, symbol.value,
(void *)(symbol.value + slide));
}
}
if (cmd == LC_REEXPORT_DYLIB) {
@ -534,7 +536,8 @@ void *custom_dlsym(struct libcache *cache, const char *libname,
return custom_dlsym(cache, hash, symbol);
}
void bootstrap_libcache_item(struct libcache_item* item, const void* header, const char* name) {
void bootstrap_libcache_item(struct libcache_item *item, const void *header,
const char *name) {
item->header = (void *)header;
item->trie = get_export_trie(header, item->trie_size);
@ -577,7 +580,8 @@ void bootstrap_libcache_item(struct libcache_item* item, const void* header, con
return;
}
struct libcache_item* get_libcache_with_name(struct libcache* cache, const char* name) {
struct libcache_item *get_libcache_with_name(struct libcache *cache,
const char *name) {
void *to_find = 0;
if (custom_strcmp(name, "main") == 0) {
to_find = cache->main;
@ -601,7 +605,8 @@ void dump_export_trie(const void* trie, uint32_t size, const char* filename) {
fclose(outfile);
}
void dump_export_trie_of(const char* libname, const libcache* cache, const char* filename) {
void dump_export_trie_of(const char *libname, const libcache *cache,
const char *filename) {
uint32_t hash = calculate_libname_hash(cache, libname);
for (int i = 0; i < cache->size; i++) {
struct libcache_item cache_lib = cache->libs[i];
@ -644,8 +649,10 @@ void* find_in_symtab(const libcache_item* lib, const char* find) {
uint64_t value;
};
uint64_t symtab_start = (uint64_t)symoff - linkedit_fileoffset + slide + linkedit_vmaddr;
uint64_t stroff_start = (uint64_t)stroff - linkedit_fileoffset + slide + linkedit_vmaddr;
uint64_t symtab_start =
(uint64_t)symoff - linkedit_fileoffset + slide + linkedit_vmaddr;
uint64_t stroff_start =
(uint64_t)stroff - linkedit_fileoffset + slide + linkedit_vmaddr;
for (int j = 0; j < nsym; j++) {
struct symbol_t *symtab = (struct symbol_t *)symtab_start;
@ -673,7 +680,8 @@ void* find_in_symtab(const libcache_item* lib, const char* find) {
return 0;
}
void* find_in_symtab(const char* libname, const libcache* cache, const char* find) {
void *find_in_symtab(const char *libname, const libcache *cache,
const char *find) {
uint32_t hash = calculate_libname_hash(cache, libname);
struct libcache_item *cache_lib = 0;
for (int i = 0; i < cache->size; i++) {
@ -727,7 +735,6 @@ struct custom_initializer_t {
// global variable for PoC
struct custom_initializer_t *custom_initializer_i;
struct ProgramVars {
void *mh; // mach_header or mach_header64
int *NXArgcPtr;
@ -760,8 +767,8 @@ bruh(int argc, const char *const argv[], const char *const envp[],
// "/usr/lib/libobjc.A.dylib", &cache,
// "../scripts/lib_objc_symtab.bin");
// struct libcache_item* objc = get_libcache_with_name(&cache, "/usr/lib/libobjc.A.dylib");
// print_macho_summary(objc->header);
// struct libcache_item* objc = get_libcache_with_name(&cache,
// "/usr/lib/libobjc.A.dylib"); print_macho_summary(objc->header);
// test(cache);
@ -773,7 +780,8 @@ bruh(int argc, const char *const argv[], const char *const envp[],
// (we do not remove them for **our lib**)
// - malloc
// - free
custom_initializer_i = (custom_initializer_t*)malloc(sizeof(custom_initializer_t));
custom_initializer_i =
(custom_initializer_t *)malloc(sizeof(custom_initializer_t));
custom_initializer_i->programvars = (void *)vars;
custom_initializer_i->cls = 0;
custom_initializer_i->constructors = 0;
@ -891,8 +899,7 @@ void fix_binds(struct libcache_item* libfixing, struct libcache* cache,
// enable WRITE protection for this data segment
int need_rw_fix = true;
for (int j = 0; j < npage_rw_fixed; j++) {
if (page_rw_fixed[j] <= fix_at &&
page_rw_fixed[j] + 0x1000 > fix_at) {
if (page_rw_fixed[j] <= fix_at && page_rw_fixed[j] + 0x1000 > fix_at) {
need_rw_fix = false;
}
}
@ -919,7 +926,6 @@ void fix_binds(struct libcache_item* libfixing, struct libcache* cache,
printf(" resolved=%llx(%p)\n", *(uint64_t *)fix_at, resolved);
}
}
}
void fix_objc(struct libcache_item *libfixing, struct libcache &cache);
@ -960,20 +966,23 @@ void fix(struct libcache& cache) {
// OBJC:
// In Objective-C, the binary is loaded with the Objective-C runtime
// This runtime (a library) install a hook on dyld for all images
// And because this runtime is a system runtime, the bootstrap step is already prepared
// The details on this runtime will be in a seperated document, below are some basics
// And because this runtime is a system runtime, the bootstrap step is already
// prepared The details on this runtime will be in a seperated document, below
// are some basics
//
// The compiler for Objective-C emits a bunch of details for the runtime in the binary itself
// These information are stored in sections with prefix name __objc, namely
// The compiler for Objective-C emits a bunch of details for the runtime in
// the binary itself These information are stored in sections with prefix name
// __objc, namely
// - __objc_classlist
// - __objc_clssrefs
// - __objc_selref
// - __objc_const
// - __objc_data
//
// Objective-C stores the class interface in the binary particulary in __objc_data
// This interface contains the superclass, metaclass, and a cache to methods pointers
// These information are either bound (by dyld) or built (by Objective-C runtime)
// Objective-C stores the class interface in the binary particulary in
// __objc_data This interface contains the superclass, metaclass, and a cache
// to methods pointers These information are either bound (by dyld) or built
// (by Objective-C runtime)
//
// One of the important routine in the Objective-C runtime is readClass.
// https://github.com/apple-oss-distributions/objc4/blob/689525d556eb3dee1ffb700423bccf5ecc501dbf/runtime/objc-runtime-new.mm#L3385
@ -983,18 +992,21 @@ void fix(struct libcache& cache) {
//
// Because __objc_data contains to-be-bound values,
// which will be resolved by dyld and referenced by Objective-C runtime later
// if we simply erase this value, reference(s) read by Objective-C runtime ensues a crash
// (through debugging, we know that the crash happens in readClass, realizeClassWithoutSwift)
// if we simply erase this value, reference(s) read by Objective-C runtime
// ensues a crash (through debugging, we know that the crash happens in
// readClass, realizeClassWithoutSwift)
//
// However, we can evade this by making the runtime thinks there is no class needs setup
// This can be done by changing the __objc_classlist to some other name or remove this section
// Because the runtime find the __objc_classlist section by name, and the size of the section
// is used to iterate through pointers.
// So if we change the name, the runtime will have no class to run setup.
// Or complete removal and call the setup by ourselves, because we know where the data is
// However, we can evade this by making the runtime thinks there is no class
// needs setup This can be done by changing the __objc_classlist to some other
// name or remove this section Because the runtime find the __objc_classlist
// section by name, and the size of the section is used to iterate through
// pointers. So if we change the name, the runtime will have no class to run
// setup. Or complete removal and call the setup by ourselves, because we know
// where the data is
//
// The setup is done through readClass function, as said above, its address can be found
// This function is pure C function so call into this function is easy
// The setup is done through readClass function, as said above, its address
// can be found This function is pure C function so call into this function is
// easy
//
// Important function with their names:
// _readClass(objc_class*, bool, bool)
@ -1027,7 +1039,8 @@ void fix(struct libcache& cache) {
uint32_t liblist_offset;
uint32_t symbollist_offset;
};
struct selfbind_t* selfbind = (struct selfbind_t*)get_selfbind(libfixing->header);
struct selfbind_t *selfbind =
(struct selfbind_t *)get_selfbind(libfixing->header);
if (selfbind) {
char *libs = (char *)(selfbind + 1) + selfbind->liblist_offset;
@ -1036,23 +1049,23 @@ void fix(struct libcache& cache) {
uint32_t *encoded_table = (uint32_t *)(selfbind + 1);
printf("[*] performing selfbind (instructions=%p)\n", selfbind);
fix_binds(libfixing, &cache,
n_instructions, encoded_table,
libs, symbols);
fix_binds(libfixing, &cache, n_instructions, encoded_table, libs,
symbols);
}
}
// the rest of the fixes are in main executable
printf("[*] performing bind for main executable\n");
struct libcache_item *libfixing = get_libcache_with_name(&cache, "main");
fix_binds(libfixing, &cache,
bshield_data::n_instructions, bshield_data::encoded_table,
bshield_data::libs, bshield_data::symbols);
fix_binds(libfixing, &cache, bshield_data::n_instructions,
bshield_data::encoded_table, bshield_data::libs,
bshield_data::symbols);
// TODO: Reformat the region as per before, or leave as it
// for (int j = 0; j < npage_rw_fixed; j++) {
// uint64_t start_page = page_rw_fixed[j];
// vm_protect_func(mach_task_self_func(), start_page, 0x4000, 0, VM_PROT_READ);
// vm_protect_func(mach_task_self_func(), start_page, 0x4000, 0,
// VM_PROT_READ);
// }
// Encrypted __TEXT segment
@ -1070,34 +1083,43 @@ void fix(struct libcache& cache) {
fix_initializer(libfixing, cache);
}
void volatile
custom_initializer(int argc, const char *const argv[], const char *const envp[], const char *const apple[]) {
void volatile custom_initializer(int argc, const char *const argv[],
const char *const envp[],
const char *const apple[]) {
printf("run custom initializers %p\n", custom_initializer_i);
if (custom_initializer_i->cls != 0) {
// for Objective-C load
uint64_t *loadable_classes = custom_initializer_i->loadable_classes;
uint32_t* loadable_classes_used = custom_initializer_i->loadable_classes_used;
sel_lookUpByName_t sel_lookUpByName = custom_initializer_i->sel_lookUpByName;
objc_autoreleasePoolPop_t objc_autoreleasePoolPop = custom_initializer_i->objc_autoreleasePoolPop;
objc_autoreleasePoolPush_t objc_autoreleasePoolPush = custom_initializer_i->objc_autoreleasePoolPush;
uint32_t *loadable_classes_used =
custom_initializer_i->loadable_classes_used;
sel_lookUpByName_t sel_lookUpByName =
custom_initializer_i->sel_lookUpByName;
objc_autoreleasePoolPop_t objc_autoreleasePoolPop =
custom_initializer_i->objc_autoreleasePoolPop;
objc_autoreleasePoolPush_t objc_autoreleasePoolPush =
custom_initializer_i->objc_autoreleasePoolPush;
remapClass_t remapClass = custom_initializer_i->remapClass;
schedule_class_load_t schedule_class_load = custom_initializer_i->schedule_class_load;
schedule_class_load_t schedule_class_load =
custom_initializer_i->schedule_class_load;
for (int i = 0; i < custom_initializer_i->ncls; i++) {
void *cls0 = (void *)custom_initializer_i->cls[i];
void *cls = remapClass(cls0);
if (!cls) continue;
if (!cls)
continue;
schedule_class_load(cls);
}
printf("loadable_classes %llx %x\n", *loadable_classes, *loadable_classes_used);
printf("loadable_classes %llx %x\n", *loadable_classes,
*loadable_classes_used);
struct loadable_class_t {
void *cls;
void *method;
};
struct loadable_class_t *classes = (struct loadable_class_t*)*loadable_classes;
struct loadable_class_t *classes =
(struct loadable_class_t *)*loadable_classes;
int used = *loadable_classes_used;
*loadable_classes = 0;
// *loadable_classes_allocated = 0;
@ -1109,11 +1131,13 @@ custom_initializer(int argc, const char *const argv[], const char *const envp[],
void *cls = classes[i].cls;
load_method_t load_method = (load_method_t)classes[i].method;
printf("call load of class %p %p\n", cls, load_method);
if (!cls) continue;
if (!cls)
continue;
(load_method)(cls, sel);
}
// Destroy the detached list.
if (classes) free(classes);
if (classes)
free(classes);
objc_autoreleasePoolPop(pool);
}
@ -1122,9 +1146,11 @@ custom_initializer(int argc, const char *const argv[], const char *const envp[],
typedef void *(*constructors_t)(int, void *, void *, void *, void *);
uint32_t nconst = custom_initializer_i->nconstructors;
for (int i = 0; i < nconst; i++) {
constructors_t cons = (constructors_t)custom_initializer_i->constructors[i];
constructors_t cons =
(constructors_t)custom_initializer_i->constructors[i];
printf("call initializer at %p\n", cons);
cons(argc, (void*)argv, (void*)envp, (void*)apple, custom_initializer_i->programvars);
cons(argc, (void *)argv, (void *)envp, (void *)apple,
custom_initializer_i->programvars);
}
free(custom_initializer_i->constructors);
}
@ -1183,52 +1209,70 @@ void fix_objc(struct libcache_item* libfixing, struct libcache& cache) {
uint64_t size = *((uint64_t *)sections_ptr + 5);
uint64_t *data_ptr = (uint64_t *)(addr + slide);
readClass_t readClass = (readClass_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__ZL9readClassP10objc_classbb");
realizeClassWithoutSwift_t realizeClassWithoutSwift = (realizeClassWithoutSwift_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__ZL24realizeClassWithoutSwiftP10objc_classS0_");
readClass_t readClass =
(readClass_t)find_in_symtab("/usr/lib/libobjc.A.dylib", &cache,
"__ZL9readClassP10objc_classbb");
realizeClassWithoutSwift_t realizeClassWithoutSwift =
(realizeClassWithoutSwift_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache,
"__ZL24realizeClassWithoutSwiftP10objc_classS0_");
for (int ptr_i = 0; ptr_i < size / 8; ptr_i++) {
// this pointer is rebased by dyld and points to the correct class interface
// for some reason, we can skip this and it should still work
// this pointer is rebased by dyld and points to the correct class
// interface for some reason, we can skip this and it should still
// work
void *newCls = readClass((void *)data_ptr[ptr_i], false, false);
if (newCls != (void *)data_ptr[ptr_i]) {
realizeClassWithoutSwift(newCls, 0);
}
printf("add class init (%llx)%p\n", data_ptr[ptr_i], newCls);
}
}
else if (custom_strncmp(secname, "__objc_nlclsbruh", 16) == 0) {
} else if (custom_strncmp(secname, "__objc_nlclsbruh", 16) == 0) {
uint64_t addr = *((uint64_t *)sections_ptr + 4);
uint64_t size = *((uint64_t *)sections_ptr + 5);
uint64_t *data_ptr = (uint64_t *)(addr + slide);
uint64_t *loadable_classes = (uint64_t *)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__ZL16loadable_classes");
uint32_t* loadable_classes_allocated = (uint32_t*)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__ZL26loadable_classes_allocated");
uint32_t* loadable_classes_used = (uint32_t*)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__ZL21loadable_classes_used");
uint32_t *loadable_classes_allocated =
(uint32_t *)find_in_symtab("/usr/lib/libobjc.A.dylib", &cache,
"__ZL26loadable_classes_allocated");
uint32_t *loadable_classes_used =
(uint32_t *)find_in_symtab("/usr/lib/libobjc.A.dylib", &cache,
"__ZL21loadable_classes_used");
remapClass_t remapClass = (remapClass_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__ZL10remapClassP10objc_class");
schedule_class_load_t schedule_class_load = (schedule_class_load_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__ZL19schedule_class_loadP10objc_class");
realizeClassWithoutSwift_t realizeClassWithoutSwift = (realizeClassWithoutSwift_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__ZL24realizeClassWithoutSwiftP10objc_classS0_");
addClassTableEntry_t addClassTableEntry = (addClassTableEntry_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__ZL18addClassTableEntryP10objc_classb");
sel_lookUpByName_t sel_lookUpByName = (sel_lookUpByName_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "_sel_lookUpByName");
objc_autoreleasePoolPush_t objc_autoreleasePoolPush = (objc_autoreleasePoolPush_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__objc_autoreleasePoolPush");
objc_autoreleasePoolPop_t objc_autoreleasePoolPop = (objc_autoreleasePoolPop_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache, "__objc_autoreleasePoolPop");
remapClass_t remapClass =
(remapClass_t)find_in_symtab("/usr/lib/libobjc.A.dylib", &cache,
"__ZL10remapClassP10objc_class");
schedule_class_load_t schedule_class_load =
(schedule_class_load_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache,
"__ZL19schedule_class_loadP10objc_class");
realizeClassWithoutSwift_t realizeClassWithoutSwift =
(realizeClassWithoutSwift_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache,
"__ZL24realizeClassWithoutSwiftP10objc_classS0_");
addClassTableEntry_t addClassTableEntry =
(addClassTableEntry_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache,
"__ZL18addClassTableEntryP10objc_classb");
sel_lookUpByName_t sel_lookUpByName =
(sel_lookUpByName_t)find_in_symtab("/usr/lib/libobjc.A.dylib",
&cache, "_sel_lookUpByName");
objc_autoreleasePoolPush_t objc_autoreleasePoolPush =
(objc_autoreleasePoolPush_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache,
"__objc_autoreleasePoolPush");
objc_autoreleasePoolPop_t objc_autoreleasePoolPop =
(objc_autoreleasePoolPop_t)find_in_symtab(
"/usr/lib/libobjc.A.dylib", &cache,
"__objc_autoreleasePoolPop");
// https://github.com/apple-oss-distributions/objc4/blob/689525d556eb3dee1ffb700423bccf5ecc501dbf/runtime/objc-runtime-new.mm#L3822
for (int ptr_i = 0; ptr_i < size / 8; ptr_i++) {
void *cls = remapClass((void *)data_ptr[ptr_i]);
if (!cls) continue;
if (!cls)
continue;
addClassTableEntry(cls);
realizeClassWithoutSwift(cls, 0);
printf("build nonlazy class at (%llx)%p\n", data_ptr[ptr_i], cls);
@ -1237,8 +1281,10 @@ void fix_objc(struct libcache_item* libfixing, struct libcache& cache) {
custom_initializer_i->sel_lookUpByName = sel_lookUpByName;
custom_initializer_i->loadable_classes = loadable_classes;
custom_initializer_i->loadable_classes_used = loadable_classes_used;
custom_initializer_i->objc_autoreleasePoolPush = objc_autoreleasePoolPush;
custom_initializer_i->objc_autoreleasePoolPop = objc_autoreleasePoolPop;
custom_initializer_i->objc_autoreleasePoolPush =
objc_autoreleasePoolPush;
custom_initializer_i->objc_autoreleasePoolPop =
objc_autoreleasePoolPop;
custom_initializer_i->schedule_class_load = schedule_class_load;
custom_initializer_i->remapClass = remapClass;
custom_initializer_i->cls = data_ptr;
@ -1259,10 +1305,11 @@ void fix_objc(struct libcache_item* libfixing, struct libcache& cache) {
void fix_initializer(struct libcache_item *libfixing, struct libcache &cache) {
// fix the initializers
// The Objective-C runtime loads the NSObject after this lib booted
// So all calls to NSObject (and its children classes) will segfault/throw error
// So all calls to NSObject (and its children classes) will segfault/throw
// error
//
// So we will fix the main initializers, which runs after all Objective-C setup
// The initializers will run these Objective-C classes' load methods
// So we will fix the main initializers, which runs after all Objective-C
// setup The initializers will run these Objective-C classes' load methods
//
// (THIS IDEA IS TESTED AND WILL NOT WORK)
// As of now, we assume the main executable has a __mod_init_func section
@ -1281,29 +1328,32 @@ void fix_initializer(struct libcache_item* libfixing, struct libcache& cache) {
//
// There could be many ways to do this. I discovered 1 method of doing this.
//
// The idea is to hijack the main function to do the rest of the initalizations.
// By fixing the LC_MAIN command, we can make dyld jump to anywhere we want as main.
// But the command can't be edited at runtime.
// And pointing to the function we want needs a workaround.
// The idea is to hijack the main function to do the rest of the
// initalizations. By fixing the LC_MAIN command, we can make dyld jump to
// anywhere we want as main. But the command can't be edited at runtime. And
// pointing to the function we want needs a workaround.
//
// So we will write a shellcode in the binary and point main to that shellcode.
// The shellcode basically loads the address of the initalization function,
// call it, then call main, and return.
// So we will write a shellcode in the binary and point main to that
// shellcode. The shellcode basically loads the address of the initalization
// function, call it, then call main, and return.
//
// The shellcode must be able ot get the current pc address to correctly calculate
// address from any offset. In arm64, we can use `adr x8, 0`.
// If we know where the shellcode is, we can effectively calculate the header of main.
// Now, everything is easy, just need offsets to anywhere we want and we can get it.
// The shellcode must be able ot get the current pc address to correctly
// calculate address from any offset. In arm64, we can use `adr x8, 0`. If we
// know where the shellcode is, we can effectively calculate the header of
// main. Now, everything is easy, just need offsets to anywhere we want and we
// can get it.
//
// Now the address of the initalization function can be fetched using many methods,
// but it resides inside this library. To reduce redundance work, we can write the
// address of this function somewhere inside main, which will then be easily found.
// Now the address of the initalization function can be fetched using many
// methods, but it resides inside this library. To reduce redundance work, we
// can write the address of this function somewhere inside main, which will
// then be easily found.
//
// As a result, we choose the space before __text to write the shellcode,
// the space after __DATA to write the address for initalization function.
// Because all segment is allocated/pre-allocated with page alignement,
// we can be pretty sure that there are free space.
// (note: __TEXT segment is aligned to the end of the page, free space in the middle)
// (note: __TEXT segment is aligned to the end of the page, free space in the
// middle)
//
// Below is the shellcode.
/*
@ -1369,10 +1419,13 @@ void fix_initializer(struct libcache_item* libfixing, struct libcache& cache) {
printf("found initializer at %p\n", data_ptr);
custom_initializer_i->nconstructors = size / 4;
custom_initializer_i->constructors = (uint64_t*)malloc(sizeof(uint64_t) * size/4);
custom_initializer_i->constructors =
(uint64_t *)malloc(sizeof(uint64_t) * size / 4);
for (int j = 0; j < size / 4; j++) {
custom_initializer_i->constructors[j] = (uint64_t)header + data_ptr[j];
printf("registered initializer at %llx\n", custom_initializer_i->constructors[j]);
custom_initializer_i->constructors[j] =
(uint64_t)header + data_ptr[j];
printf("registered initializer at %llx\n",
custom_initializer_i->constructors[j]);
}
}
if (custom_strcmp(secname, "__mod_init_func") == 0) {
@ -1436,7 +1489,8 @@ void test(struct libcache& cache) {
printf("Indirect search: Found=%p Expected=%p\n", vm_protect_func,
vm_protect);
void *realpath_func = custom_dlsym(&cache, libsystem_hash, "_realpath$DARWIN_EXTSN");
void *realpath_func =
custom_dlsym(&cache, libsystem_hash, "_realpath$DARWIN_EXTSN");
printf("Indirect search: Found=%p Expected=%p\n", realpath_func, realpath);
}
}