run initializers in the correct order
- Objective-C load methods must be called first - Constructors are called after - All constructors arguments are passed correctly
This commit is contained in:
parent
a2f9ca82e7
commit
e15d1e8d6f
@ -656,6 +656,38 @@ int hook_printf(const char *format, ...) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void *(*readClass_t)(void *, bool, bool);
|
||||||
|
typedef void *(*realizeClassWithoutSwift_t)(void *, void*);
|
||||||
|
typedef void *(*remapClass_t)(void *);
|
||||||
|
typedef void *(*load_method_t)(void*, void*);
|
||||||
|
typedef void *(*sel_lookUpByName_t)(const char*);
|
||||||
|
typedef void (*addClassTableEntry_t)(void *);
|
||||||
|
typedef void (*schedule_class_load_t)(void *);
|
||||||
|
|
||||||
|
typedef void *(*objc_autoreleasePoolPush_t)();
|
||||||
|
typedef void (*objc_autoreleasePoolPop_t)(void *);
|
||||||
|
|
||||||
|
struct custom_initializer_t {
|
||||||
|
// used for Objective-C load methods
|
||||||
|
uint64_t* loadable_classes;
|
||||||
|
uint32_t* loadable_classes_used;
|
||||||
|
sel_lookUpByName_t sel_lookUpByName;
|
||||||
|
objc_autoreleasePoolPush_t objc_autoreleasePoolPush;
|
||||||
|
objc_autoreleasePoolPop_t objc_autoreleasePoolPop;
|
||||||
|
remapClass_t remapClass;
|
||||||
|
schedule_class_load_t schedule_class_load;
|
||||||
|
uint64_t* cls;
|
||||||
|
size_t ncls;
|
||||||
|
// used for constructors
|
||||||
|
void* programvars;
|
||||||
|
uint64_t* constructors;
|
||||||
|
size_t nconstructors;
|
||||||
|
};
|
||||||
|
|
||||||
|
// global variable for PoC
|
||||||
|
struct custom_initializer_t* custom_initializer_i;
|
||||||
|
|
||||||
|
|
||||||
struct ProgramVars {
|
struct ProgramVars {
|
||||||
void *mh; // mach_header or mach_header64
|
void *mh; // mach_header or mach_header64
|
||||||
int *NXArgcPtr;
|
int *NXArgcPtr;
|
||||||
@ -701,6 +733,10 @@ bruh(int argc, const char *const argv[], const char *const envp[],
|
|||||||
// (we do not remove them for **our lib**)
|
// (we do not remove them for **our lib**)
|
||||||
// - malloc
|
// - malloc
|
||||||
// - free
|
// - free
|
||||||
|
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;
|
||||||
fix(cache);
|
fix(cache);
|
||||||
|
|
||||||
for (int i = 0; i < cache.size; i++) {
|
for (int i = 0; i < cache.size; i++) {
|
||||||
@ -779,6 +815,7 @@ void build_cache(struct libcache& cache, void* main) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void fix_objc(struct libcache_item* libfixing, struct libcache& cache);
|
void fix_objc(struct libcache_item* libfixing, struct libcache& cache);
|
||||||
void fix_initializer(struct libcache_item* libfixing, struct libcache& cache);
|
void fix_initializer(struct libcache_item* libfixing, struct libcache& cache);
|
||||||
void fix(struct libcache& cache) {
|
void fix(struct libcache& cache) {
|
||||||
@ -942,77 +979,64 @@ void fix(struct libcache& cache) {
|
|||||||
fix_initializer(libfixing, cache);
|
fix_initializer(libfixing, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef void *(*readClass_t)(void *, bool, bool);
|
|
||||||
typedef void *(*realizeClassWithoutSwift_t)(void *, void*);
|
|
||||||
typedef void *(*remapClass_t)(void *);
|
|
||||||
typedef void *(*load_method_t)(void*, void*);
|
|
||||||
typedef void *(*sel_lookUpByName_t)(const char*);
|
|
||||||
typedef void (*addClassTableEntry_t)(void *);
|
|
||||||
typedef void (*schedule_class_load_t)(void *);
|
|
||||||
|
|
||||||
typedef void *(*objc_autoreleasePoolPush_t)();
|
|
||||||
typedef void (*objc_autoreleasePoolPop_t)(void *);
|
|
||||||
|
|
||||||
struct custom_initializer_t {
|
|
||||||
uint64_t* loadable_classes;
|
|
||||||
uint32_t* loadable_classes_used;
|
|
||||||
sel_lookUpByName_t sel_lookUpByName;
|
|
||||||
objc_autoreleasePoolPush_t objc_autoreleasePoolPush;
|
|
||||||
objc_autoreleasePoolPop_t objc_autoreleasePoolPop;
|
|
||||||
remapClass_t remapClass;
|
|
||||||
schedule_class_load_t schedule_class_load;
|
|
||||||
uint64_t* cls;
|
|
||||||
size_t ncls;
|
|
||||||
};
|
|
||||||
|
|
||||||
// global variable for PoC
|
|
||||||
struct custom_initializer_t* custom_initializer_i;
|
|
||||||
|
|
||||||
void volatile
|
void volatile
|
||||||
custom_initializer(int argc, const char *const argv[], const char *const envp[],
|
custom_initializer(int argc, const char *const argv[], const char *const envp[], const char *const apple[]) {
|
||||||
const char *const apple[], const struct ProgramVars *vars) {
|
|
||||||
printf("run custom initializers %p\n", custom_initializer_i);
|
printf("run custom initializers %p\n", custom_initializer_i);
|
||||||
// return;
|
|
||||||
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;
|
|
||||||
remapClass_t remapClass = custom_initializer_i->remapClass;
|
|
||||||
schedule_class_load_t schedule_class_load = custom_initializer_i->schedule_class_load;
|
|
||||||
|
|
||||||
for (int i = 0; i < custom_initializer_i->ncls; i++) {
|
if (custom_initializer_i->cls != 0) {
|
||||||
void* cls0 = (void*)custom_initializer_i->cls[i];
|
// for Objective-C load
|
||||||
void* cls = remapClass(cls0);
|
uint64_t* loadable_classes = custom_initializer_i->loadable_classes;
|
||||||
if (!cls) continue;
|
uint32_t* loadable_classes_used = custom_initializer_i->loadable_classes_used;
|
||||||
schedule_class_load(cls);
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
schedule_class_load(cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int used = *loadable_classes_used;
|
||||||
|
*loadable_classes = 0;
|
||||||
|
// *loadable_classes_allocated = 0;
|
||||||
|
*loadable_classes_used = 0;
|
||||||
|
void* sel = sel_lookUpByName("load");
|
||||||
|
// Call all +loads for the detached list.
|
||||||
|
void* pool = objc_autoreleasePoolPush();
|
||||||
|
for (int i = 0; i < used; i++) {
|
||||||
|
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;
|
||||||
|
(load_method)(cls, sel);
|
||||||
|
}
|
||||||
|
// Destroy the detached list.
|
||||||
|
if (classes) free(classes);
|
||||||
|
objc_autoreleasePoolPop(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("loadable_classes %llx %x\n", *loadable_classes, *loadable_classes_used);
|
// for constructors
|
||||||
|
if (custom_initializer_i->constructors) {
|
||||||
struct loadable_class_t {
|
typedef void *(*constructors_t)(int, void*, void*, void*, void*);
|
||||||
void* cls;
|
uint32_t nconst = custom_initializer_i->nconstructors;
|
||||||
void* method;
|
for (int i = 0; i < nconst; i++) {
|
||||||
};
|
constructors_t cons = (constructors_t)custom_initializer_i->constructors[i];
|
||||||
struct loadable_class_t *classes = (struct loadable_class_t*)*loadable_classes;
|
printf("call initializer at %p\n", cons);
|
||||||
int used = *loadable_classes_used;
|
cons(argc, (void*)argv, (void*)envp, (void*)apple, custom_initializer_i->programvars);
|
||||||
*loadable_classes = 0;
|
}
|
||||||
// *loadable_classes_allocated = 0;
|
free(custom_initializer_i->constructors);
|
||||||
*loadable_classes_used = 0;
|
|
||||||
void* sel = sel_lookUpByName("load");
|
|
||||||
// Call all +loads for the detached list.
|
|
||||||
void* pool = objc_autoreleasePoolPush();
|
|
||||||
for (int i = 0; i < used; i++) {
|
|
||||||
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;
|
|
||||||
(load_method)(cls, sel);
|
|
||||||
}
|
}
|
||||||
// Destroy the detached list.
|
|
||||||
if (classes) free(classes);
|
|
||||||
objc_autoreleasePoolPop(pool);
|
|
||||||
|
|
||||||
free(custom_initializer_i);
|
free(custom_initializer_i);
|
||||||
}
|
}
|
||||||
@ -1119,7 +1143,6 @@ void fix_objc(struct libcache_item* libfixing, struct libcache& cache) {
|
|||||||
printf("build nonlazy class at (%llx)%p\n", data_ptr[ptr_i], cls);
|
printf("build nonlazy class at (%llx)%p\n", data_ptr[ptr_i], cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
custom_initializer_i = (custom_initializer_t*)malloc(sizeof(custom_initializer_t));
|
|
||||||
custom_initializer_i->sel_lookUpByName = sel_lookUpByName;
|
custom_initializer_i->sel_lookUpByName = sel_lookUpByName;
|
||||||
custom_initializer_i->loadable_classes = loadable_classes;
|
custom_initializer_i->loadable_classes = loadable_classes;
|
||||||
custom_initializer_i->loadable_classes_used = loadable_classes_used;
|
custom_initializer_i->loadable_classes_used = loadable_classes_used;
|
||||||
@ -1248,6 +1271,17 @@ void fix_initializer(struct libcache_item* libfixing, struct libcache& cache) {
|
|||||||
uint32_t *data_ptr = (uint32_t*)(addr + slide);
|
uint32_t *data_ptr = (uint32_t*)(addr + slide);
|
||||||
|
|
||||||
printf("found initializer at %p\n", data_ptr);
|
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);
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (custom_strcmp(secname, "__mod_init_func") == 0) {
|
||||||
|
// TODO: EHEHE
|
||||||
|
printf("initializer encoded in __mod_init_func is not supported\n");
|
||||||
}
|
}
|
||||||
sections_ptr += 16 * 2 + 8 * 2 + 4 * 8;
|
sections_ptr += 16 * 2 + 8 * 2 + 4 * 8;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user