-
-
Save LukeZGD/244d7dc3f07ec98a4505e4084c5dbf6b to your computer and use it in GitHub Desktop.
patch restored external for iPhone X downgrades
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #define _GNU_SOURCE | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <stdint.h> | |
| #include <string.h> | |
| // the following few functions are from patchfinder64 | |
| #define GET_OFFSET(len, x) (x - (uintptr_t) restored_external) | |
| typedef unsigned long long addr_t; | |
| static uint32_t arm64_branch_instruction(uintptr_t from, uintptr_t to) { | |
| return from > to ? 0x18000000 - (from - to) / 4 : 0x14000000 + (to - from) / 4; | |
| } | |
| static addr_t | |
| xref64(const uint8_t *buf, addr_t start, addr_t end, addr_t what) | |
| { | |
| addr_t i; | |
| uint64_t value[32]; | |
| memset(value, 0, sizeof(value)); | |
| end &= ~3; | |
| for (i = start & ~3; i < end; i += 4) { | |
| uint32_t op = *(uint32_t *)(buf + i); | |
| unsigned reg = op & 0x1F; | |
| if ((op & 0x9F000000) == 0x90000000) { | |
| signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8); | |
| //printf("%llx: ADRP X%d, 0x%llx\n", i, reg, ((long long)adr << 1) + (i & ~0xFFF)); | |
| value[reg] = ((long long)adr << 1) + (i & ~0xFFF); | |
| continue; // XXX should not XREF on its own? | |
| /*} else if ((op & 0xFFE0FFE0) == 0xAA0003E0) { | |
| unsigned rd = op & 0x1F; | |
| unsigned rm = (op >> 16) & 0x1F; | |
| //printf("%llx: MOV X%d, X%d\n", i, rd, rm); | |
| value[rd] = value[rm];*/ | |
| } else if ((op & 0xFF000000) == 0x91000000) { | |
| unsigned rn = (op >> 5) & 0x1F; | |
| unsigned shift = (op >> 22) & 3; | |
| unsigned imm = (op >> 10) & 0xFFF; | |
| if (shift == 1) { | |
| imm <<= 12; | |
| } else { | |
| //assert(shift == 0); | |
| if (shift > 1) continue; | |
| } | |
| //printf("%llx: ADD X%d, X%d, 0x%x\n", i, reg, rn, imm); | |
| value[reg] = value[rn] + imm; | |
| } else if ((op & 0xF9C00000) == 0xF9400000) { | |
| unsigned rn = (op >> 5) & 0x1F; | |
| unsigned imm = ((op >> 10) & 0xFFF) << 3; | |
| //printf("%llx: LDR X%d, [X%d, 0x%x]\n", i, reg, rn, imm); | |
| if (!imm) continue; // XXX not counted as true xref | |
| value[reg] = value[rn] + imm; // XXX address, not actual value | |
| /*} else if ((op & 0xF9C00000) == 0xF9000000) { | |
| unsigned rn = (op >> 5) & 0x1F; | |
| unsigned imm = ((op >> 10) & 0xFFF) << 3; | |
| //printf("%llx: STR X%d, [X%d, 0x%x]\n", i, reg, rn, imm); | |
| if (!imm) continue; // XXX not counted as true xref | |
| value[rn] = value[rn] + imm; // XXX address, not actual value*/ | |
| } else if ((op & 0x9F000000) == 0x10000000) { | |
| signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8); | |
| //printf("%llx: ADR X%d, 0x%llx\n", i, reg, ((long long)adr >> 11) + i); | |
| value[reg] = ((long long)adr >> 11) + i; | |
| } else if ((op & 0xFF000000) == 0x58000000) { | |
| unsigned adr = (op & 0xFFFFE0) >> 3; | |
| //printf("%llx: LDR X%d, =0x%llx\n", i, reg, adr + i); | |
| value[reg] = adr + i; // XXX address, not actual value | |
| } | |
| if (value[reg] == what) { | |
| return i; | |
| } | |
| } | |
| return 0; | |
| } | |
| static addr_t | |
| bof64(const uint8_t *buf, addr_t start, addr_t where) | |
| { | |
| for (; where >= start; where -= 4) { | |
| uint32_t op = *(uint32_t *)(buf + where); | |
| if ((op & 0xFFC003FF) == 0x910003FD) { | |
| unsigned delta = (op >> 10) & 0xFFF; | |
| //printf("%x: ADD X29, SP, #0x%x\n", where, delta); | |
| if ((delta & 0xF) == 0) { | |
| addr_t prev = where - ((delta >> 4) + 1) * 4; | |
| uint32_t au = *(uint32_t *)(buf + prev); | |
| if ((au & 0xFFC003E0) == 0xA98003E0) { | |
| //printf("%x: STP x, y, [SP,#-imm]!\n", prev); | |
| return prev; | |
| } | |
| // try something else | |
| while (where > start) { | |
| where -= 4; | |
| au = *(uint32_t *)(buf + where); | |
| // SUB SP, SP, #imm | |
| if ((au & 0xFFC003FF) == 0xD10003FF && ((au >> 10) & 0xFFF) == delta + 0x10) { | |
| return where; | |
| } | |
| // STP x, y, [SP,#imm] | |
| if ((au & 0xFFC003E0) != 0xA90003E0) { | |
| where += 4; | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return 0; | |
| } | |
| uint32_t* find_next_insn(uint32_t* from, uint32_t num, uint32_t insn, uint32_t mask) | |
| { | |
| while(num) | |
| { | |
| // printf("from: %p, num: %d, insn: %x, mask: %x\n", from, num, insn, mask); | |
| if((*from & mask) == (insn & mask)) | |
| { | |
| return from; | |
| } | |
| from++; | |
| num--; | |
| } | |
| return NULL; | |
| } | |
| uint32_t* find_prev_insn(uint32_t* from, uint32_t num, uint32_t insn, uint32_t mask) | |
| { | |
| while(num) | |
| { | |
| if((*from & mask) == (insn & mask)) | |
| { | |
| return from; | |
| } | |
| from--; | |
| num--; | |
| } | |
| return NULL; | |
| } | |
| int get_faceid_patch(void *restored_external, size_t len) { | |
| printf("getting %s()\n", __FUNCTION__); | |
| void *str_ref = memmem(restored_external, len, "refFrame", strlen("refFrame")); | |
| if (!str_ref) { | |
| printf("[-] Failed to find string refFrame\n"); | |
| return -1; | |
| } | |
| addr_t xref = xref64(restored_external, 0, len, GET_OFFSET(len, (uintptr_t)str_ref)); | |
| if (!xref) { | |
| printf("[-] Failed to find xref to refFrame\n"); | |
| return -1; | |
| } | |
| // printf("[+] Found xref to refFrame at 0x%llx\n", xref); | |
| // go to the next ret | |
| uint32_t *insn = find_next_insn((uint32_t *)(restored_external + xref), 0x300, 0xD65F03C0, 0xFFFFFFFF); | |
| if (!insn) { | |
| printf("[-] Failed to find next ret\n"); | |
| return -1; | |
| } | |
| // printf("[+] Found next ret at 0x%lx\n", (uintptr_t)insn - (uintptr_t)restored_external); | |
| insn = find_prev_insn(insn, 0x100, 0xAA000000, 0xFF000000); | |
| if (!insn) { | |
| printf("[-] Failed to find prev mov\n"); | |
| return -1; | |
| } | |
| // printf("[+] Found prev mov at 0x%lx\n", (uintptr_t)insn - (uintptr_t)restored_external); | |
| printf("[+] Patching decompressReferenceFrames patch point at 0x%lx\n", (uintptr_t)insn - (uintptr_t)restored_external); | |
| *insn = 0xD2800000; // mov x0, #0 | |
| printf("[+] Patched decompressReferenceFrames\n"); | |
| return 0; | |
| } | |
| int main(int argc, char* argv[]) { | |
| printf("restored patcher by @mineekdev\n"); | |
| if (argc < 3) { | |
| printf("usage: %s <restored_external> <restored_external.patched>\n", argv[0]); | |
| return -1; | |
| } | |
| char *in = argv[1]; | |
| char *out = argv[2]; | |
| void *restored_external; | |
| size_t len; | |
| FILE* fp = fopen(in, "rb"); | |
| if (!fp) { | |
| printf("failed to open %s, does it exist?\n", in); | |
| return -1; | |
| } | |
| fseek(fp, 0, SEEK_END); | |
| len = ftell(fp); | |
| fseek(fp, 0, SEEK_SET); | |
| restored_external = (void*)malloc(len); | |
| if(!restored_external) { | |
| printf("malloc failed\n"); | |
| fclose(fp); | |
| return -1; | |
| } | |
| fread(restored_external, 1, len, fp); | |
| fclose(fp); | |
| get_faceid_patch(restored_external, len); | |
| printf("Patched file to %s\n", out); | |
| fp = fopen(out, "wb+"); | |
| fwrite(restored_external, 1, len, fp); | |
| fflush(fp); | |
| fclose(fp); | |
| free(restored_external); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment