mirror of
https://github.com/khanhduytran0/coruna.git
synced 2026-04-24 04:36:28 +02:00
106 lines
3.6 KiB
Objective-C
106 lines
3.6 KiB
Objective-C
@import Darwin;
|
|
@import MachO;
|
|
@import UIKit;
|
|
#include <mach-o/ldsyms.h> /* _mh_dylib_header */
|
|
|
|
// Function pointers
|
|
extern pthread_t pthread_main_thread_np(void);
|
|
extern void _pthread_set_self(pthread_t p);
|
|
void (*_abort)(void);
|
|
int (*_close)(int);
|
|
void * (*_dlsym)(void *, const char *);
|
|
thread_t (*_mach_thread_self)(void);
|
|
int (*_open)(const char *, int, ...);
|
|
void (*__pthread_set_self)(pthread_t p);
|
|
pthread_t (*_pthread_main_thread_np)(void);
|
|
int (*_strncmp)(const char *s1, const char *s2, size_t n);
|
|
kern_return_t (*_thread_terminate)(mach_port_t);
|
|
int (*_write)(int, const void *, size_t);
|
|
|
|
int shellcode_init(void * (*_dlsym)(void* handle, const char* symbol), const char *next_stage_dylib_path);
|
|
|
|
static uintptr_t _get_text_vmaddr(const struct mach_header_64 *mh) {
|
|
struct load_command *lc = (void*)((uintptr_t)mh + sizeof(struct mach_header_64));
|
|
for (uint32_t i = 0; i < mh->ncmds; i++, lc = (void*)((uint8_t*)lc + lc->cmdsize)) {
|
|
if (lc->cmd != LC_SEGMENT_64) continue;
|
|
struct segment_command_64 *seg = (void*)lc;
|
|
if (_strncmp(seg->segname, "__TEXT", 6) == 0)
|
|
return seg->vmaddr;
|
|
}
|
|
return 0;
|
|
}
|
|
static size_t macho_size_from_header(const struct mach_header_64 *mh) {
|
|
uintptr_t base = (uintptr_t)mh;
|
|
uintptr_t text_vm = _get_text_vmaddr(mh);
|
|
uintptr_t slide = base - text_vm; // ASLR slide
|
|
|
|
struct load_command *lc = (void*)(base + sizeof(struct mach_header_64));
|
|
for (uint32_t i = 0; i < mh->ncmds; i++, lc = (void*)((uint8_t*)lc + lc->cmdsize)) {
|
|
if (lc->cmd != LC_SEGMENT_64) continue;
|
|
struct segment_command_64 *seg = (void*)lc;
|
|
if (_strncmp(seg->segname, "__LINKEDIT", 10) != 0) continue;
|
|
|
|
// vmaddr + slide = actual mapped address of __LINKEDIT
|
|
// end = that + vmsize
|
|
return (seg->vmaddr + slide + seg->vmsize) - base;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const char *save_myself(void) {
|
|
const char *path = "/tmp/SpringBoardTweak.dylib";
|
|
const struct mach_header_64 *header = (struct mach_header_64 *)&_mh_dylib_header;
|
|
size_t size = macho_size_from_header(header);
|
|
int fd = _open(path, O_RDWR | O_CREAT | O_TRUNC, 0755);
|
|
if (fd < 0) _abort();
|
|
|
|
if (_write(fd, header, size) != size) {
|
|
_abort();
|
|
}
|
|
_close(fd);
|
|
return path;
|
|
}
|
|
|
|
#if __arm64e__
|
|
__attribute__((noinline)) void *pacia(void* ptr, uint64_t ctx) {
|
|
__asm__("xpaci %[value]\n" : [value] "+r"(ptr));
|
|
__asm__("pacia %0, %1" : "+r"(ptr) : "r"(ctx));
|
|
return ptr;
|
|
}
|
|
#endif
|
|
|
|
// Entry point when loaded by Coruna
|
|
int last(void) {
|
|
#if __arm64e__
|
|
_dlsym = pacia(dlsym, 0);
|
|
__pthread_set_self = pacia(_pthread_set_self, 0);
|
|
_pthread_main_thread_np = pacia(pthread_main_thread_np, 0);
|
|
#else
|
|
_dlsym = dlsym;
|
|
__pthread_set_self = _pthread_set_self;
|
|
_pthread_main_thread_np = pthread_main_thread_np;
|
|
#endif
|
|
__pthread_set_self(_pthread_main_thread_np());
|
|
|
|
_abort = _dlsym(RTLD_DEFAULT, "abort");
|
|
_close = _dlsym(RTLD_DEFAULT, "close");
|
|
_mach_thread_self = _dlsym(RTLD_DEFAULT, "mach_thread_self");
|
|
_open = _dlsym(RTLD_DEFAULT, "open");
|
|
_strncmp = _dlsym(RTLD_DEFAULT, "strncmp");
|
|
_thread_terminate = _dlsym(RTLD_DEFAULT, "thread_terminate");
|
|
_write = _dlsym(RTLD_DEFAULT, "write");
|
|
|
|
// setup dyld validation bypass
|
|
const char *path = save_myself();
|
|
shellcode_init(_dlsym, path);
|
|
|
|
// should not return
|
|
_thread_terminate(_mach_thread_self());
|
|
return 0;
|
|
}
|
|
int end(void) {
|
|
// should never be called
|
|
return 0;
|
|
}
|