From a1c11f713a28f6993e49e86acf1b78e500f78b9f Mon Sep 17 00:00:00 2001 From: tihmstar Date: Fri, 14 Jun 2024 08:07:33 +0200 Subject: [PATCH 01/15] add check for macho-o header --- configure.ac | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/configure.ac b/configure.ac index 81cf4ec..55bd17e 100644 --- a/configure.ac +++ b/configure.ac @@ -158,6 +158,20 @@ fi AM_CONDITIONAL(WITH_WTFPWNDFU, test x$with_wtfpwndfu == xyes) # Checks for header files. + +AC_CHECK_HEADERS([mach-o/loader.h mach-o/nlist.h], [ + AC_DEFINE(HAVE_MACHO_O_HEADER, 1, [Define if you have apple cctools headers]) + AC_SUBST([HAVE_MACHO_O_HEADER], [1]) + have_macho_header=yes; +], [ + AC_SUBST([HAVE_MACHO_O_HEADER], [0]) + have_macho_header=no; +], []) + +if test "x$have_macho_header" != "xyes"; then + AC_MSG_ERROR(["Macho-O headers not found, are apple cctools headers installed?"]) +fi + AC_CHECK_HEADERS([fcntl.h stdint.h stdlib.h string.h unistd.h arpa/inet.h winsock.h]) # Check for functions @@ -183,6 +197,7 @@ Configuration for $PACKAGE-$VERSION: install prefix ..........: $prefix have img4tool ...........: $with_img4tool have img3tool ...........: $with_img3tool + have mach-o header.......: $have_macho_header debug build ............: $debug_build asan build .............: $asan_build with binrider ...........: $with_binrider From f932db7ea242cb50aa5b51a842ecbcd4d7ec1581 Mon Sep 17 00:00:00 2001 From: Elcomsoft R&D Date: Thu, 25 Jul 2024 10:40:10 +0200 Subject: [PATCH 02/15] update --- .github/FUNDING.yml | 13 -- configure.ac | 13 +- .../ibootpatchfinder/ibootpatchfinder64.hpp | 1 - include/libpatchfinder/patch.hpp | 12 +- libpatchfinder.xcodeproj/project.pbxproj | 6 + .../ibootpatchfinder32_base.cpp | 36 ++--- .../ibootpatchfinder32_base.hpp | 1 + .../ibootpatchfinder/ibootpatchfinder64.cpp | 6 - .../ibootpatchfinder64_base.cpp | 86 +++++++---- .../ibootpatchfinder64_base.hpp | 1 + .../ibootpatchfinder64_iOS10.cpp | 61 -------- .../ibootpatchfinder64_iOS10.hpp | 5 - .../ibootpatchfinder64_iOS12.cpp | 118 +++++++++------ .../ibootpatchfinder64_iOS13.cpp | 139 +++++++++++++++++- .../ibootpatchfinder64_iOS13.hpp | 9 +- .../ibootpatchfinder64_iOS14.cpp | 2 + libpatchfinder/kernelpatchfinder/Makefile.am | 1 + .../kernelpatchfinder32_base.cpp | 4 +- .../kernelpatchfinder/kernelpatchfinder64.cpp | 4 + .../kernelpatchfinder64_base.cpp | 40 +++-- .../kernelpatchfinder64_iOS8.cpp | 32 ++++ .../kernelpatchfinder64_iOS8.hpp | 24 +++ .../kernelpatchfinder64_iOS9.hpp | 6 +- libpatchfinder/machopatchfinder64.cpp | 1 + libpatchfinder/main.cpp | 17 ++- libpatchfinder/patch.cpp | 22 ++- libpatchfinder/patchfinder64.cpp | 21 +-- 27 files changed, 440 insertions(+), 241 deletions(-) delete mode 100644 .github/FUNDING.yml create mode 100644 libpatchfinder/kernelpatchfinder/kernelpatchfinder64_iOS8.cpp create mode 100644 libpatchfinder/kernelpatchfinder/kernelpatchfinder64_iOS8.hpp diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index fb56cba..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,13 +0,0 @@ -# These are supported funding model platforms - -github: [tihmstar] -patreon: tihmstar -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -otechie: # Replace with a single Otechie username -lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/configure.ac b/configure.ac index 55bd17e..a395706 100644 --- a/configure.ac +++ b/configure.ac @@ -38,10 +38,10 @@ CFLAGS+=" -std=c11" CXXFLAGS+=" -D EXPECTIONNAME=OFexception" # Checks for libraries. -IMG4TOOL_REQUIRES_STR="libimg4tool >= 202" -IMG3TOOL_REQUIRES_STR="libimg3tool >= 8" -LIBGENERAL_REQUIRES_STR="libgeneral >= 75" -LIBINSN_REQUIRES_STR="libinsn >= 49" +IMG4TOOL_REQUIRES_STR="libimg4tool >= 198" +IMG3TOOL_REQUIRES_STR="libimg3tool >= 2" +LIBGENERAL_REQUIRES_STR="libgeneral >= 65" +LIBINSN_REQUIRES_STR="libinsn >= 38" PKG_CHECK_MODULES(libimg4tool, $IMG4TOOL_REQUIRES_STR, have_img4tool=yes, have_img4tool=no) PKG_CHECK_MODULES(libimg3tool, $IMG3TOOL_REQUIRES_STR, have_img3tool=yes, have_img3tool=no) PKG_CHECK_MODULES(libgeneral, $LIBGENERAL_REQUIRES_STR) @@ -159,6 +159,8 @@ AM_CONDITIONAL(WITH_WTFPWNDFU, test x$with_wtfpwndfu == xyes) # Checks for header files. +ORIG_CFLAGS=${CFLAGS} +CFLAGS+=" -I${lt_sysroot}/include -I${lt_sysroot}/${prefix}/include -I${lt_sysroot}/${ac_default_prefix}/include" AC_CHECK_HEADERS([mach-o/loader.h mach-o/nlist.h], [ AC_DEFINE(HAVE_MACHO_O_HEADER, 1, [Define if you have apple cctools headers]) AC_SUBST([HAVE_MACHO_O_HEADER], [1]) @@ -167,6 +169,7 @@ AC_CHECK_HEADERS([mach-o/loader.h mach-o/nlist.h], [ AC_SUBST([HAVE_MACHO_O_HEADER], [0]) have_macho_header=no; ], []) +CFLAGS=${ORIG_CFLAGS} if test "x$have_macho_header" != "xyes"; then AC_MSG_ERROR(["Macho-O headers not found, are apple cctools headers installed?"]) @@ -187,7 +190,7 @@ AC_CONFIG_FILES([Makefile tools/Makefile tools/binrider/Makefile tools/offsetexporter/Makefile - libpatchfinder.pc]) + libpatchfinder.pc]) AC_OUTPUT echo " diff --git a/include/libpatchfinder/ibootpatchfinder/ibootpatchfinder64.hpp b/include/libpatchfinder/ibootpatchfinder/ibootpatchfinder64.hpp index 12b6cb7..143a075 100644 --- a/include/libpatchfinder/ibootpatchfinder/ibootpatchfinder64.hpp +++ b/include/libpatchfinder/ibootpatchfinder/ibootpatchfinder64.hpp @@ -26,7 +26,6 @@ namespace tihmstar { class ibootpatchfinder64 : public patchfinder64, public ibootpatchfinder { protected: ibootpatchfinder64(bool freeBuf); - ibootpatchfinder64(ibootpatchfinder64 &&mv); public: static ibootpatchfinder64 *make_ibootpatchfinder64(const char *filename); diff --git a/include/libpatchfinder/patch.hpp b/include/libpatchfinder/patch.hpp index 5d9bc48..c82ec2d 100644 --- a/include/libpatchfinder/patch.hpp +++ b/include/libpatchfinder/patch.hpp @@ -15,17 +15,19 @@ namespace tihmstar { namespace patchfinder{ class patch{ + void *_patch; + size_t _patchSize; bool _slideme; - bool _dofree; void(*_slidefunc)(class patch *patch, uint64_t slide); public: uint64_t _location; - size_t _patchSize; - const void *_patch; - patch(uint64_t location, const void *patch, size_t patchSize, void(*slidefunc)(class patch *patch, uint64_t slide) = NULL, bool dofree = true); + patch(uint64_t location, const void *patch, size_t patchSize, void(*slidefunc)(class patch *patch, uint64_t slide) = NULL); patch(const patch& cpy) noexcept; ~patch(); - + + inline const void *getPatch(){return _patch;} + inline size_t getPatchSize(){return _patchSize;} + patch &operator=(const patch& cpy); void slide(uint64_t slide); }; diff --git a/libpatchfinder.xcodeproj/project.pbxproj b/libpatchfinder.xcodeproj/project.pbxproj index b7a4121..b3452b5 100644 --- a/libpatchfinder.xcodeproj/project.pbxproj +++ b/libpatchfinder.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 2A0D862E2BF4FABC00CE4FA7 /* kernelpatchfinder64_iOS8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A0D862C2BF4FABC00CE4FA7 /* kernelpatchfinder64_iOS8.cpp */; }; 2A102B482ADD3CDD00F86D9E /* ibootpatchfinder32_iOS8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A102B462ADD3CDD00F86D9E /* ibootpatchfinder32_iOS8.cpp */; }; 2A32E5DE2A41CD5A007170DA /* kernelpatchfinder64_iOS17.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A32E5DC2A41CD5A007170DA /* kernelpatchfinder64_iOS17.cpp */; }; 2A44ABC12A84C0650076F87C /* StableHash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8739AE2F2A6B48E000630CEA /* StableHash.cpp */; }; @@ -167,6 +168,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2A0D862C2BF4FABC00CE4FA7 /* kernelpatchfinder64_iOS8.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = kernelpatchfinder64_iOS8.cpp; sourceTree = ""; }; + 2A0D862D2BF4FABC00CE4FA7 /* kernelpatchfinder64_iOS8.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = kernelpatchfinder64_iOS8.hpp; sourceTree = ""; }; 2A102B462ADD3CDD00F86D9E /* ibootpatchfinder32_iOS8.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ibootpatchfinder32_iOS8.cpp; sourceTree = ""; }; 2A102B472ADD3CDD00F86D9E /* ibootpatchfinder32_iOS8.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ibootpatchfinder32_iOS8.hpp; sourceTree = ""; }; 2A32E5DC2A41CD5A007170DA /* kernelpatchfinder64_iOS17.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = kernelpatchfinder64_iOS17.cpp; sourceTree = ""; }; @@ -472,6 +475,8 @@ 87C7D5B22854D9EC001CE584 /* sbops64.h */, 87F0A57626A5BD950090C657 /* kernelpatchfinder64_base.hpp */, 8738E8FA2695981A00C03872 /* kernelpatchfinder64_base.cpp */, + 2A0D862D2BF4FABC00CE4FA7 /* kernelpatchfinder64_iOS8.hpp */, + 2A0D862C2BF4FABC00CE4FA7 /* kernelpatchfinder64_iOS8.cpp */, 87F0A57526A5BD950090C657 /* kernelpatchfinder64_iOS9.hpp */, 8738E8FC2695981A00C03872 /* kernelpatchfinder64_iOS9.cpp */, 87F0A57426A5BD950090C657 /* kernelpatchfinder64_iOS12.hpp */, @@ -653,6 +658,7 @@ 8738E8F7269597FE00C03872 /* ibootpatchfinder64.cpp in Sources */, 8738E87226945D5300C03872 /* patchfinder64.cpp in Sources */, 8738E91426959AEE00C03872 /* ibootpatchfinder32_base.cpp in Sources */, + 2A0D862E2BF4FABC00CE4FA7 /* kernelpatchfinder64_iOS8.cpp in Sources */, 8738E88626945EE500C03872 /* patchfinder32.cpp in Sources */, 87F8453A2771C93D0018347B /* ibootpatchfinder32_iOS12.cpp in Sources */, 8738E8F4269597FE00C03872 /* ibootpatchfinder64_iOS12.cpp in Sources */, diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder32_base.cpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder32_base.cpp index 37056e0..c11fbf1 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder32_base.cpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder32_base.cpp @@ -31,34 +31,17 @@ using namespace tihmstar::libinsn::arm32; ibootpatchfinder32_base::ibootpatchfinder32_base(const char * filename) : ibootpatchfinder32(true) { - struct stat fs = {0}; - int fd = 0; - bool didConstructSuccessfully = false; + int fd = -1; cleanup([&]{ - if (fd>0) close(fd); - if (!didConstructSuccessfully) { - safeFreeConst(_buf); - } + safeClose(fd); }) - + struct stat fs = {0}; + assure((fd = open(filename, O_RDONLY)) != -1); assure(!fstat(fd, &fs)); assure((_buf = (uint8_t*)malloc( _bufSize = fs.st_size))); assure(read(fd,(void*)_buf,_bufSize)==_bufSize); - - assure(_bufSize > 0x1000); - - assure(!strncmp((char*)&_buf[IBOOT_VERS_STR_OFFSET], "iBoot", sizeof("iBoot")-1)); - retassure(*(uint32_t*)&_buf[0] == IBOOT32_RESET_VECTOR_BYTES, "invalid magic"); - - _entrypoint = _base = (loc_t)((*(uint32_t*)&_buf[0x20]) & ~0xFFF); - debug("iBoot base at=0x%08x", _base); - _vmemThumb = new vmem_thumb({{_buf,_bufSize,_base, (vmprot)(kVMPROTREAD | kVMPROTWRITE | kVMPROTEXEC)}}); - _vmemArm = new vmem_arm({{_buf,_bufSize,_base, (vmprot)(kVMPROTREAD | kVMPROTWRITE | kVMPROTEXEC)}}); - retassure(_vers = atoi((char*)&_buf[IBOOT_VERS_STR_OFFSET+6]), "No iBoot version found!\n"); - debug("iBoot-%d inputted", _vers); - - didConstructSuccessfully = true; + init(); } ibootpatchfinder32_base::ibootpatchfinder32_base(const void *buffer, size_t bufSize, bool takeOwnership) @@ -66,12 +49,18 @@ ibootpatchfinder32_base::ibootpatchfinder32_base(const void *buffer, size_t bufS { _bufSize = bufSize; _buf = (uint8_t*)buffer; + init(); +} + +void ibootpatchfinder32_base::init(){ assure(_bufSize > 0x1000); retassure(*(uint32_t*)&_buf[0] == IBOOT32_RESET_VECTOR_BYTES, "invalid magic"); _entrypoint = _base = (loc_t)((*(uint32_t*)&_buf[0x20]) & ~0xFFF); debug("iBoot base at=0x%08x", _base); + safeDelete(_vmemThumb); + safeDelete(_vmemArm); _vmemThumb = new vmem_thumb({{_buf,_bufSize,_base, (vmprot)(kVMPROTREAD | kVMPROTWRITE | kVMPROTEXEC)}}); _vmemArm = new vmem_arm({{_buf,_bufSize,_base, (vmprot)(kVMPROTREAD | kVMPROTWRITE | kVMPROTEXEC)}}); @@ -79,7 +68,7 @@ ibootpatchfinder32_base::ibootpatchfinder32_base(const void *buffer, size_t bufS retassure(_vers = atoi((char*)&_buf[IBOOT_VERS_STR_OFFSET+6]), "No iBoot version found!\n"); }else{ //iOS 1 iBoot?? - loc_t ibootstrloc = memmem("iBoot-", sizeof("iBoot-")-1); + loc_t ibootstrloc = (loc_t)memmem("iBoot-", sizeof("iBoot-")-1); retassure(ibootstrloc, "No iBoot version found!\n"); const char *ibootstr = (char*)memoryForLoc(ibootstrloc); retassure(_vers = atoi(ibootstr+6), "No iBoot version found!\n"); @@ -91,6 +80,7 @@ ibootpatchfinder32_base::~ibootpatchfinder32_base(){ // } +#pragma mark public bool ibootpatchfinder32_base::has_kernel_load(){ try { return (bool) (memstr(KERNELCACHE_PREP_STRING) != 0); diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder32_base.hpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder32_base.hpp index 9e8365a..eb3ec7e 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder32_base.hpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder32_base.hpp @@ -21,6 +21,7 @@ namespace tihmstar { namespace patchfinder { class ibootpatchfinder32_base : public ibootpatchfinder32{ + void init(); public: ibootpatchfinder32_base(const char *filename); ibootpatchfinder32_base(const void *buffer, size_t bufSize, bool takeOwnership = false); diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64.cpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64.cpp index d53eb41..b56979e 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64.cpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64.cpp @@ -38,12 +38,6 @@ ibootpatchfinder64::ibootpatchfinder64(bool freeBuf) // } -ibootpatchfinder64::ibootpatchfinder64(ibootpatchfinder64 &&mv) -: patchfinder64(std::move(mv)) -{ - _vers = mv._vers; -} - ibootpatchfinder64 *ibootpatchfinder64::make_ibootpatchfinder64(const char * filename){ bool didConstructSuccessfully = false; int fd = 0; diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_base.cpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_base.cpp index 17b28f4..1ba40d2 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_base.cpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_base.cpp @@ -31,23 +31,18 @@ using namespace tihmstar::libinsn::arm64; ibootpatchfinder64_base::ibootpatchfinder64_base(const char * filename) : ibootpatchfinder64(true) { - int fd = 0; - void *buf = NULL; + int fd = -1; cleanup([&]{ safeClose(fd); - safeFree(buf); }) - size_t bufSize = 0; struct stat fs = {}; - + assure((fd = open(filename, O_RDONLY)) != -1); assure(!fstat(fd, &fs)); - assure((buf = (uint8_t*)malloc( bufSize = fs.st_size))); - assure(read(fd,(void*)buf,bufSize)==bufSize); + assure((_buf = (uint8_t*)malloc(_bufSize = fs.st_size))); + assure(read(fd,(void*)_buf,_bufSize)==_bufSize); - assure(bufSize > 0x1000); - this->make_ibootpatchfinder64(buf, bufSize, true); - buf = NULL; + init(); } ibootpatchfinder64_base::ibootpatchfinder64_base(const void *buffer, size_t bufSize, bool takeOwnership) @@ -55,6 +50,10 @@ ibootpatchfinder64_base::ibootpatchfinder64_base(const void *buffer, size_t bufS { _bufSize = bufSize; _buf = (uint8_t*)buffer; + init(); +} + +void ibootpatchfinder64_base::init(){ assure(_bufSize > 0x1000); assure(!strncmp((char*)&_buf[IBOOT_VERS_STR_OFFSET], "iBoot", sizeof("iBoot")-1)); @@ -65,6 +64,7 @@ ibootpatchfinder64_base::ibootpatchfinder64_base(const void *buffer, size_t bufS _entrypoint = _base = (loc_t)*(uint64_t*)&_buf[iBOOT_BASE_OFFSET]; debug("iBoot base at=0x%016llx\n", _base); + safeDelete(_vmem); _vmem = new vmem({{_buf,_bufSize,_base, (vmprot)(kVMPROTREAD | kVMPROTWRITE | kVMPROTEXEC)}}); retassure(_vers = atoi((char*)&_buf[IBOOT_VERS_STR_OFFSET+6]), "No iBoot version found!\n"); debug("iBoot-%d inputted\n", _vers); @@ -74,6 +74,7 @@ ibootpatchfinder64_base::~ibootpatchfinder64_base(){ // } +#pragma mark public bool ibootpatchfinder64_base::has_kernel_load(){ try { return (bool) (_vmem->memstr(KERNELCACHE_PREP_STRING) != 0); @@ -457,6 +458,9 @@ std::vector ibootpatchfinder64_base::replace_cmd_with_memcpy(const char * pushINSN(insn::new_immediate_cmp(cPC, 4, 0)); pushINSN(insn::new_immediate_bcond(cPC, shellcode+insnRet*4, insn::cond::NE)); + /* + iPhone 5s iOS 12 still uses 0x30+0x28*x formula + */ pushINSN(insn::new_immediate_ldr_unsigned(cPC, 0x30+0x28*2, 1, 2)); pushINSN(insn::new_immediate_ldr_unsigned(cPC, 0x30+0x28*0, 1, 0)); pushINSN(insn::new_immediate_ldr_unsigned(cPC, 0x30+0x28*1, 1, 1)); @@ -518,40 +522,58 @@ std::vector ibootpatchfinder64_base::get_ra1nra1n_patch(){ loc_t findloc = memmem("\x12\x00\x80\xd2", 4); debug("findloc=0x%016llx\n",findloc); - constexpr const char patch[] = "\xE8\x03\x1D\xAA\xE9\x03\x1D\xAA\x1B\x01\xC0\xD2\x1B\x00\xA3\xF2\xFD\x03\x1B\xAA"; - - patches.push_back({findloc,patch,sizeof(patch)-1}); + auto iter = _vmem->getIter(findloc); + while (++iter != insn::mov && iter().rd() != 30){ + retassure(iter() != insn::ret, "got unexpected ret!"); + } + uint8_t srcreg = iter().rm(); + + findloc-=4; + pushINSN(insn::new_register_mov(findloc+=4, 0, 8, srcreg)); + pushINSN(insn::new_register_mov(findloc+=4, 0, 9, srcreg)); + /* + 0x7000 iOS 12 buffers the ramdisk at 0x818000000. If we write ra1nra1n there, the ramdisk gets corrupted + */ + pushINSN(insn::new_immediate_movz(findloc+=4, 0x8, 27, 32)); + pushINSN(insn::new_immediate_movk(findloc+=4, 0x2000, 27, 16)); + pushINSN(insn::new_register_mov(findloc+=4, 0, 29, 27)); + + /* + Disable bzero above 0x818000000 + */ + loc_t findloc2 = memmem("\x23\x74\x0b\xd5", 4); debug("findloc2=0x%016llx\n",findloc2); loc_t bzero = find_bof(findloc2); debug("bzero=0x%016llx\n",bzero); - int shellcodesize = 10*sizeof(uint32_t); //commitment - - loc_t shellcode = findnops(shellcodesize/4); - debug("shellcode=0x%016llx\n",shellcode); + uint32_t shellcode_insn_cnt = 10; //commitment + loc_t shellcode = findnops((shellcode_insn_cnt/2)+1, true, 0x00000000); + debug("shellcode=0x%016llx",shellcode); pushINSN(insn::new_immediate_b(bzero, shellcode)); - constexpr const char patch2[] = "\x03\x01\xC0\xD2\x03\x00\xA3\xF2\x1F\x00\x03\xEB\xA8\x00\x00\x54\x22\x00\x00\x8B\x5F\x00\x03\xEB\x43\x00\x00\x54\xC0\x03\x1F\xD6"; - patches.push_back({shellcode,patch2,sizeof(patch2)-1}); - shellcodesize -= sizeof(patch2)-1; - - loc_t aftershellcode = shellcode+sizeof(patch2)-1; - debug("aftershellcode=0x%016llx\n",aftershellcode); - +#define cPC (shellcode+(insnNum++)*4) + int insnNum = 0; + uint32_t shellend = 8; + + pushINSN(insn::new_immediate_movz(cPC, 0x8, 3, 32)); + pushINSN(insn::new_immediate_movk(cPC, 0x1800, 3, 16)); + pushINSN(insn::new_register_cmp(cPC, 0, 0, 3, -1)); + pushINSN(insn::new_immediate_bcond(cPC, shellcode+shellend*4, insn::HI)); + pushINSN(insn::new_register_add(cPC, 0, 1, 0, 2)); + pushINSN(insn::new_register_cmp(cPC, 0, 2, 3, -1)); + pushINSN(insn::new_immediate_bcond(cPC, shellcode+shellend*4, insn::CC)); + pushINSN(insn::new_general_br(cPC, 30)); + assure(shellend == insnNum); uint32_t backUpProloge = (uint32_t)deref(bzero); + patches.push_back({shellcode+insnNum*4, &backUpProloge, 4});insnNum++; + pushINSN(insn::new_immediate_b(cPC, (int64_t)bzero+4)); + assure(insnNum == shellcode_insn_cnt); +#undef cPC - patches.push_back({aftershellcode, &backUpProloge, 4}); - aftershellcode +=4; - shellcodesize -=4; - - pushINSN(insn::new_immediate_b(aftershellcode, (int64_t)bzero+4)); - shellcodesize -=4; - - assure(shellcodesize >=0); return patches; } diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_base.hpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_base.hpp index 0e1601b..76c5b73 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_base.hpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_base.hpp @@ -22,6 +22,7 @@ namespace tihmstar { namespace patchfinder { class ibootpatchfinder64_base : public ibootpatchfinder64{ + void init(); public: ibootpatchfinder64_base(const char *filename); ibootpatchfinder64_base(const void *buffer, size_t bufSize, bool takeOwnership = false); diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS10.cpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS10.cpp index e8462de..1bb1204 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS10.cpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS10.cpp @@ -15,67 +15,6 @@ using namespace tihmstar::patchfinder; using namespace tihmstar::libinsn; using namespace tihmstar::libinsn::arm64; -std::vector ibootpatchfinder64_iOS10::replace_cmd_with_memcpy(const char *cmd_handler_str){ - std::vector patches; - retassure(cmd_handler_str, "unexpected NULL cmd_handler_str"); - - loc_t handler_str_loc = findstr(cmd_handler_str, true); - debug("handler_str_loc=0x%016llx\n",handler_str_loc); - - loc_t tableref = memmem(&handler_str_loc, sizeof(handler_str_loc)); - debug("tableref=0x%016llx\n",tableref); - - loc_t scratchbuf = _vmem->memstr("failed to execute upgrade command from new"); - debug("scratchbuf=0x%016llx\n",scratchbuf); - - uint32_t shellcode_insn_cnt = 10; //commitment - loc_t shellcode = findnops(shellcode_insn_cnt); - debug("shellcode=0x%016llx\n",shellcode); - - int insnRet = 9; //commitment - int insnLoopRef = 5; //commitment - - -#define cPC (shellcode+(insnNum++)*4) - int insnNum = 0; - - pushINSN(insn::new_immediate_cmp(cPC, 4, 0)); - pushINSN(insn::new_immediate_bcond(cPC, shellcode+insnRet*4, insn::cond::NE)); - pushINSN(insn::new_immediate_ldr_unsigned(cPC, 0x28+0x20*2, 1, 2)); - pushINSN(insn::new_immediate_ldr_unsigned(cPC, 0x28+0x20*0, 1, 0)); - pushINSN(insn::new_immediate_ldr_unsigned(cPC, 0x28+0x20*1, 1, 1)); - assure(insnLoopRef == insnNum); - - { - /* - patch: - ldrb w3, [x1], #0x1 - strb w3, [x0], #0x1 - subs x2, x2, #0x1 - b.ne cmd_bgcolor+84 - */ - constexpr const char patch[] = "\x23\x14\x40\x38" - "\x03\x14\x00\x38" - "\x42\x04\x00\xF1" - "\xA1\xFF\xFF\x54"; - patches.push_back({cPC,patch,sizeof(patch)-1}); //my memcpy - cPC; - cPC; - cPC; - } - - assure(insnNum == insnRet); - pushINSN(insn::new_general_ret(cPC)); - assure(insnNum == shellcode_insn_cnt); -#undef cPC - - patches.push_back({scratchbuf,"memcpy",sizeof("memcpy")}); //overwrite name - patches.push_back({tableref,&scratchbuf,8}); //overwrite pointer to name - patches.push_back({tableref+8,&shellcode,8}); //overwrite function pointer - - return patches; -} - std::vector ibootpatchfinder64_iOS10::get_skip_set_bpr_patch(){ std::vector patches; for (uint64_t bpr_reg : {0x2102d0030/*t8010*/, 0x2352d0030/*t8015*/}) { diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS10.hpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS10.hpp index 0db315c..b564031 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS10.hpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS10.hpp @@ -16,11 +16,6 @@ namespace tihmstar { class ibootpatchfinder64_iOS10 : public ibootpatchfinder64_iOS9{ public: using ibootpatchfinder64_iOS9::ibootpatchfinder64_iOS9; - - /* - replace command with: "memcpy " - */ - virtual std::vector replace_cmd_with_memcpy(const char *cmd_handler_str) override; /* Skip setting BPR by iBoot diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS12.cpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS12.cpp index 647c7f4..35e1036 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS12.cpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS12.cpp @@ -17,59 +17,87 @@ using namespace tihmstar::libinsn::arm64; std::vector ibootpatchfinder64_iOS12::get_tz0_lock_patch(){ - std::vector patches; - - /* Looking for: - movz w8, #0x1 - str w8, [x24] - bl call_dmb_sy - ldr w8, [x24] - tbz w8, 0x0, .... - */ + UNCACHEPATCHES; vmem iter = _vmem->getIter(); - - try { - while (true) { - while (++iter != insn::str); - uint8_t strrn = iter().rn(); - insn prevInsn = iter-1; - if (prevInsn == insn::movz){ - if (prevInsn.imm() != 1) continue; - }else if (prevInsn == insn::orr){ - if (prevInsn.imm() != 1 || prevInsn.rn() != 31 /*weird alias for wzr??*/) continue; + + for (uint64_t lockval : {0x200000910 /*A7 lock*/, 0x200000490 /*A8 lock*/}) { + if (loc_t lock_ref = find_literal_ref(lockval)){ + debug("lock_ref=0x%016llx",lock_ref); + iter = lock_ref; + uint8_t reg_ref = iter().rd(); + debug("reg_ref=%d",reg_ref); + for (int i=0; i<2; i++) { + /* + Skip locking both, tz0 and tz1 + */ + while (++iter != insn::str || iter().rn() != reg_ref) + ; + + loc_t strtgt = iter; + debug("strtgt=0x%016llx",strtgt); + uint8_t reg_strval = iter().rt(); + debug("reg_strval=%d",reg_strval); + pushINSN(insn::new_general_nop(iter)); + if (++iter == insn::bl) + ++iter; + retassure(iter() == insn::ldr && iter().rn() == reg_ref, "unexpected insn"); + pushINSN(insn::new_register_mov(iter, 0, iter().rt(), reg_strval)); } - else continue; - - if (iter().rt() != prevInsn.rd()) continue; //this insn doesn't store result of prev insn - - if (++iter != insn::bl) continue; //here should be a call to call_dmb_sy - - if (++iter != insn::ldr || strrn != iter().rn()) continue; //check the store was successfull - uint8_t ldrrt = iter().rt(); - ++iter; - - if (iter() == insn::cmp) { - if (iter().imm() != 1 && iter().imm() != 0) continue; //wtf? - }else if (iter() == insn::tbz || iter() == insn::tbz){ - if (iter().special() != 1 && iter().special() != 0) continue; //wtf? + } + } + if (!patches.size()) { + //fallback plan non-(A7 A8) + + /* Looking for: + movz w8, #0x1 + str w8, [x24] + bl call_dmb_sy + ldr w8, [x24] + tbz w8, 0x0, .... + */ + try { + while (true) { + while (++iter != insn::str); + uint8_t strrn = iter().rn(); + insn prevInsn = iter-1; + if (prevInsn == insn::movz){ + if (prevInsn.imm() != 1) continue; + }else if (prevInsn == insn::orr){ + if (prevInsn.imm() != 1 || prevInsn.rn() != 31 /*weird alias for wzr??*/) continue; + } + else continue; + + if (iter().rt() != prevInsn.rd()) continue; //this insn doesn't store result of prev insn + + if (++iter != insn::bl) continue; //here should be a call to call_dmb_sy + + if (++iter != insn::ldr || strrn != iter().rn()) continue; //check the store was successfull + uint8_t ldrrt = iter().rt(); + ++iter; + + if (iter() == insn::cmp) { + if (iter().imm() != 1 && iter().imm() != 0) continue; //wtf? + }else if (iter() == insn::tbz || iter() == insn::tbz){ + if (iter().special() != 1 && iter().special() != 0) continue; //wtf? + } + + loc_t check = iter; + check -= 4; + debug("check=0x%016llx",check); + pushINSN(insn::new_immediate_movz(check, 1, ldrrt, 0)); + + loc_t lock = check-2*4; + debug("lock=0x%016llx",lock); + pushINSN(insn::new_general_nop(lock)); } - - loc_t check = iter; - check -= 4; - debug("check=0x%016llx",check); - pushINSN(insn::new_immediate_movz(check, 1, ldrrt, 0)); - - loc_t lock = check-2*4; - debug("lock=0x%016llx",lock); - pushINSN(insn::new_general_nop(lock)); + } catch (...) { + //will fail eventually. this is fine } - } catch (...) { - //will fail eventually. this is fine } retassure(patches.size(), "Failed to find patches"); - return patches; + RETCACHEPATCHES; } std::vector ibootpatchfinder64_iOS12::get_force_septype_local_patch(){ diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS13.cpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS13.cpp index 76c3766..4378584 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS13.cpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS13.cpp @@ -61,6 +61,70 @@ std::vector ibootpatchfinder64_iOS13::get_force_septype_local_patch(){ return patches; } +std::vector ibootpatchfinder64_iOS13::replace_cmd_with_memcpy(const char *cmd_handler_str){ + std::vector patches; + retassure(cmd_handler_str, "unexpected NULL cmd_handler_str"); + + loc_t handler_str_loc = findstr(cmd_handler_str, true); + debug("handler_str_loc=0x%016llx\n",handler_str_loc); + + loc_t tableref = memmem(&handler_str_loc, sizeof(handler_str_loc)); + debug("tableref=0x%016llx\n",tableref); + + loc_t scratchbuf = _vmem->memstr("failed to execute upgrade command from new"); + debug("scratchbuf=0x%016llx\n",scratchbuf); + + uint32_t shellcode_insn_cnt = 10; //commitment + loc_t shellcode = findnops(shellcode_insn_cnt); + debug("shellcode=0x%016llx\n",shellcode); + + int insnRet = 9; //commitment + int insnLoopRef = 5; //commitment + + +#define cPC (shellcode+(insnNum++)*4) + int insnNum = 0; + + pushINSN(insn::new_immediate_cmp(cPC, 4, 0)); + pushINSN(insn::new_immediate_bcond(cPC, shellcode+insnRet*4, insn::cond::NE)); + /* + iPhone 5s iOS 12 still uses 0x30+0x28*x formula + */ + pushINSN(insn::new_immediate_ldr_unsigned(cPC, 0x28+0x20*2, 1, 2)); + pushINSN(insn::new_immediate_ldr_unsigned(cPC, 0x28+0x20*0, 1, 0)); + pushINSN(insn::new_immediate_ldr_unsigned(cPC, 0x28+0x20*1, 1, 1)); + assure(insnLoopRef == insnNum); + + { + /* + patch: + ldrb w3, [x1], #0x1 + strb w3, [x0], #0x1 + subs x2, x2, #0x1 + b.ne cmd_bgcolor+84 + */ + constexpr const char patch[] = "\x23\x14\x40\x38" + "\x03\x14\x00\x38" + "\x42\x04\x00\xF1" + "\xA1\xFF\xFF\x54"; + patches.push_back({cPC,patch,sizeof(patch)-1}); //my memcpy + cPC; + cPC; + cPC; + } + + assure(insnNum == insnRet); + pushINSN(insn::new_general_ret(cPC)); + assure(insnNum == shellcode_insn_cnt); +#undef cPC + + patches.push_back({scratchbuf,"memcpy",sizeof("memcpy")}); //overwrite name + patches.push_back({tableref,&scratchbuf,8}); //overwrite pointer to name + patches.push_back({tableref+8,&shellcode,8}); //overwrite function pointer + + return patches; +} + std::vector ibootpatchfinder64_iOS13::get_always_production_patch(){ std::vector patches; @@ -314,7 +378,7 @@ std::vector ibootpatchfinder64_iOS13::get_rw_and_x_mappings_patch_el1(){ uint32_t fullpatch_size = 0; for (auto p: patches){ - fullpatch_size += p._patchSize; + fullpatch_size += p.getPatchSize(); } /* @@ -357,3 +421,76 @@ std::vector ibootpatchfinder64_iOS13::get_rw_and_x_mappings_patch_el1(){ return patches; } + +std::vector ibootpatchfinder64_iOS13::get_ra1nra1n_patch(){ + std::vector patches; + + /* + uint32_t* tramp = find_next_insn(boot_image, 0x80000, 0xd2800012, 0xFFFFFFFF); + if (tramp) { + for (int i = 0; i < 5; i++) { + tramp[i] = tramp_hook[i]; + } + } + + patch -> + + mov x8, x29 + mov x9, x29 + mov x27, #0x800000000 + movk x27, #0x1800, lsl#16 + mov x29, x27 + + */ + + + loc_t findloc = memmem("\x12\x00\x80\xd2", 4); + debug("findloc=0x%016llx\n",findloc); + + auto iter = _vmem->getIter(findloc); + while (++iter != insn::mov && iter().rd() != 30){ + retassure(iter() != insn::ret, "got unexpected ret!"); + } + uint8_t srcreg = iter().rm(); + + findloc-=4; + pushINSN(insn::new_register_mov(findloc+=4, 0, 8, srcreg)); + pushINSN(insn::new_register_mov(findloc+=4, 0, 9, srcreg)); + pushINSN(insn::new_immediate_movz(findloc+=4, 0x8, 27, 32)); + pushINSN(insn::new_immediate_movk(findloc+=4, 0x1800, 27, 16)); + pushINSN(insn::new_register_mov(findloc+=4, 0, 29, 27)); + + + loc_t findloc2 = memmem("\x23\x74\x0b\xd5", 4); + debug("findloc2=0x%016llx\n",findloc2); + + loc_t bzero = find_bof(findloc2); + debug("bzero=0x%016llx\n",bzero); + + uint32_t shellcode_insn_cnt = 10; //commitment + loc_t shellcode = findnops((shellcode_insn_cnt/2)+1, true, 0x00000000); + debug("shellcode=0x%016llx",shellcode); + + pushINSN(insn::new_immediate_b(bzero, shellcode)); + +#define cPC (shellcode+(insnNum++)*4) + int insnNum = 0; + uint32_t shellend = 8; + + pushINSN(insn::new_immediate_movz(cPC, 0x8, 3, 32)); + pushINSN(insn::new_immediate_movk(cPC, 0x1800, 3, 16)); + pushINSN(insn::new_register_cmp(cPC, 0, 0, 3, -1)); + pushINSN(insn::new_immediate_bcond(cPC, shellcode+shellend*4, insn::HI)); + pushINSN(insn::new_register_add(cPC, 0, 1, 0, 2)); + pushINSN(insn::new_register_cmp(cPC, 0, 2, 3, -1)); + pushINSN(insn::new_immediate_bcond(cPC, shellcode+shellend*4, insn::CC)); + pushINSN(insn::new_general_br(cPC, 30)); + assure(shellend == insnNum); + uint32_t backUpProloge = (uint32_t)deref(bzero); + patches.push_back({shellcode+insnNum*4, &backUpProloge, 4});insnNum++; + pushINSN(insn::new_immediate_b(cPC, (int64_t)bzero+4)); + assure(insnNum == shellcode_insn_cnt); +#undef cPC + + return patches; +} diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS13.hpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS13.hpp index b826f5f..92205ac 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS13.hpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS13.hpp @@ -18,7 +18,12 @@ namespace tihmstar { using ibootpatchfinder64_iOS12::ibootpatchfinder64_iOS12; virtual std::vector get_force_septype_local_patch() override; - + + /* + replace command with: "memcpy " + */ + virtual std::vector replace_cmd_with_memcpy(const char *cmd_handler_str) override; + /* Make iBoot think we're in production mode, even if we demoted */ @@ -27,6 +32,8 @@ namespace tihmstar { virtual uint32_t get_el1_pagesize() override; virtual std::vector get_rw_and_x_mappings_patch_el1() override; + + virtual std::vector get_ra1nra1n_patch() override; }; }; }; diff --git a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS14.cpp b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS14.cpp index cefb0c3..da8aa8f 100644 --- a/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS14.cpp +++ b/libpatchfinder/ibootpatchfinder/ibootpatchfinder64_iOS14.cpp @@ -25,6 +25,7 @@ ibootpatchfinder64_iOS14::ibootpatchfinder64_iOS14(const char *filename) : ibootpatchfinder64_iOS13(filename) { _entrypoint = _base = (loc_t)*(uint64_t*)&_buf[iBOOT_BASE_OFFSET]; + safeDelete(_vmem); _vmem = new vmem({{_buf,_bufSize,_base, (vmprot)(kVMPROTREAD | kVMPROTWRITE | kVMPROTEXEC)}}); debug("iBoot base at=0x%016llx\n", _base); } @@ -33,6 +34,7 @@ ibootpatchfinder64_iOS14::ibootpatchfinder64_iOS14(const void *buffer, size_t bu : ibootpatchfinder64_iOS13(buffer,bufSize,takeOwnership) { _entrypoint = _base = (loc_t)*(uint64_t*)&_buf[iBOOT_BASE_OFFSET]; + safeDelete(_vmem); _vmem = new vmem({{_buf,_bufSize,_base, (vmprot)(kVMPROTREAD | kVMPROTWRITE | kVMPROTEXEC)}}); debug("iBoot base at=0x%016llx\n", _base); } diff --git a/libpatchfinder/kernelpatchfinder/Makefile.am b/libpatchfinder/kernelpatchfinder/Makefile.am index 8504183..f382a4f 100644 --- a/libpatchfinder/kernelpatchfinder/Makefile.am +++ b/libpatchfinder/kernelpatchfinder/Makefile.am @@ -17,6 +17,7 @@ libpatchfinder_kernelpatchfinder64_la_CXXFLAGS = $(AM_CXXFLAGS) libpatchfinder_kernelpatchfinder64_la_LIBADD = $(AM_LDFLAGS) libpatchfinder_kernelpatchfinder64_la_SOURCES = kernelpatchfinder64.cpp \ kernelpatchfinder64_base.cpp \ + kernelpatchfinder64_iOS8.cpp \ kernelpatchfinder64_iOS9.cpp \ kernelpatchfinder64_iOS12.cpp \ kernelpatchfinder64_iOS13.cpp \ diff --git a/libpatchfinder/kernelpatchfinder/kernelpatchfinder32_base.cpp b/libpatchfinder/kernelpatchfinder/kernelpatchfinder32_base.cpp index 8a78421..0c8ba50 100644 --- a/libpatchfinder/kernelpatchfinder/kernelpatchfinder32_base.cpp +++ b/libpatchfinder/kernelpatchfinder/kernelpatchfinder32_base.cpp @@ -970,6 +970,6 @@ std::vector kernelpatchfinder32_base::get_read_bpr_patch_with_params(int #pragma mark utils void kernelpatchfinder32_base::slide_ptr(class patch *p, uint64_t slide){ - slide += *(uint32_t*)p->_patch; - memcpy((void*)p->_patch, &slide, 4); + slide += *(uint32_t*)p->getPatch(); + memcpy((void*)p->getPatch(), &slide, 4); } diff --git a/libpatchfinder/kernelpatchfinder/kernelpatchfinder64.cpp b/libpatchfinder/kernelpatchfinder/kernelpatchfinder64.cpp index 8b79b84..715695f 100644 --- a/libpatchfinder/kernelpatchfinder/kernelpatchfinder64.cpp +++ b/libpatchfinder/kernelpatchfinder/kernelpatchfinder64.cpp @@ -8,6 +8,7 @@ #include "../../include/libpatchfinder/kernelpatchfinder/kernelpatchfinder64.hpp" #include "kernelpatchfinder64_base.hpp" +#include "kernelpatchfinder64_iOS8.hpp" #include "kernelpatchfinder64_iOS9.hpp" #include "kernelpatchfinder64_iOS12.hpp" #include "kernelpatchfinder64_iOS13.hpp" @@ -46,6 +47,9 @@ kernelpatchfinder64 *kernelpatchfinder64::make_kernelpatchfinder64(machopatchfin }else if (vers > 3200) { info("Detected iOS 9 kernel"); return new kernelpatchfinder64_iOS9(std::move(helper)); + }else if (vers > 2700) { + info("Detected iOS 8 kernel"); + return new kernelpatchfinder64_iOS8(std::move(helper)); } return new kernelpatchfinder64_base(std::move(helper)); diff --git a/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_base.cpp b/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_base.cpp index 69af193..ca33c02 100644 --- a/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_base.cpp +++ b/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_base.cpp @@ -44,8 +44,8 @@ kernelpatchfinder64_base::~kernelpatchfinder64_base(){ #pragma mark utils static void slide_ptr(class patch *p, uint64_t slide){ - slide += *(uint64_t*)p->_patch; - memcpy((void*)p->_patch, &slide, 8); + slide += *(uint64_t*)p->getPatch(); + memcpy((void*)p->getPatch(), &slide, 8); } #pragma mark Location finders @@ -53,7 +53,7 @@ patchfinder64::loc_t kernelpatchfinder64_base::find_syscall0(){ UNCACHELOC; constexpr char sig_syscall_3[] = "\x06\x00\x00\x00\x03\x00\x0c\x00"; patchfinder64::loc_t sys3 = memmem(sig_syscall_3, sizeof(sig_syscall_3)-1); - loc_t retval = sys3 - (3 * 0x18) + 0x8; + loc_t retval = sys3 - (3 * 0x20) + 0x8; RETCACHELOC(retval); } @@ -97,7 +97,7 @@ patchfinder64::loc_t kernelpatchfinder64_base::find_machtrap_table(){ patchfinder64::loc_t kernelpatchfinder64_base::find_table_entry_for_syscall(int syscall){ patchfinder64::loc_t syscallTable = find_syscall0(); - return (syscallTable + 3*(syscall-1)*sizeof(uint64_t)); + return (syscallTable + 4*(syscall-1)*sizeof(uint64_t)); } patchfinder64::loc_t kernelpatchfinder64_base::find_function_for_syscall(int syscall){ @@ -451,7 +451,9 @@ std::vector kernelpatchfinder64_base::get_mount_patch(){ vmem iter = _vmem->getIter(mount); while (++iter != insn::bl); - + loc_t mount_internal_bl = iter; + debug("mount_internal_bl=0x%016llx\n",mount_internal_bl); + patchfinder64::loc_t mount_internal = iter().imm(); debug("mount_internal=0x%016llx\n",mount_internal); @@ -502,16 +504,28 @@ std::vector kernelpatchfinder64_base::get_cs_enforcement_disable_amfi_pat debug("ref=0x%016llx",ref); vmem cbz = _vmem->getIter(ref); - while (--cbz != insn::cbz); - - vmem movz(cbz); - while (++movz != insn::movz); - --movz; + while (--cbz != insn::cbz && cbz() != insn::cbnz){ + retassure(cbz() != insn::stp, "Failed to find cbz!"); + } + + if (cbz() == insn::cbz) { + vmem movz(cbz); + while (++movz != insn::movz); + --movz; - int anz = static_cast((movz.pc()-cbz.pc())/4 +1); + int anz = static_cast((movz.pc()-cbz.pc())/4 +1); - for (int i=0; i +#include "../all64.h" +#include "sbops64.h" +#include +#include + +using namespace std; +using namespace tihmstar; +using namespace patchfinder; +using namespace libinsn; +using namespace arm64; + +patchfinder64::loc_t kernelpatchfinder64_iOS8::find_syscall0(){ + UNCACHELOC; + constexpr char sig_syscall_3[] = "\x06\x00\x00\x00\x03\x00\x0c\x00"; + patchfinder64::loc_t sys3 = memmem(sig_syscall_3, sizeof(sig_syscall_3)-1); + loc_t retval = sys3 - (3 * 0x18) + 0x8; + RETCACHELOC(retval); +} + +patchfinder64::loc_t kernelpatchfinder64_iOS8::find_table_entry_for_syscall(int syscall){ + patchfinder64::loc_t syscallTable = find_syscall0(); + return (syscallTable + 3*(syscall-1)*sizeof(uint64_t)); +} diff --git a/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_iOS8.hpp b/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_iOS8.hpp new file mode 100644 index 0000000..094c1ad --- /dev/null +++ b/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_iOS8.hpp @@ -0,0 +1,24 @@ +// +// kernelpatchfinder64_iOS8.hpp +// libpatchfinder +// +// Created by erd on 15.05.24. +// + +#ifndef kernelpatchfinder64_iOS8_hpp +#define kernelpatchfinder64_iOS8_hpp + +#include "kernelpatchfinder64_base.hpp" + +namespace tihmstar { +namespace patchfinder { + class kernelpatchfinder64_iOS8 : public kernelpatchfinder64_base{ + public: + using kernelpatchfinder64_base::kernelpatchfinder64_base; + virtual loc_t find_syscall0() override; + virtual loc_t find_table_entry_for_syscall(int syscall) override; + + }; +} +} +#endif /* kernelpatchfinder64_iOS8_hpp */ diff --git a/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_iOS9.hpp b/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_iOS9.hpp index 849cfea..a74d3be 100644 --- a/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_iOS9.hpp +++ b/libpatchfinder/kernelpatchfinder/kernelpatchfinder64_iOS9.hpp @@ -9,13 +9,13 @@ #ifndef kernelpatchfinder64_iOS9_hpp #define kernelpatchfinder64_iOS9_hpp -#include "kernelpatchfinder64_base.hpp" +#include "kernelpatchfinder64_iOS8.hpp" namespace tihmstar { namespace patchfinder { - class kernelpatchfinder64_iOS9 : public kernelpatchfinder64_base{ + class kernelpatchfinder64_iOS9 : public kernelpatchfinder64_iOS8{ public: - using kernelpatchfinder64_base::kernelpatchfinder64_base; + using kernelpatchfinder64_iOS8::kernelpatchfinder64_iOS8; virtual std::vector get_mount_patch() override; }; diff --git a/libpatchfinder/machopatchfinder64.cpp b/libpatchfinder/machopatchfinder64.cpp index f945df4..f456c39 100644 --- a/libpatchfinder/machopatchfinder64.cpp +++ b/libpatchfinder/machopatchfinder64.cpp @@ -166,6 +166,7 @@ void machopatchfinder64::loadSegments(){ } segments = newsegments; } + safeDelete(_vmem); _vmem = new vmem(segments,0,kVMPROTALL); try { diff --git a/libpatchfinder/main.cpp b/libpatchfinder/main.cpp index 90efda4..45eb251 100644 --- a/libpatchfinder/main.cpp +++ b/libpatchfinder/main.cpp @@ -27,6 +27,7 @@ using namespace tihmstar::patchfinder; int main(int argc, const char * argv[]) { printf("start\n"); + std::vector patches; ibootpatchfinder *ibpf = nullptr; kernelpatchfinder *kpf = nullptr; @@ -66,7 +67,7 @@ int main(int argc, const char * argv[]) { // addpatch(ibpf->get_force_septype_local_patch()); // addpatch(ibpf->get_always_sepfw_booted_patch()); // addpatch(ibpf->get_atv4k_enable_uart_patch()); -// addpatch(ibpf->get_ra1nra1n_patch()); + addpatch(ibpf->get_ra1nra1n_patch()); // addpatch(ibpf->replace_cmd_with_memcpy("reboot")); // addpatch(ibpf->get_boot_arg_patch("-v serial=3 rd=md0")); // addpatch(ibpf->get_no_force_dfu_patch()); @@ -79,7 +80,7 @@ int main(int argc, const char * argv[]) { // debug("asd=0x%016llx",asd); // addpatch(kpf->get_allow_UID_key_patch()); - addpatch(kpf->get_codesignature_patches()); +// addpatch(kpf->get_codesignature_patches()); // addpatch(kpf->get_trustcache_true_patch()); // addpatch(kpf->get_mount_patch()); // addpatch(kpf->get_sandbox_patch()); @@ -115,13 +116,13 @@ int main(int argc, const char * argv[]) { for (auto p : patches) { printf(": Applying patch=0x%016llx : ",p._location); - for (int i=0; i segments) : - patchfinder(true) +patchfinder64::patchfinder64(loc_t base, const char *filename, std::vector segments) +: patchfinder(true) +, _vmem(nullptr) { struct stat fs = {0}; int fd = 0; @@ -83,8 +85,9 @@ patchfinder64::patchfinder64(loc_t base, const char *filename, std::vector segments) : - patchfinder(takeOwnership) +patchfinder64::patchfinder64(loc_t base, const void *buffer, size_t bufSize, bool takeOwnership, std::vector segments) +: patchfinder(takeOwnership) +, _vmem(nullptr) { _bufSize = bufSize; _buf = (uint8_t*)buffer; From e37692f7c487acc902d710037a73f7d70d016bee Mon Sep 17 00:00:00 2001 From: tihmstar Date: Mon, 29 Jul 2024 21:44:25 +0200 Subject: [PATCH 03/15] add binrider commands --- libpatchfinder/machopatchfinder64.cpp | 24 +++--- tools/binrider/main.cpp | 118 ++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 17 deletions(-) diff --git a/libpatchfinder/machopatchfinder64.cpp b/libpatchfinder/machopatchfinder64.cpp index f945df4..88099c4 100644 --- a/libpatchfinder/machopatchfinder64.cpp +++ b/libpatchfinder/machopatchfinder64.cpp @@ -102,6 +102,7 @@ void machopatchfinder64::loadSegments(){ struct mach_header_64 *mh = (struct mach_header_64*)_buf; struct load_command *lcmd = (struct load_command *)(mh + 1); bool has_text_exec = false; + bool hasEntrypoint = false; for (uint32_t i=0; incmds; i++, lcmd = (struct load_command *)((uint8_t *)lcmd + lcmd->cmdsize)) { if (lcmd->cmd == LC_SEGMENT_64){ struct segment_command_64* seg = (struct segment_command_64*)lcmd; @@ -133,6 +134,7 @@ void machopatchfinder64::loadSegments(){ } *thread = (struct _tread*)(ptr + 2); if (flavor == 6) { _entrypoint = (patchfinder64::patchfinder64::loc_t)(thread->pc); + hasEntrypoint = true; } } if (lcmd->cmd == LC_FILESET_ENTRY) { @@ -168,16 +170,18 @@ void machopatchfinder64::loadSegments(){ } _vmem = new vmem(segments,0,kVMPROTALL); - try { - deref(_entrypoint); - info("Detected non-slid kernel."); - } catch (tihmstar::out_of_range &e) { - reterror("Detected slid kernel. but slid kernel is currently not supported"); - } - try { - deref(_entrypoint); - } catch (tihmstar::out_of_range &e) { - reterror("Error occured when handling kernel entry checks"); + if (hasEntrypoint) { + try { + deref(_entrypoint); + info("Detected non-slid kernel."); + } catch (tihmstar::out_of_range &e) { + reterror("Detected slid kernel. but slid kernel is currently not supported"); + } + try { + deref(_entrypoint); + } catch (tihmstar::out_of_range &e) { + reterror("Error occured when handling kernel entry checks"); + } } info("Inited machopatchfinder64 %s %s",VERSION_COMMIT_COUNT, VERSION_COMMIT_SHA); diff --git a/tools/binrider/main.cpp b/tools/binrider/main.cpp index ebc0e88..626744c 100644 --- a/tools/binrider/main.cpp +++ b/tools/binrider/main.cpp @@ -26,9 +26,13 @@ static struct option longopts[] = { { "raw", required_argument, NULL, 'r' }, /* action */ - { "xref", required_argument, NULL, 0 }, - { "cref", required_argument, NULL, 0 }, + { "bof", required_argument, NULL, 0 }, { "bref", required_argument, NULL, 0 }, + { "cref", required_argument, NULL, 0 }, + { "fof" , required_argument, NULL, 0 }, + { "stringloc", required_argument, NULL, 0 }, + { "stringloc2", required_argument, NULL, 0 }, + { "xref", required_argument, NULL, 0 }, /* prints */ { "Preg", required_argument, NULL, 0 }, @@ -46,8 +50,12 @@ void cmd_help(){ printf(" -r, --raw <64/32/32a/32t>\t\t\tSet binary type to 'raw'. You must select parser 64bit, 32bit (arm/thumb)\n"); /* actions */ + printf(" --bof
\t\t\t\tPrint beginning of function for address\n"); printf(" --bref
\t\t\t\tPrint branch refs to address\n"); printf(" --cref
\t\t\t\tPrint call refs to address\n"); + printf(" --fof
\t\t\t\tPrint fileoffset of virtual address\n"); + printf(" --stringloc \t\t\t\tPrint addr of null terminated string\n"); + printf(" --stringloc2 \t\t\t\tPrint addr of not null terminated string\n"); printf(" --xref
\t\t\t\tPrint literal refs to address\n"); @@ -71,6 +79,11 @@ struct rstruct{ std::function func; }; +struct fstruct { + std::vector data; + std::vector refs; + bool isString; +}; MAINFUNCTION int main_r(int argc, const char * argv[]) { @@ -94,6 +107,13 @@ int main_r(int argc, const char * argv[]) { std::set Pregs; //actions + rstruct bofs{ + .name = "beginning of function", + .refs = {}, + .func = [&](patchfinder::loc_t pos, patchfinder::loc_t start){ + return pf->find_bof(pos); + } + }; rstruct brefs{ .name = "branch refs", .refs = {}, @@ -108,6 +128,14 @@ int main_r(int argc, const char * argv[]) { return pf->find_call_ref(ref, 0, start); } }; + rstruct fofs{ + .name = "fileoffset", + .refs = {}, + .func = [&](patchfinder::loc_t ref, patchfinder::loc_t start){ + pf->deref(ref); + return ref-pf->find_base(); + } + }; rstruct xrefs{ .name = "xrefs", .refs = {}, @@ -115,16 +143,32 @@ int main_r(int argc, const char * argv[]) { return pf->find_literal_ref(ref, 0, start); } }; - + std::vector memLocs; + while ((opt = getopt_long(argc, (char * const*)argv, "hb:r:", longopts, &optindex)) >= 0) { switch (opt) { case 0: { std::string curopt = longopts[optindex].name; - if (curopt == "bref") { + if (curopt == "bof") { + bofs.refs.push_back(strtoll(optarg, NULL, 16)); + }else if (curopt == "bref") { brefs.refs.push_back(strtoll(optarg, NULL, 16)); }else if (curopt == "cref") { crefs.refs.push_back(strtoll(optarg, NULL, 16)); + }else if (curopt == "fof") { + fofs.refs.push_back(strtoll(optarg, NULL, 16)); + }else if (curopt.starts_with("stringloc")) { + bool isNullTerminated = (curopt == "stringloc"); + std::string str = optarg; + fstruct mLoc = { + .data = {str.begin(), str.end()}, + .isString = true, + }; + if (!isNullTerminated && mLoc.data.size()) { + mLoc.data.pop_back(); + } + memLocs.push_back(mLoc); }else if (curopt == "xref") { xrefs.refs.push_back(strtoll(optarg, NULL, 16)); }else if (curopt == "Preg") { @@ -182,8 +226,24 @@ int main_r(int argc, const char * argv[]) { } if (bintype == kBinaryTypeDefault) { - if (!pf) try {pf = new machopatchfinder64(lastArg); bintype = kBinaryTypeARM64;} catch (...) {} - if (!pf) try {pf = new machopatchfinder32(lastArg); bintype = kBinaryTypeARM32;} catch (...) {} + if (!pf){ + try { + pf = new machopatchfinder64(lastArg); bintype = kBinaryTypeARM64; + }catch (tihmstar::exception &e) { +#ifdef DEBUG + e.dump(); +#endif + } + } + if (!pf){ + try { + pf = new machopatchfinder32(lastArg); bintype = kBinaryTypeARM32; + }catch (tihmstar::exception &e) { +#ifdef DEBUG + e.dump(); +#endif + } + } retassure(pf,"not implemented"); }else{ info("Setting base to 0x%08llx",base); @@ -209,24 +269,68 @@ int main_r(int argc, const char * argv[]) { { + //refs int add = (bintype == kBinaryTypeARM64) ? 4 : 2; char regname = (bintype == kBinaryTypeARM64) ? 'X' : 'R'; - for (auto r : {brefs,crefs,xrefs}){ + for (auto r : {bofs,brefs,crefs,fofs,xrefs}){ for (auto tgt : r.refs) { info("Checking %s to 0x%08llx",r.name.c_str(),tgt); + patchfinder::loc_t lasref = 0; patchfinder::loc_t ref = 0 - add; + bool didFind = false; while (true) { try { if (!(ref = r.func(tgt,ref+add))) break; } catch (...) { break; } + if (ref == lasref) break; info("\tFound %s at 0x%08llx",r.name.c_str(),ref); + didFind = true; + lasref = ref; for (auto r : Pregs) { auto rv = pf->find_register_value(ref, r); info("\t\t%c: 0x%08llx",regname,rv); } } + if (!didFind) { + info("\tNo refs found to 0x%08llx",r.name.c_str()); + } + } + } + } + + { + //memloc + for (auto m : memLocs) { + if (m.isString) { + info("Searching for string '%s'",(char*)m.data.data()); + }else{ + reterror("TODO"); + } + patchfinder::loc_t found = -1; + bool didFind = false; + do{ + try { + found = pf->memmem(m.data.data(), m.data.size(),found+1); + didFind = true; + } catch (...) { + break; + } + if (didFind && found) { + if (m.isString) { + info("\tFound '%s' at 0x%08llx",(char*)m.data.data(),found); + }else{ + reterror("TODO"); + } + } + } while (found); + if (!didFind) { + if (m.isString) { + info("\tNo occurences found of '%s'",(char*)m.data.data()); + }else{ + reterror("TODO"); + } } } } From 7a3171f3f9e72ccf935e6b79d461fbb8f157d2f3 Mon Sep 17 00:00:00 2001 From: tihmstar Date: Mon, 29 Jul 2024 21:55:33 +0200 Subject: [PATCH 04/15] binrider needs c++20 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 55bd17e..c5fc956 100644 --- a/configure.ac +++ b/configure.ac @@ -33,7 +33,7 @@ case $host_os in esac -CXXFLAGS+=" -std=c++11 -O3" +CXXFLAGS+=" -std=c++20 -O3" CFLAGS+=" -std=c11" CXXFLAGS+=" -D EXPECTIONNAME=OFexception" From 4b9ecb0765a293e00d3f198b725981a477726692 Mon Sep 17 00:00:00 2001 From: tihmstar Date: Mon, 29 Jul 2024 21:56:07 +0200 Subject: [PATCH 05/15] pretty helpscreen --- tools/binrider/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/binrider/main.cpp b/tools/binrider/main.cpp index 626744c..130f4cc 100644 --- a/tools/binrider/main.cpp +++ b/tools/binrider/main.cpp @@ -54,8 +54,8 @@ void cmd_help(){ printf(" --bref
\t\t\t\tPrint branch refs to address\n"); printf(" --cref
\t\t\t\tPrint call refs to address\n"); printf(" --fof
\t\t\t\tPrint fileoffset of virtual address\n"); - printf(" --stringloc \t\t\t\tPrint addr of null terminated string\n"); - printf(" --stringloc2 \t\t\t\tPrint addr of not null terminated string\n"); + printf(" --stringloc \t\t\tPrint addr of null terminated string\n"); + printf(" --stringloc2 \t\t\tPrint addr of not null terminated string\n"); printf(" --xref
\t\t\t\tPrint literal refs to address\n"); From 4054a1ab402146d86de88ec6c4d2603e97819d71 Mon Sep 17 00:00:00 2001 From: tihmstar Date: Mon, 29 Jul 2024 23:13:18 +0200 Subject: [PATCH 06/15] fix no ref msg --- tools/binrider/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binrider/main.cpp b/tools/binrider/main.cpp index 130f4cc..b8ce013 100644 --- a/tools/binrider/main.cpp +++ b/tools/binrider/main.cpp @@ -294,7 +294,7 @@ int main_r(int argc, const char * argv[]) { } } if (!didFind) { - info("\tNo refs found to 0x%08llx",r.name.c_str()); + info("\tNo refs found to 0x%08llx",tgt); } } } From 57253d3bfc5dee759a85665773109979a60cedc8 Mon Sep 17 00:00:00 2001 From: tihmstar Date: Thu, 1 Aug 2024 16:40:56 +0200 Subject: [PATCH 07/15] use clang --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index c5fc956..4e0bb6e 100644 --- a/configure.ac +++ b/configure.ac @@ -15,8 +15,8 @@ AC_SUBST([VERSION_COMMIT_COUNT], ["m4_esyscmd([git rev-list --count HEAD | tr -d AC_SUBST([VERSION_COMMIT_SHA], ["m4_esyscmd([git rev-parse HEAD | tr -d '\n'])"]) # Checks for programs. -AC_PROG_CXX -AC_PROG_CC +AC_PROG_CXX([clang++]) +AC_PROG_CC([clang]) # Check for operating system AC_MSG_CHECKING([whether we need platform-specific build settings]) From 88c89ea66495ac475212a7e6861eabc7dd04e2a2 Mon Sep 17 00:00:00 2001 From: tihmstar Date: Thu, 1 Aug 2024 16:44:27 +0200 Subject: [PATCH 08/15] add ci --- .github/workflows/main.yml | 135 +++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..b332b8d --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,135 @@ +name: Buildrunner + +on: [push] + +jobs: + build: + + strategy: + matrix: + platform: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.platform }} + env: + BUILDROOT: "buildroot_${{ matrix.platform }}" + GIT_DEPENDENCIES: libgeneral,img3tool,img4tool,libinsn + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install pre-dependencies + run: | + if [ "$RUNNER_OS" == "Linux" ]; then + sudo apt-get update + sudo apt-get install -y jq + + elif [ "$RUNNER_OS" == "macOS" ]; then + brew install autoconf automake libtool jq pkg-config + + else + echo "$RUNNER_OS not supported" + exit 1 + fi + shell: bash + - name: download dependencies + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + get_latest_release() { + url="https://api.github.com/repos/$1/releases/latest" + echo "url: ${url}" >&2 + curl --silent --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' "${url}" | # Get latest release from GitHub api + jq .tag_name | # Get tag + tr -d '"' # Strip quotes + } + mkdir depdir + cd depdir + mkdir $BUILDROOT + IFS=',' read -r -a deparray <<< "$GIT_DEPENDENCIES"; for d in ${deparray[@]}; do + dep=$d + if ! echo ${dep} | grep -q '/'; then + dep=${{ github.repository_owner }}/${dep} + fi + echo "Got dependency: ${dep}" + tag=$(get_latest_release ${dep}); + echo "Found tag: $tag" + wget "https://github.com/${dep}/releases/download/$tag/$BUILDROOT.zip" + unzip -u "$BUILDROOT.zip" + rm "$BUILDROOT.zip" + done + echo "moving dependencies to /" + sudo cp -r $BUILDROOT/* / + cd .. + rm -rf depdir + - name: prepre buildroot + run: mkdir -p $BUILDROOT + - name: autogen + run: ./autogen.sh --enable-static --disable-shared --with-binrider --with-offsetexporter + - name: make + run: | + if [ "$RUNNER_OS" == "macOS" ]; then + IFS=',' read -r -a deparray <<< "$MAC_DYNAMIC_LIBS"; for d in ${deparray[@]}; do + echo "moving library $d" + cd $(brew --prefix $d) + find . -name "*.dylib" -exec mv {} {}.bak \; + done + cd $GITHUB_WORKSPACE + + make -j || make + + IFS=',' read -r -a deparray <<< "$MAC_DYNAMIC_LIBS"; for d in ${deparray[@]}; do + echo "restoring library $d" + cd $(brew --prefix $d) + find . -name "*.dylib.bak" | while read f; do o=$(echo $f | rev | cut -d '.' -f2- | rev); mv $f $o; done + done + cd $GITHUB_WORKSPACE + else + make -j || make + fi + - name: make install + run: make DESTDIR=$GITHUB_WORKSPACE/$BUILDROOT install + - uses: actions/upload-artifact@v4 + with: + name: ${{ env.BUILDROOT }} + path: ${{ env.BUILDROOT }} + + release: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Download ubuntu artifact + uses: actions/download-artifact@v4 + with: + name: buildroot_ubuntu-latest + path: buildroot_ubuntu-latest + - name: Download macos artifact + uses: actions/download-artifact@v4 + with: + name: buildroot_macos-latest + path: buildroot_macos-latest + - name: Set env vars and zip + run: | + echo "BUILD_VERSION_NUM=$(echo "$(git rev-list --count HEAD | tr -d '\n')")" >> $GITHUB_ENV + echo "BUILD_VERSION_SHA=$(echo "$(git rev-parse HEAD | tr -d '\n'])")" >> $GITHUB_ENV + echo "BUILD_VERSION_STR=$(echo "$(git rev-list --count HEAD | tr -d '\n')-$(git rev-parse HEAD | tr -d '\n'])")" >> $GITHUB_ENV + echo "COMMIT_MSG=$(echo "$(git log -1 --pretty=%B)")" >> $GITHUB_ENV + zip -r buildroot_macos-latest.zip buildroot_macos-latest + zip -r buildroot_ubuntu-latest.zip buildroot_ubuntu-latest + - name: Create Release + id: create_release + uses: softprops/action-gh-release@v2 + if: github.ref == 'refs/heads/master' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + prerelease: false + draft: false + tag_name: ${{ env.BUILD_VERSION_NUM }} + name: Build ${{ env.BUILD_VERSION_STR }} + body: ${{ env.COMMIT_MSG }} + files: | + buildroot_ubuntu-latest.zip + buildroot_macos-latest.zip \ No newline at end of file From 147f99025e4ca535889e46d382926221c181e858 Mon Sep 17 00:00:00 2001 From: tihmstar Date: Thu, 1 Aug 2024 16:47:24 +0200 Subject: [PATCH 09/15] ci: add libplist dep --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b332b8d..55b6c06 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: runs-on: ${{ matrix.platform }} env: BUILDROOT: "buildroot_${{ matrix.platform }}" - GIT_DEPENDENCIES: libgeneral,img3tool,img4tool,libinsn + GIT_DEPENDENCIES: img3tool,img4tool,libgeneral,libinsn,libplist steps: - uses: actions/checkout@v4 From 735e52d3d7279e4b3c6554133c6a4dfa1b67c241 Mon Sep 17 00:00:00 2001 From: tihmstar Date: Thu, 1 Aug 2024 16:51:30 +0200 Subject: [PATCH 10/15] ci: linux add cctools --- .github/workflows/main.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 55b6c06..514013a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,6 +23,15 @@ jobs: sudo apt-get update sudo apt-get install -y jq + wget https://github.com/apple-oss-distributions/cctools/archive/refs/tags/cctools-973.0.1.tar.gz -O cctools.tar.gz + mkdir tmp + tar -xvzf cctools.tar.gz -C tmp + mv tmp/cctoo* tmp/cctools + sed -i 's_#include_//_g' tmp/cctools/include/mach-o/loader.h + sed -i -e 's==\n#include \ntypedef int integer_t;\ntypedef integer_t cpu_type_t;\ntypedef integer_t cpu_subtype_t;\ntypedef integer_t cpu_threadtype_t;\ntypedef int vm_prot_t;=g' tmp/cctools/include/mach-o/loader.h + cp -r tmp/cctools/include/* /usr/local/include/ + rm -rf tmp cctools.tar.gz + elif [ "$RUNNER_OS" == "macOS" ]; then brew install autoconf automake libtool jq pkg-config From 26ff1ed8c027fc6325149ba88ad17210b05a7781 Mon Sep 17 00:00:00 2001 From: tihmstar Date: Thu, 1 Aug 2024 16:52:12 +0200 Subject: [PATCH 11/15] ci: linux add cctools (fix) --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 514013a..f18082a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: mv tmp/cctoo* tmp/cctools sed -i 's_#include_//_g' tmp/cctools/include/mach-o/loader.h sed -i -e 's==\n#include \ntypedef int integer_t;\ntypedef integer_t cpu_type_t;\ntypedef integer_t cpu_subtype_t;\ntypedef integer_t cpu_threadtype_t;\ntypedef int vm_prot_t;=g' tmp/cctools/include/mach-o/loader.h - cp -r tmp/cctools/include/* /usr/local/include/ + sudo cp -r tmp/cctools/include/* /usr/local/include/ rm -rf tmp cctools.tar.gz elif [ "$RUNNER_OS" == "macOS" ]; then From cf505c183eabc2fae4843027c7ddb43b3b16afd1 Mon Sep 17 00:00:00 2001 From: tihmstar Date: Thu, 1 Aug 2024 19:07:28 +0200 Subject: [PATCH 12/15] fix merge --- tools/offsetexporter/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/offsetexporter/main.cpp b/tools/offsetexporter/main.cpp index 3ded061..ab998f1 100644 --- a/tools/offsetexporter/main.cpp +++ b/tools/offsetexporter/main.cpp @@ -153,7 +153,7 @@ int main_r(int argc, const char * argv[]) { std::string static_str; if (method.funcname == "static") { retassure(method.args.size() == 1, "bad number of args for 'static' call! Needs 1"); - pp = patch(offsetexporter::ReturnType_std_string,method.args.at(0).data(),method.args.at(0).size(),NULL,false); + pp = patch(offsetexporter::ReturnType_std_string,method.args.at(0).data(),method.args.at(0).size(),NULL); }else{ pp = offsetexporter::reflect_kernelpatchfinder(kpf, method.funcname, method.args); } @@ -163,9 +163,9 @@ int main_r(int argc, const char * argv[]) { if (pp._location == offsetexporter::ReturnType_std_string) { //first check for "magic" locations - std::string rs = {(char*)pp._patch,(char*)pp._patch+pp._patchSize}; + std::string rs = {(char*)pp.getPatch(),(char*)pp.getPatch()+pp.getPatchSize()}; templ = ReplaceAll(templ, method.templaceName, rs); - }else if (pp._patchSize == 0){ + }else if (pp.getPatchSize() == 0){ //this is a location, not a patch uint64_t loc = pp._location; char buf[20] = {}; From d12f088d83c45e1c388d08ca130589522cd684f0 Mon Sep 17 00:00:00 2001 From: tihmstar Date: Thu, 1 Aug 2024 19:10:39 +0200 Subject: [PATCH 13/15] ci: remove unused copypasta args --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f18082a..3c83798 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -73,7 +73,7 @@ jobs: - name: prepre buildroot run: mkdir -p $BUILDROOT - name: autogen - run: ./autogen.sh --enable-static --disable-shared --with-binrider --with-offsetexporter + run: ./autogen.sh --enable-static --disable-shared - name: make run: | if [ "$RUNNER_OS" == "macOS" ]; then From 0141ec2cca153ec45112fade1191b1310b7060bb Mon Sep 17 00:00:00 2001 From: tihmstar Date: Tue, 20 Aug 2024 17:08:37 +0200 Subject: [PATCH 14/15] fix null terminate search --- tools/binrider/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/binrider/main.cpp b/tools/binrider/main.cpp index b8ce013..7bed808 100644 --- a/tools/binrider/main.cpp +++ b/tools/binrider/main.cpp @@ -165,8 +165,8 @@ int main_r(int argc, const char * argv[]) { .data = {str.begin(), str.end()}, .isString = true, }; - if (!isNullTerminated && mLoc.data.size()) { - mLoc.data.pop_back(); + if (isNullTerminated) { + mLoc.data.push_back('\0'); } memLocs.push_back(mLoc); }else if (curopt == "xref") { From 94cec83aadd24e0f0d32420b75f18e38a906b17f Mon Sep 17 00:00:00 2001 From: tihmstar Date: Tue, 20 Aug 2024 18:16:40 +0200 Subject: [PATCH 15/15] add deref functionality --- tools/binrider/main.cpp | 60 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/tools/binrider/main.cpp b/tools/binrider/main.cpp index 7bed808..9f68fbb 100644 --- a/tools/binrider/main.cpp +++ b/tools/binrider/main.cpp @@ -29,6 +29,8 @@ static struct option longopts[] = { { "bof", required_argument, NULL, 0 }, { "bref", required_argument, NULL, 0 }, { "cref", required_argument, NULL, 0 }, + { "derefmem", required_argument, NULL, 0 }, + { "derefstr", required_argument, NULL, 0 }, { "fof" , required_argument, NULL, 0 }, { "stringloc", required_argument, NULL, 0 }, { "stringloc2", required_argument, NULL, 0 }, @@ -53,6 +55,8 @@ void cmd_help(){ printf(" --bof
\t\t\t\tPrint beginning of function for address\n"); printf(" --bref
\t\t\t\tPrint branch refs to address\n"); printf(" --cref
\t\t\t\tPrint call refs to address\n"); + printf(" --derefmem
,\tDump memory at address\n"); + printf(" --derefstr
\t\t\tDump string at address\n"); printf(" --fof
\t\t\t\tPrint fileoffset of virtual address\n"); printf(" --stringloc \t\t\tPrint addr of null terminated string\n"); printf(" --stringloc2 \t\t\tPrint addr of not null terminated string\n"); @@ -85,6 +89,11 @@ struct fstruct { bool isString; }; +struct mstruct { + uint64_t addr; + uint64_t size; +}; + MAINFUNCTION int main_r(int argc, const char * argv[]) { info("binrider: %s",VERSION_STRING); @@ -144,7 +153,8 @@ int main_r(int argc, const char * argv[]) { } }; std::vector memLocs; - + std::vector derefLocs; + while ((opt = getopt_long(argc, (char * const*)argv, "hb:r:", longopts, &optindex)) >= 0) { switch (opt) { case 0: @@ -156,6 +166,27 @@ int main_r(int argc, const char * argv[]) { brefs.refs.push_back(strtoll(optarg, NULL, 16)); }else if (curopt == "cref") { crefs.refs.push_back(strtoll(optarg, NULL, 16)); + }else if (curopt == "derefmem" || curopt == "derefstr") { + bool isString = (curopt == "derefstr"); + uint64_t addr = strtoull(optarg, NULL, 16); + uint64_t memsize = 0; + if (!isString){ + char *smem = strstr(optarg, ","); + if (!smem) { + error("Failed to parse derefmem size"); + return -1; + } + smem++; + if (smem[0] == '0' && tolower(smem[1]) == 'x') { + memsize = strtoull(smem, NULL, 16); + }else{ + memsize = strtoull(smem, NULL, 10); + } + } + derefLocs.push_back({ + .addr = addr, + .size = memsize, + }); }else if (curopt == "fof") { fofs.refs.push_back(strtoll(optarg, NULL, 16)); }else if (curopt.starts_with("stringloc")) { @@ -335,6 +366,33 @@ int main_r(int argc, const char * argv[]) { } } + { + //deref + for (auto dm : derefLocs) { + if (dm.size == 0) { + printf("Deref string at 0x%08llx: ",dm.addr); + try { + const char *ms = (const char*)pf->memoryForLoc(dm.addr); + printf("%s\n",ms); + } catch (...) { + printf("[FAILED]\n"); + } + }else{ + printf("Deref mem at 0x%08llx: ",dm.addr); + try { + const uint8_t *mem = (const uint8_t*)pf->memoryForLoc(dm.addr); + for (int i=0; i