diff options
Diffstat (limited to 'src/gen/patchfinder.c')
| -rw-r--r-- | src/gen/patchfinder.c | 805 |
1 files changed, 805 insertions, 0 deletions
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 <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 |
