├── .github └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── OVERVIEW.md ├── README.md ├── apfs.c ├── apple-include-private ├── APFS │ ├── APFS.h │ └── APFSConstants.h ├── CoreFoundation │ └── CFURLPriv.h ├── CoreServices │ ├── FSNode.h │ └── FSNodePropertyProviding.h ├── IOMobileFramebuffer │ └── IOMobileframebuffer.h ├── kern │ └── cs_blobs.h ├── mach │ └── coalition.h ├── mach_debug │ └── zone_info.h ├── os │ ├── alloc_once_impl.h │ ├── alloc_once_private.h │ ├── base_private.h │ ├── once_private.h │ └── variant_private.h ├── sandbox │ └── private.h ├── spawn_private.h ├── sys │ ├── codesign.h │ ├── kern_memorystatus.h │ ├── reason.h │ └── spawn_internal.h └── xpc │ ├── private.h │ └── xpc_transcation_deprecate.h ├── build.command ├── include ├── dyld-interpose.h ├── fakedyld │ ├── errno.h │ ├── fakedyld.h │ ├── graftdmg_un.h │ ├── lib.h │ ├── param.h │ ├── printf.h │ ├── rw_file.h │ ├── spawn.h │ ├── startup.h │ ├── string.h │ ├── syscalls.h │ ├── types.h │ └── utils.h ├── libjailbreak │ └── libjailbreak.h ├── libroot.h ├── mount_args.h ├── paleinfo.h ├── patches │ └── platform │ │ ├── patch.h │ │ └── shellcode.h ├── payload │ └── payload.h ├── payload_dylib │ ├── common.h │ └── crashreporter.h ├── plooshfinder │ ├── asm │ │ └── arm64.h │ ├── formats │ │ ├── defs │ │ │ ├── elf_defs.h │ │ │ ├── macho_defs.h │ │ │ └── pe_defs.h │ │ ├── elf.h │ │ ├── macho.h │ │ ├── multi.h │ │ └── pe.h │ ├── plooshfinder.h │ ├── plooshfinder32.h │ ├── plooshfinder64.h │ └── utils.h ├── rootfulhooks │ └── hooks.h ├── rootlesshooks │ └── hooks.h ├── substrate.h ├── systemhook │ ├── common.h │ ├── envbuf.h │ ├── launchd.h │ └── libiosexec.h └── universalhooks │ └── hooks.h ├── plooshInit.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ ├── IDEWorkspaceChecks.plist │ └── WorkspaceSettings.xcsettings ├── shared ├── boot.jp2 ├── copyright │ ├── APSL-2.0.txt │ ├── Apache-2.0.txt │ ├── License-Dopamine.txt │ ├── License-curl.txt │ ├── License-dobby.txt │ ├── License-dropbear.txt │ ├── License-ellekit.txt │ ├── License-ellekit2.txt │ ├── License-ellekit3.txt │ ├── License-launchctl.txt │ ├── License-ldid.txt │ ├── License-less.txt │ ├── License-mksh.txt │ ├── License-ncurses.txt │ ├── License-snaputil.txt │ ├── License-trustcache.txt │ ├── License-uikittools.txt │ ├── License-vim.txt │ ├── License-xz.txt │ ├── License-zstd.txt │ ├── agpl-3.0.txt │ ├── gpl-2.0.txt │ ├── gpl-3.0.txt │ └── lgpl-2.1.txt ├── debug-shell.plist ├── dropbear-2.plist ├── dropbear-3.plist ├── dropbear-5.plist ├── palera1nd.plist ├── payload.plist └── telnetd.plist ├── src ├── .gitignore ├── Makefile ├── bridgehook │ ├── .gitignore │ ├── Makefile │ └── main.c ├── ellekit │ ├── .gitignore │ └── Makefile ├── fakedyld │ ├── .gitignore │ ├── Makefile │ ├── asm │ │ ├── Makefile │ │ ├── start.S │ │ └── syscall.S │ ├── lib │ │ ├── Makefile │ │ ├── atoi.c │ │ ├── bzero.c │ │ ├── fs_snapshot.c │ │ ├── isalpha.c │ │ ├── isdigit.c │ │ ├── isspace.c │ │ ├── isupper.c │ │ ├── memcpy.c │ │ ├── memmem.c │ │ ├── memset.c │ │ ├── printf.c │ │ ├── putchar.c │ │ ├── strchr.c │ │ ├── strcmp.c │ │ ├── strerror.c │ │ ├── strlen.c │ │ ├── strncmp.c │ │ ├── stroul.c │ │ ├── stroull.c │ │ ├── strstr.c │ │ └── syscalls.c │ ├── main │ │ ├── Makefile │ │ ├── clean_fakefs.c │ │ ├── cores_init.c │ │ ├── fakedyld.c │ │ ├── mountroot.c │ │ ├── pinfo.c │ │ ├── pinfo_check.c │ │ ├── prepare_root.c │ │ ├── rw_file.c │ │ ├── start.c │ │ └── systeminfo.c │ └── patch_dyld │ │ ├── Makefile │ │ ├── patcher.c │ │ ├── patches │ │ ├── Makefile │ │ └── platform │ │ │ ├── Makefile │ │ │ ├── patch.c │ │ │ └── shellcode.c │ │ └── plooshfinder │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── Makefile │ │ └── src │ │ ├── asm │ │ └── arm64.c │ │ ├── formats │ │ ├── elf.c │ │ ├── macho.c │ │ ├── multi.c │ │ └── pe.c │ │ ├── plooshfinder.c │ │ ├── plooshfinder32.c │ │ ├── plooshfinder64.c │ │ └── utils.c ├── libjailbreak │ ├── .gitignore │ ├── Makefile │ ├── bmhash.c │ ├── jbdcall.c │ ├── launchd.c │ ├── prebootpath.c │ └── strflags.c ├── libs │ ├── APFS.tbd │ ├── IOKit.tbd │ ├── IOMobileFramebuffer.tbd │ └── substrate.tbd ├── mount_cores │ ├── .gitignore │ ├── Makefile │ ├── entitlements.xml │ ├── main.c │ └── mount_dmg.c ├── payload │ ├── .gitignore │ ├── Info.plist │ ├── Makefile │ ├── bootscreend.c │ ├── entitlements.xml │ ├── jailbreakd │ │ ├── Makefile │ │ ├── bootstrap.c │ │ ├── handler.c │ │ ├── main.c │ │ ├── obliterate.c │ │ ├── overwrite_file.c │ │ ├── reboot3.c │ │ └── runcmd.c │ ├── launchctl │ │ ├── Makefile │ │ ├── bootstrap.c │ │ ├── launchctl.h │ │ ├── load.c │ │ ├── os_alloc_once.h │ │ ├── xpc_helper.c │ │ └── xpc_private.h │ ├── loader │ │ ├── Makefile │ │ ├── create_var_jb.c │ │ ├── fixup_user_groups.c │ │ ├── launchdaemons.c │ │ ├── load_etc_rc_d.c │ │ ├── main.c │ │ ├── mount_dmg.c │ │ ├── platform.c │ │ ├── prelaunchd.c │ │ ├── remount.c │ │ ├── runcmd.c │ │ ├── setup_fakefs.c │ │ └── sysstatuscheck.c │ ├── main.c │ ├── p1ctl │ │ ├── Makefile │ │ ├── bootstrap.c │ │ ├── libroot.c │ │ ├── libroot_cmd.c │ │ ├── main.c │ │ ├── obliterate.c │ │ ├── overwrite.c │ │ ├── palera1n_flags.c │ │ ├── preboot_path.c │ │ └── print_jailbreakd_reply.c │ └── pinfo.c ├── payload_dylib │ ├── .gitignore │ ├── Makefile │ ├── crashreporter.m │ ├── daemon.c │ ├── main.c │ ├── platform.c │ ├── pspawn.c │ └── xpc.c ├── systemhook │ ├── .gitignore │ ├── Makefile │ ├── common.c │ ├── envbuf.c │ ├── get_libiosexec.c │ ├── getgrent.c │ ├── getpwent.c │ ├── getusershell.c │ └── main.c └── universalhooks │ ├── .gitignore │ ├── Makefile │ ├── cfprefsd.c │ ├── headboard.c │ ├── lsd.m │ ├── main.c │ ├── pineboard.m │ ├── securityd.c │ ├── springboard.m │ ├── trollstorehelper.c │ └── watchdogd.c └── tools ├── Makefile └── patch_dyld-test ├── .gitignore ├── Makefile ├── include ├── fakedyld │ └── fakedyld.h ├── patches └── plooshfinder └── main.c /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | pull_request: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | runs-on: macos-13 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | with: 15 | submodules: true 16 | 17 | - name: Select correct Xcode 18 | uses: mobiledevops/xcode-select-version-action@v1 19 | with: 20 | xcode-select-version: 15.2 21 | 22 | - name: Install dependencies (packages) 23 | run: | 24 | brew install make gnu-sed ldid-procursus fakeroot 25 | 26 | - name: Install dependecies 27 | run: | 28 | curl -LOO https://static.palera.in/artifacts/loader/universal_lite/palera1nLoader{TV,}.ipa 29 | curl -LO https://static.palera.in/binpack.tar 30 | install -m644 binpack.tar palera1nLoader{TV,}.ipa src 31 | 32 | - name: Compile 33 | run: | 34 | gmake -j1 tools 35 | gmake -j$(sysctl -n hw.ncpu) 36 | 37 | - name: Prepare for upload (RELEASE) 38 | run: | 39 | mkdir dist 40 | cp src/ramdisk.dmg dist/ramdisk.dmg 41 | cp src/binpack.dmg dist/binpack.dmg 42 | 43 | - name: Compile DEVELOPMENT 44 | run: | 45 | gmake clean 46 | gmake -j$(sysctl -n hw.ncpu) DEV_BUILD=1 47 | 48 | 49 | - name: Prepare for upload (DEVELOPMENT) 50 | run: | 51 | cp src/ramdisk.dmg dist/ramdisk.development.dmg 52 | cp src/binpack.dmg dist/binpack.development.dmg 53 | 54 | - name: Upload artifact 55 | uses: wangyucode/sftp-upload-action@v1.4.8 56 | with: 57 | host: ${{ secrets.NICKCHAN_FTP_HOST }} 58 | port: ${{ secrets.NICKCHAN_FTP_PORT }} 59 | username: palera1n 60 | password: ${{ secrets.NICKCHAN_FTP_PASS }} 61 | forceUpload: true 62 | dryRun: false 63 | localDir: 'dist/' 64 | remoteDir: '/palera1n/c-rewrite/deps/' 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .DS_Store 3 | *.o 4 | *.dmg 5 | test 6 | palera1n 7 | checkra1n 8 | plooshra1n 9 | apple-include 10 | statfs 11 | statfs.c 12 | *.xz 13 | *.lzma 14 | *.dSYM 15 | *.dSYM.zip 16 | bootscreend 17 | bootscreend.xml 18 | launchd 19 | build 20 | plooshInit.xcodeproj/project.xcworkspace/xcuserdata 21 | plooshInit.xcodeproj/xcuserdata/ 22 | *.img 23 | *.log 24 | *.sdk 25 | *.tar 26 | src/ellekit/libellekit.dylib 27 | a.out 28 | dyld.* 29 | tools/libdmg-hfsplus/ide/xcode/libdmg-hfsplus.xcodeproj/xcuserdata/ 30 | shared/RSOD.heic 31 | src/palera1nLoaderTV.ipa 32 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/rootlesshooks/ellekit"] 2 | path = src/ellekit/ellekit 3 | url = https://github.com/evelyneee/ellekit 4 | [submodule "tools/libdmg-hfsplus"] 5 | path = tools/libdmg-hfsplus 6 | url = git@github.com:palera1n/libdmg-hfsplus.git 7 | [submodule "src/bridgehook/dobby"] 8 | path = src/bridgehook/dobby 9 | url = git@github.com:jmpews/Dobby.git 10 | [submodule "src/payload/libroot"] 11 | path = src/payload/libroot 12 | url = git@github.com:opa334/libroot.git 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # plooshInit 2 | 3 | how to compile on macos: 4 | 5 | 1. make sure xcode is installed 6 | 2. install gnu sed, procursus ldid and gnu make 7 | (`brew install gnu-sed make ldid-procursus`) 8 | 3. get the two dependency files, they are the palera1n loader 9 | ipa and the procursus binpack. 10 | get [palera1nLoader.ipa](https://static.palera.in/artifacts/loader/universal_lite/palera1nLoader.ipa), [palera1nLoaderTV.ipa](https://static.palera.in/artifacts/loader/universal_lite/palera1nLoaderTV.ipa) and place it into the src directory. 11 | get [binpack.tar](https://static.palera.in/binpack.tar) and also place it in the src directory 12 | 4. `gmake -j$(sysctl -n hw.ncpu)` 13 | 14 | compiling on ios/ipados: 15 | 16 | 1. must be jailbroken and strapped with Procursus (or palera1n strap which is effectively Procursus) 17 | 2. `sudo apt install build-essential git make unzip ldid odcctools llvm bash sed` 18 | 3. place [palera1nLoader.ipa](https://static.palera.in/artifacts/loader/universal_lite/palera1nLoader.ipa) [binpack.tar](https://static.palera.in/binpack.tar) into src directory 19 | place [libellekit.dylib](https://static.palera.in/development/libellekit.dylib) into src/ellekit directory 20 | 4. prepare iPhoneOS.sdk and MacOSX.sdk of the same darwin version, 21 | export path to iPhoneOS.sdk in TARGET_SYSROOT environmental variable, 22 | and path to MacOSX.sdk in MACOSX_SYSROOT environmental variable 23 | 5. `make -j$(sysctl -n hw.ncpu)` 24 | 25 | compiling on linux/other unix: 26 | 27 | more or less the same as compiling on ios, but notably you need to make sure 28 | your toolchain includes the compiler-rt builtins for ios, otherwise you will 29 | get an error related to ___isPlatformVersionAtLeast. 30 | 31 | you can get the builtins from xcode and copy them onto your toolchains's 32 | compiler-rt builtin path 33 | 34 | compiler-rt builtin path in Xcode.app: 35 | `Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/${APPLE_CLANG_VERSION}/lib` 36 | 37 | usual distro compiler-rt builtin path 38 | `/usr/lib/clang/${LLVM_MAJOR_V}/lib` or `/usr/lib/llvm-${LLVM_MAJOR_V}/lib/clang/${LLVM_VERSION}` 39 | 40 | useful links: 41 | - [cctools-port](https://github.com/tpoechtrager/cctools-port) - Apple cctools port for Linux/*BSD 42 | - [unxip](https://github.com/saagarjha/unxip) - Fast Xcode unarchiver in swift 43 | - [Xcode releases](https://xcodereleases.com/) - Xcode download site 44 | - [Darling unxip](https://github.com/darlinghq/darling/tree/master/src/unxip) - Another Xcode unarchiver if you can't build swift for some reason 45 | 46 | after compiling: 47 | - check the output files, src/ramdisk.dmg and src/binpack.dmg 48 | - you can use the files in palera1n like this: `palera1n -r /path/to/ramdisk.dmg -o /path/to/binpack.dmg` 49 | -------------------------------------------------------------------------------- /apfs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern kern_return_t APFSVolumeDelete(const char *dev); 5 | 6 | int main(int argc, const char **argv) 7 | { 8 | if(argc != 2) 9 | { 10 | fprintf(stderr, "Usage: %s diskN\n", argv[0]); 11 | return -1; 12 | } 13 | kern_return_t ret = APFSVolumeDelete(argv[1]); 14 | if(ret != KERN_SUCCESS) 15 | { 16 | fprintf(stderr, "APFSVolumeDelete: %s\n", mach_error_string(ret)); 17 | return -1; 18 | } 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /apple-include-private/APFS/APFSConstants.h: -------------------------------------------------------------------------------- 1 | #ifndef _APFSCONSTANTS_H_ 2 | #define _APFSCONSTANTS_H_ 3 | 4 | #include 5 | 6 | #define apple_apfs 0x1200 7 | 8 | #define APFS_BUNDLE_ID "com.apple.filesystems.apfs" 9 | #define APFS_CONTAINER_OBJECT "AppleAPFSContainer" 10 | #define APFS_VOLUME_OBJECT "AppleAPFSVolume" 11 | 12 | #define APFS_VOL_ROLE_NONE 0x0000 13 | #define APFS_VOL_ROLE_SYSTEM 0x0001 14 | #define APFS_VOL_ROLE_USER 0x0002 15 | #define APFS_VOL_ROLE_RECOVERY 0x0004 16 | #define APFS_VOL_ROLE_VM 0x0008 17 | #define APFS_VOL_ROLE_PREBOOT 0x0010 18 | #define APFS_VOL_ROLE_INSTALLER 0x0020 19 | #define APFS_VOL_ROLE_DATA 0x0040 20 | #define APFS_VOL_ROLE_BASEBAND 0x0080 21 | #define APFS_VOL_ROLE_RESERVED_200 0x0200 22 | 23 | #define APFS_VOL_ROLES_VALID_MASK (APFS_VOL_ROLE_SYSTEM \ 24 | | APFS_VOL_ROLE_USER \ 25 | | APFS_VOL_ROLE_RECOVERY \ 26 | | APFS_VOL_ROLE_VM \ 27 | | APFS_VOL_ROLE_PREBOOT \ 28 | | APFS_VOL_ROLE_INSTALLER \ 29 | | APFS_VOL_ROLE_DATA \ 30 | | APFS_VOL_ROLE_BASEBAND \ 31 | | APFS_VOL_ROLE_RESERVED_200) 32 | 33 | #define EDT_OS_ENV_MAIN 1 34 | #define EDT_OS_ENV_OTHER 2 35 | #define EDT_OS_ENV_DIAGS 3 36 | 37 | #define EDTVolumeFSType "apfs" 38 | #define EDTVolumePropertySize (2 << 4) 39 | #define EDTVolumePropertyMaxSize (2 << 7) // Guessed 40 | 41 | #define kAPFSStatusKey "Status" 42 | #define kAPFSRoleKey "Role" 43 | #define kAPFSVolumeRoleSystem "System" 44 | #define kAPFSVolGroupUUIDKey "VolGroupUUID" 45 | 46 | #define kEDTFilesystemEntry "IODeviceTree:/filesystems/fstab" 47 | #define kEDTOSEnvironment CFSTR("os_env_type") 48 | 49 | enum { 50 | kAPFSXSubType = 0, /* APFS Case-sensitive */ 51 | kAPFSSubType = 1 /* APFS Case-insensitive */ 52 | }; 53 | 54 | extern CFStringRef kAPFSContainerBlocksizeKey; 55 | extern CFStringRef kAPFSContainerExtentAddressKey; 56 | extern CFStringRef kAPFSContainerExtentLengthKey; 57 | extern CFStringRef kAPFSContainerExtentsListKey; 58 | extern CFStringRef kAPFSContainerFSTypeKey; 59 | extern CFStringRef kAPFSContainerSizeKey; 60 | extern CFStringRef kAPFSContainerTidemarkKey; 61 | extern CFStringRef kAPFSStreamCreateEmbedCRC; 62 | extern CFStringRef kAPFSStreamCreateReadAlignment; 63 | extern CFStringRef kAPFSVolumeCaseSensitiveKey; 64 | extern CFStringRef kAPFSVolumeEffaceableKey; 65 | extern CFStringRef kAPFSVolumeEncryptedKey; 66 | extern CFStringRef kAPFSVolumeEncryptedACMKey; 67 | extern CFStringRef kAPFSVolumeFSIndexKey; 68 | extern CFStringRef APFSVolumeGroupSiblingFSIndexKey; 69 | extern CFStringRef kAPFSVolumeNameKey; 70 | extern CFStringRef kAPFSVolumeNoAutomountAtCreateKey; 71 | extern CFStringRef kAPFSVolumeQuotaSizeKey; 72 | extern CFStringRef kAPFSVolumeReserveSizeKey; 73 | extern CFStringRef kAPFSVolumeRoleKey; 74 | #endif 75 | -------------------------------------------------------------------------------- /apple-include-private/CoreServices/FSNodePropertyProviding.h: -------------------------------------------------------------------------------- 1 | #ifndef CORESERVICES_FSNODEPROPERTYPROVIDING_H 2 | #define CORESERVICES_FSNODEPROPERTYPROVIDING_H 3 | #include 4 | 5 | @protocol FSNodePropertyProviding 6 | 7 | @required 8 | 9 | - (NSURL *)URL; 10 | - (bool)canIssueIO; 11 | - (NSString *)canonicalPathWithError:(id*)arg1; 12 | - (bool)childNodeWithRelativePathExists:(NSString *)arg1; 13 | - (NSString *)extensionWithError:(id*)arg1; 14 | - (bool)getCachedResourceValueIfPresent:(id*)arg1 forKey:(NSString *)arg2 error:(id*)arg3; 15 | - (bool)getContentModificationDate:(double*)arg1 error:(id*)arg2; 16 | - (bool)getCreationDate:(double*)arg1 error:(id*)arg2; 17 | - (bool)getDeviceNumber:(int*)arg1 error:(id*)arg2; 18 | - (bool)getFileIdentifier:(unsigned long long*)arg1 error:(id*)arg2; 19 | - (bool)getFileSystemRepresentation:(BOOL)arg1 error:(id*)arg2; 20 | - (bool)getHFSType:(unsigned int*)arg1 creator:(unsigned int*)arg2 error:(id*)arg3; 21 | - (bool)getInodeNumber:(unsigned long long*)arg1 error:(id*)arg2; 22 | - (bool)getLength:(unsigned long long*)arg1 error:(id*)arg2; 23 | - (bool)getOwnerUID:(unsigned int*)arg1 error:(id*)arg2; 24 | - (bool)getResourceValue:(id*)arg1 forKey:(NSString *)arg2 options:(unsigned char)arg3 error:(id*)arg4; 25 | - (bool)getVolumeIdentifier:(unsigned long long*)arg1 error:(id*)arg2; 26 | - (bool)hasHiddenExtension; 27 | - (bool)hasPackageBit; 28 | - (bool)isAVCHDCollection; 29 | - (bool)isAliasFile; 30 | - (bool)isBusyDirectory; 31 | - (bool)isDirectory; 32 | - (bool)isExecutable; 33 | - (bool)isExecutableModeFile; 34 | - (bool)isHidden; 35 | - (bool)isMountTrigger; 36 | - (bool)isOnDiskImage; 37 | - (bool)isOnLocalVolume; 38 | - (bool)isRegularFile; 39 | - (bool)isResolvable; 40 | - (bool)isSecuredSystemContent; 41 | - (bool)isSideFault; 42 | - (bool)isSymbolicLink; 43 | - (bool)isVolume; 44 | - (NSString *)nameWithError:(id*)arg1; 45 | - (NSString *)pathWithError:(id*)arg1; 46 | - (NSDictionary *)sideFaultResourceValuesWithError:(id*)arg1; 47 | 48 | @end 49 | #endif 50 | -------------------------------------------------------------------------------- /apple-include-private/IOMobileFramebuffer/IOMobileframebuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef IOMOBILEFRAMEBUFFER_IOMOBILEFRAMEBUFFER_H 2 | #define IOMOBILEFRAMEBUFFER_IOMOBILEFRAMEBUFFER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef IOReturn IOMobileFramebufferReturn; 10 | typedef struct __IOMobileFramebuffer *IOMobileFramebufferRef; 11 | typedef CGSize IOMobileFramebufferDisplaySize; 12 | 13 | __BEGIN_DECLS 14 | 15 | IOMobileFramebufferReturn 16 | IOMobileFramebufferGetMainDisplay(IOMobileFramebufferRef *pointer); 17 | 18 | IOMobileFramebufferReturn 19 | IOMobileFramebufferGetSecondaryDisplay(IOMobileFramebufferRef *pointer); 20 | 21 | IOMobileFramebufferReturn 22 | IOMobileFramebufferGetDisplaySize(IOMobileFramebufferRef pointer, IOMobileFramebufferDisplaySize *size); 23 | 24 | IOMobileFramebufferReturn 25 | IOMobileFramebufferGetLayerDefaultSurface(IOMobileFramebufferRef pointer, int surface, IOSurfaceRef *buffer); 26 | 27 | IOMobileFramebufferReturn 28 | IOMobileFramebufferSwapBegin(IOMobileFramebufferRef pointer, int *token); 29 | 30 | IOMobileFramebufferReturn 31 | IOMobileFramebufferSwapEnd(IOMobileFramebufferRef pointer); 32 | 33 | IOMobileFramebufferReturn 34 | IOMobileFramebufferSwapSetLayer(IOMobileFramebufferRef pointer, int layerid, IOSurfaceRef buffer, CGRect bounds, CGRect frame, int flags); 35 | 36 | __END_DECLS 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /apple-include-private/os/alloc_once_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2013 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. The rights granted to you under the License 10 | * may not be used to create, or enable the creation or redistribution of, 11 | * unlawful or unlicensed copies of an Apple operating system, or to 12 | * circumvent, violate, or enable the circumvention or violation of, any 13 | * terms of an Apple operating system software license agreement. 14 | * 15 | * Please obtain a copy of the License at 16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 | * 18 | * The Original Code and all software distributed under the License are 19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 | * Please see the License for the specific language governing rights and 24 | * limitations under the License. 25 | * 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 | */ 28 | 29 | #ifndef __OS_ALLOC_ONCE_IMPL__ 30 | #define __OS_ALLOC_ONCE_IMPL__ 31 | 32 | #ifndef __OS_ALLOC_INDIRECT__ 33 | #error "Please include instead of this file directly." 34 | #endif 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | __BEGIN_DECLS 42 | 43 | #define OS_ALLOC_SPI_VERSION 20120430 44 | 45 | #define OS_ALLOC_ONCE_KEY_MAX 100 46 | 47 | typedef os_once_t os_alloc_token_t; 48 | struct _os_alloc_once_s { 49 | os_alloc_token_t once; 50 | void *ptr; 51 | }; 52 | 53 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 54 | extern struct _os_alloc_once_s _os_alloc_once_table[]; 55 | 56 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 57 | OS_EXPORT OS_NONNULL1 58 | void* 59 | _os_alloc_once(struct _os_alloc_once_s *slot, size_t sz, os_function_t init); 60 | 61 | /* 62 | * The region allocated by os_alloc_once is 0-filled when initially 63 | * returned (or handed off to the initializer). 64 | */ 65 | OS_WARN_RESULT OS_NOTHROW OS_CONST 66 | __header_always_inline void* 67 | os_alloc_once(os_alloc_token_t token, size_t sz, os_function_t init) 68 | { 69 | struct _os_alloc_once_s *slot = &_os_alloc_once_table[token]; 70 | if (OS_EXPECT(slot->once, ~0l) != ~0l) { 71 | void *ptr = _os_alloc_once(slot, sz, init); 72 | OS_COMPILER_CAN_ASSUME(slot->once == ~0l); 73 | return ptr; 74 | } 75 | return slot->ptr; 76 | } 77 | 78 | __END_DECLS 79 | 80 | #endif // __OS_ALLOC_ONCE_IMPL__ 81 | -------------------------------------------------------------------------------- /apple-include-private/os/base_private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __OS_BASE_PRIVATE__ 22 | #define __OS_BASE_PRIVATE__ 23 | 24 | #ifndef KERNEL 25 | #include 26 | #endif 27 | #include 28 | 29 | #ifndef os_fastpath 30 | #define os_fastpath(x) ((__typeof__(x))OS_EXPECT((long)(x), ~0l)) 31 | #endif 32 | #ifndef os_slowpath 33 | #define os_slowpath(x) ((__typeof__(x))OS_EXPECT((long)(x), 0l)) 34 | #endif 35 | #ifndef os_likely 36 | #define os_likely(x) OS_EXPECT(!!(x), 1) 37 | #endif 38 | #ifndef os_unlikely 39 | #define os_unlikely(x) OS_EXPECT(!!(x), 0) 40 | #endif 41 | 42 | 43 | #endif // __OS_BASE_PRIVATE__ 44 | -------------------------------------------------------------------------------- /apple-include-private/os/once_private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | #ifndef __OS_ONCE_PRIVATE__ 22 | #define __OS_ONCE_PRIVATE__ 23 | 24 | #include 25 | #include 26 | 27 | OS_ASSUME_NONNULL_BEGIN 28 | 29 | __BEGIN_DECLS 30 | 31 | #define OS_ONCE_SPI_VERSION 20130313 32 | 33 | OS_SWIFT_UNAVAILABLE("Swift has lazy init") 34 | typedef long os_once_t; 35 | 36 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0) 37 | OS_EXPORT OS_NONNULL1 OS_NONNULL3 OS_NOTHROW 38 | OS_SWIFT_UNAVAILABLE("Swift has lazy init") 39 | void 40 | _os_once(os_once_t *predicate, void *_Nullable context, os_function_t function); 41 | 42 | OS_NONNULL1 OS_NONNULL3 OS_NOTHROW 43 | __header_always_inline void 44 | os_once(os_once_t *predicate, void *_Nullable context, os_function_t function) 45 | { 46 | if (OS_EXPECT(*predicate, ~0l) != ~0l) { 47 | _os_once(predicate, context, function); 48 | OS_COMPILER_CAN_ASSUME(*predicate == ~0l); 49 | } else { 50 | os_compiler_barrier(); 51 | } 52 | } 53 | 54 | /* This SPI is *strictly* for the use of pthread_once only. This is not 55 | * safe in general use of os_once. 56 | */ 57 | __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0) 58 | OS_EXPORT OS_NONNULL1 OS_NOTHROW 59 | OS_SWIFT_UNAVAILABLE("Swift has lazy init") 60 | void 61 | __os_once_reset(os_once_t *val); 62 | 63 | __END_DECLS 64 | 65 | OS_ASSUME_NONNULL_END 66 | 67 | #endif // __OS_ONCE_PRIVATE__ 68 | -------------------------------------------------------------------------------- /apple-include-private/xpc/xpc_transcation_deprecate.h: -------------------------------------------------------------------------------- 1 | #ifndef __XPC_TRANSACTION_DEPRECATE_H__ 2 | #define __XPC_TRANSACTION_DEPRECATE_H__ 3 | 4 | #include 5 | #include 6 | 7 | #ifndef __XPC_INDIRECT__ 8 | #error "Please #include instead of this file directly." 9 | #endif // __XPC_INDIRECT__ 10 | 11 | #ifndef XPC_TRANSACTION_DEPRECATED 12 | #define XPC_TRANSACTION_DEPRECATED 13 | #endif 14 | 15 | #pragma mark Transactions 16 | 17 | __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0) 18 | XPC_TRANSACTION_DEPRECATED 19 | void 20 | xpc_transaction_exit_clean(void); 21 | 22 | __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0) 23 | XPC_TRANSACTION_DEPRECATED 24 | void 25 | xpc_transaction_interrupt_clean_exit(void); 26 | 27 | __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_5_0) 28 | XPC_TRANSACTION_DEPRECATED 29 | void 30 | xpc_transactions_enable(void); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /build.command: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This file is for Xcode only! Do not run directly 4 | 5 | set -e 6 | 7 | UNAME_M="$(uname -m)" 8 | 9 | export PATH="${HOME}/.local/bin:/opt/procursus/bin:/usr/local/bin:/opt/homebrew/bin:${PATH}" 10 | echo "Invoked as: $0 $@" 11 | 12 | if [ "$XCODE_VERSION_ACTUAL" = "" ]; then 13 | >&2 echo "$0 cannot be ran directly." 14 | exit 1; 15 | fi 16 | 17 | if [ "$PALERA1N" = "" ]; then 18 | PALERA1N="palera1n" 19 | fi 20 | 21 | PALERA1NS="palera1n palera1n-macos-universal palera1n-macos-x86_64" 22 | 23 | if [ "$UNAME_M" = "arm64" ]; then 24 | PALERA1NS="${PALERA1NS} palera1n-macos-arm64" 25 | fi 26 | 27 | for p1 in ${PALERA1NS}; do 28 | if [ "$(command -v $p1)" != "" ]; then 29 | PALERA1N="$(command -v $p1)" 30 | break; 31 | fi 32 | done 33 | 34 | if ! [ -f "$BUILT_PRODUCTS_DIR"/../.didbuild ]; then 35 | gmake -j$(sysctl -n hw.ncpu) clean 36 | fi 37 | 38 | touch "$BUILT_PRODUCTS_DIR"/../.didbuild 39 | 40 | case "$ACTION" in 41 | clean) 42 | gmake -j$(sysctl -n hw.ncpu) clean 43 | ;; 44 | run) 45 | "${PALERA1N}" -le serial=3 -r "${RAMDISK_DMG}" -o "${BINPACK_DMG}" 46 | ;; 47 | *) 48 | gmake -j$(sysctl -n hw.ncpu) 49 | cp -a src/ramdisk.dmg src/binpack.dmg "$BUILT_PRODUCTS_DIR" 50 | ;; 51 | esac 52 | -------------------------------------------------------------------------------- /include/dyld-interpose.h: -------------------------------------------------------------------------------- 1 | #ifndef DYLD_INTERPOSE_H 2 | #define DYLD_INTERPOSE_H 3 | 4 | #define DYLD_INTERPOSE(_replacment,_replacee) \ 5 | __attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \ 6 | __attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee }; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/fakedyld/fakedyld.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKEDYLD_H 2 | #define FAKEDYLD_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define PLATFORM_IOS 2 22 | #define PLATFORM_TVOS 3 23 | #define PLATFORM_BRIDGEOS 5 24 | 25 | extern char** environ; 26 | extern const struct KernelArgs* gKernArgs; 27 | extern void* gPreDyldMH; 28 | 29 | #define PRIx64 "llx" 30 | 31 | void mountroot(struct paleinfo* pinfo_p, struct systeminfo* sysinfo_p); 32 | void init_cores(struct systeminfo* sysinfo_p, int platform, bool ramdisk_boot); 33 | void patch_dyld(memory_file_handle_t* dyld_handle, int platform); 34 | void check_dyld(const memory_file_handle_t* dyld_handle); 35 | int get_platform(const memory_file_handle_t* dyld_handle); 36 | void prepare_rootfs(struct systeminfo* sysinfo_p, struct paleinfo* pinfo_p, int platform); 37 | void systeminfo(struct systeminfo* sysinfo_p); 38 | void set_fd_console(int fd_console); 39 | void clean_fakefs(char* rootdev); 40 | _Noreturn void panic(char* fmt, ...); 41 | const char* find_realfs(void); 42 | #ifdef FAKEDYLD_ENABLE_LOGGING 43 | #else 44 | #define panic(...) panic(""); 45 | #undef printf 46 | #define printf(...) 47 | #endif 48 | #endif 49 | -------------------------------------------------------------------------------- /include/fakedyld/graftdmg_un.h: -------------------------------------------------------------------------------- 1 | #ifndef _GRAFTDMG_UN_ 2 | #define _GRAFTDMG_UN_ 3 | 4 | #include 5 | 6 | #define GRAFTDMG_SECURE_BOOT_CRYPTEX_ARGS_VERSION 1 7 | #define MAX_GRAFT_ARGS_SIZE 512 8 | 9 | /* Flag values for secure_boot_cryptex_args.sbc_flags */ 10 | #define SBC_PRESERVE_MOUNT 0x0001 /* Preserve underlying mount until shutdown */ 11 | #define SBC_ALTERNATE_SHARED_REGION 0x0002 /* Binaries within should use alternate shared region */ 12 | #define SBC_SYSTEM_CONTENT 0x0004 /* Cryptex contains system content */ 13 | #define SBC_PANIC_ON_AUTHFAIL 0x0008 /* On failure to authenticate, panic */ 14 | #define SBC_STRICT_AUTH 0x0010 /* Strict authentication mode */ 15 | #define SBC_PRESERVE_GRAFT 0x0020 /* Preserve graft itself until unmount */ 16 | 17 | typedef struct secure_boot_cryptex_args { 18 | uint32_t sbc_version; /* 1 */ 19 | uint32_t sbc_4cc; /* ??? */ 20 | int sbc_authentic_manifest_fd; /* apticket im4m ??? */ 21 | int sbc_user_manifest_fd; /* dmg trustcache im4p */ 22 | int sbc_payload_fd; /* dmg root hash */ 23 | uint64_t sbc_flags; 24 | } __attribute__((aligned(4), packed)) secure_boot_cryptex_args_t; 25 | 26 | typedef union graft_args { 27 | uint8_t max_size[MAX_GRAFT_ARGS_SIZE]; 28 | secure_boot_cryptex_args_t sbc_args; 29 | } graftdmg_args_un; 30 | #endif /* _GRAFTDMG_UN_ */ 31 | -------------------------------------------------------------------------------- /include/fakedyld/lib.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKEDYLD_LIB_H 2 | #define FAKEDYLD_LIB_H 3 | #include 4 | #include 5 | 6 | void *memcpy(void *dst, const void *src, size_t n); 7 | void *memmove(void *dest, const void *src, size_t n); 8 | int isdigit(int c); 9 | int isspace(int c); 10 | int atoi(const char* str); 11 | void bzero (void *s, size_t n); 12 | int isupper(int c); 13 | int isalpha(int c); 14 | void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen); 15 | int fs_snapshot_list(int dirfd, struct attrlist *alist, void *attrbuf, size_t bufsize, uint32_t flags); 16 | int fs_snapshot_create(int dirfd, const char *name, uint32_t flags); 17 | int fs_snapshot_delete(int dirfd, const char *name, uint32_t flags); 18 | int fs_snapshot_rename(int dirfd, const char *old, const char *new, uint32_t flags); 19 | int fs_snapshot_revert(int dirfd, const char *name, uint32_t flags); 20 | int fs_snapshot_root(int dirfd, const char *name, uint32_t flags); 21 | int fs_snapshot_mount(int dirfd, const char *dir, const char *snapshot, uint32_t flags); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/fakedyld/rw_file.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKEDYLD_RWFILE_H 2 | #define FAKEDYLD_RWFILE_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | char* file_p; 8 | size_t file_len; 9 | } memory_file_handle_t; 10 | 11 | void read_file(char* path, memory_file_handle_t* handle); 12 | /* WARNING: using this function will DESTROY the handle */ 13 | void write_file(char* path, memory_file_handle_t* handle); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/fakedyld/spawn.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKEDYLD_SPAWN_H 2 | #define FAKEDYLD_SPAWN_H 3 | 4 | #include 5 | #include 6 | 7 | int posix_spawn(pid_t *pid, const char *path, const void* adesc, char **argv, char **envp); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/fakedyld/startup.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKEDYLD_STARTUP_H 2 | #define FAKEDYLD_STARTUP_H 3 | 4 | #include 5 | 6 | #define MAX_KERNEL_ARGS 128 7 | 8 | /* how kernel passes argc, argv, envp, apple etc */ 9 | struct KernelArgs { 10 | const void* mainExecutable; 11 | uintptr_t argc; 12 | /* basically argv, envp and apple squished together */ 13 | const char* args[MAX_KERNEL_ARGS]; 14 | }; 15 | 16 | #if 1 17 | int main(int argc, char* argv[], char* envp[], char* apple[]); 18 | #else 19 | int main(); 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/fakedyld/string.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKEDYLD_STRING_H 2 | #define FAKEDYLD_STRING_H 3 | 4 | #include 5 | extern const char* const sys_errlist[]; 6 | 7 | size_t strlen(const char* str); 8 | char *strstr(const char *string, char *substring); 9 | char *strchr(const char *p, int ch); 10 | int strncmp(const char* s1, const char* s2, size_t n); 11 | int strcmp(const char* s1, const char* s2); 12 | unsigned long strtoul(const char *nptr, char **endptr, register int base); 13 | unsigned long long strtoull(const char *nptr, char **endptr, register int base); 14 | 15 | const char* strerror(int err); 16 | #endif 17 | -------------------------------------------------------------------------------- /include/fakedyld/syscalls.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKEDYLD_SYSCALLS_H 2 | #define FAKEDYLD_SYSCALLS_H 3 | 4 | #ifndef __ASSEMBLER__ 5 | #include 6 | #include 7 | #endif 8 | 9 | #define SYS_exit 1 10 | #define SYS_fork 2 11 | #define SYS_read 3 12 | #define SYS_write 4 13 | #define SYS_open 5 14 | #define SYS_close 6 15 | #define SYS_wait4 7 16 | #define SYS_link 9 17 | #define SYS_unlink 10 18 | #define SYS_chdir 12 19 | #define SYS_fchdir 13 20 | #define SYS_mknod 14 21 | #define SYS_chmod 15 22 | #define SYS_chown 16 23 | #define SYS_reboot 55 24 | #define SYS_symlink 57 25 | #define SYS_execve 59 26 | #define SYS_chroot 61 27 | #define SYS_munmap 73 28 | #define SYS_dup2 90 29 | #define SYS_mkdir 136 30 | #define SYS_rmdir 137 31 | #define SYS_unmount 159 32 | #define SYS_mount 167 33 | #define SYS_stat 188 34 | #define SYS_mmap 197 35 | #define SYS_lseek 199 36 | #define SYS_posix_spawn 244 37 | #define SYS_sys_sysctlbyname 274 38 | #define SYS_stat64 338 39 | #define SYS_getdirentries64 344 40 | #define SYS_statfs64 345 41 | #define SYS_getattrlistbulk 461 42 | #define SYS_fs_snapshot 518 43 | #define SYS_abort_with_payload 521 44 | 45 | #ifndef __ASSEMBLER__ 46 | int* __error(void); 47 | #define errno (*__error()) 48 | 49 | uint64_t msyscall(uint64_t syscall, ...); 50 | 51 | void sleep(int secs); 52 | /* keep this list in order of syscall numbers */ 53 | void exit(int rval); 54 | int fork(void); 55 | ssize_t read(int fd, void *cbuf, size_t nbyte); 56 | ssize_t write(int fd, void *cbuf, size_t nbyte); 57 | int open(char* path, int flags, int mode); 58 | int close(int fd); 59 | int link(char* path, char* link); 60 | int unlink(char* path); 61 | int chdir(char* path); 62 | int fchdir(int fd); 63 | int mknod(char* path, int mode, int dev); 64 | int chmod(char* path, int mode); 65 | int chown(char* path, int uid, int gid); 66 | int reboot(int opt, char* msg); 67 | int symlink(char *path, char *link); 68 | int execve(char* fname, char** argp, char** envp); 69 | int chroot(char* path); 70 | int munmap(void* addr, size_t len); 71 | int dup2(int from, int to); 72 | int mkdir(char* path, int mode); 73 | int rmdir(char* path); 74 | int unmount(char *path, int flags); 75 | int mount(char* type, char* path, int flags, void* data); 76 | int stat64(void *path, struct stat64 *ub); 77 | void *mmap(void *addr, size_t length, int prot, int flags, int fd, uint64_t offset); 78 | uint64_t lseek(int fildes, int32_t offset, int whence); 79 | int sys_sysctlbyname(const char *name, size_t namelen, void *old, size_t *oldlenp, void *new_, size_t newlen); 80 | ssize_t getdirentries64(int fd, void *buf, size_t bufsize, off_t *position); 81 | int getattrlistbulk(int dirfd, struct attrlist *alist, void *attributeBuffer, size_t bufferSize, uint64_t options); 82 | int statfs64(char *path, struct statfs64 *buf); 83 | int fs_snapshot(uint32_t op, int dirfd, const char* name1, const char* name2, void* data, uint32_t flags); 84 | int wait4(int pid, int* status, int options, void* rusage); 85 | _Noreturn void abort_with_payload(uint32_t reason_namespace, uint64_t reason_code, void *payload, uint32_t payload_size, const char *reason_string, uint64_t reason_flags); 86 | #endif 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /include/fakedyld/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKEDYLD_UTILS_H 2 | #define FAKEDYLD_UTILS_H 3 | 4 | #include 5 | #include 6 | 7 | void spin(void); 8 | void get_pinfo(struct paleinfo* pinfo_p); 9 | void pinfo_check(struct paleinfo* pinfo_p); 10 | /* declared in assembly */ 11 | uint64_t lz4dec(const void *src, void *dst, uint64_t srcsz, uint64_t dstsz); 12 | 13 | #ifndef RAW_RAMDISK 14 | #define RAW_RAMDISK "/dev/rmd0" 15 | #endif 16 | 17 | #ifndef RAMDISK 18 | #define RAMDISK "/dev/md0" 19 | #endif 20 | 21 | #define DARWIN21_ROOTDEV "disk0s1s1" 22 | #define DARWIN22_ROOTDEV "disk1s1" 23 | 24 | #define MAX_BOOTARGS_LEN 0x400 25 | #define MAX_KVERSION_LEN 256 26 | #define MAX_OSRELEASE_LEN 16 27 | 28 | #define likely(x) __builtin_expect(!!(x), 1) 29 | #define unlikely(x) __builtin_expect(!!(x), 0) 30 | 31 | struct systeminfo { 32 | char bootargs[MAX_BOOTARGS_LEN]; 33 | char kversion[MAX_KVERSION_LEN]; 34 | struct { 35 | int darwinMajor; /* ex. 22 */ 36 | int darwinMinor; /* ex. 5 */ 37 | int darwinRevision; /* most likely 0 */ 38 | } osrelease; 39 | int xnuMajor; /* ex. 8796 */ 40 | }; 41 | 42 | static inline int p1_log(const char* format, ...) { 43 | printf("fakedyld: "); 44 | va_list va; 45 | va_start(va, format); 46 | int ret = vprintf(format, va); 47 | va_end(va); 48 | printf("\n"); 49 | return ret; 50 | } 51 | #ifdef FAKEDYLD_ENABLE_LOGGING 52 | #define LOG(...) p1_log(__VA_ARGS__) 53 | #else 54 | #define LOG(...) 55 | #endif 56 | #define CHECK_ERROR(action, msg, ...) do { \ 57 | int check_error_ret = action; \ 58 | if (unlikely(check_error_ret)) { \ 59 | panic(msg ": %d", ##__VA_ARGS__, errno); \ 60 | } \ 61 | } while (0) 62 | 63 | #define fbi(mnt, dir) \ 64 | do \ 65 | { \ 66 | struct stat64 fbi_st; \ 67 | if (stat64(mnt, &fbi_st)) { \ 68 | LOG("Skipping bind mount %s because it does not exist", mnt); \ 69 | }\ 70 | int fbi_ret = mount("bindfs", mnt, MNT_RDONLY, dir); \ 71 | if (fbi_ret != 0) \ 72 | { \ 73 | panic("cannot bind %s onto %s, err=%d", dir, mnt, errno); \ 74 | } \ 75 | else \ 76 | { \ 77 | LOG("bound %s onto %s", dir, mnt); \ 78 | } \ 79 | } while (0) 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /include/libjailbreak/libjailbreak.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBJAILBREAK_LIBJAILBREAK_H 2 | #define LIBJAILBREAK_LIBJAILBREAK_H 3 | 4 | #include 5 | #include 6 | 7 | #define KERNELINFO_ENTITLEMENT "in.palera.pinfo.kernel-info" 8 | #define BOOTSTRAPPER_ENTITLEMENT "in.palera.loader.bootstrapper" 9 | #define OBLITERATOR_ENTITLEMENT "in.palera.loader.allow-obliterate-jailbreak" 10 | #define LAUNCHD_CMD_ENTITLEMENT "in.palera.private.launchd-commands.client" 11 | 12 | 13 | #define HOOK_DYLIB_PATH "/cores/binpack/usr/lib/systemhook.dylib" 14 | enum { 15 | JBD_CMD_GET_PINFO_FLAGS = 1, 16 | JBD_CMD_GET_PREBOOTPATH, 17 | JBD_CMD_GET_PINFO_KERNEL_INFO, 18 | JBD_CMD_GET_PINFO_ROOTDEV, 19 | JBD_CMD_DEPLOY_BOOTSTRAP, 20 | JBD_CMD_OBLITERATE_JAILBREAK, 21 | JBD_CMD_PERFORM_REBOOT3, 22 | JBD_CMD_OVERWRITE_FILE_WITH_CONTENT, 23 | JBD_CMD_INTERCEPT_USERSPACE_PANIC, 24 | JBD_CMD_EXIT_SAFE_MODE, 25 | JBD_CMD_RUN_AS_ROOT, 26 | JBD_CMD_REGISTER_PAYLOAD_PID, 27 | JBD_CMD_RESUME_PAYLOAD 28 | }; 29 | 30 | enum { 31 | LAUNCHD_CMD_RELOAD_JB_ENV = 1, 32 | LAUNCHD_CMD_SET_TWEAKLOADER_PATH, 33 | LAUNCHD_CMD_SET_PINFO_FLAGS, 34 | LAUNCHD_CMD_DRAW_IMAGE, 35 | LAUNCHD_CMD_CRASH, 36 | LAUNCHD_CMD_RUN_BOOTSCREEND, 37 | LAUNCHD_CMD_GET_BOOT_UUID 38 | }; 39 | 40 | struct xpc_global_data { 41 | uint64_t a; 42 | uint64_t xpc_flags; 43 | mach_port_t task_bootstrap_port; /* 0x10 */ 44 | #ifndef _64 45 | uint32_t padding; 46 | #endif 47 | xpc_object_t xpc_bootstrap_pipe; /* 0x18 */ 48 | }; 49 | 50 | int jailbreak_get_bmhash(char* hash); 51 | int jailbreak_get_prebootPath(char jbPath[150]); 52 | const char* jailbreak_str_pinfo_flag(uint64_t flag); 53 | xpc_object_t jailbreak_send_jailbreakd_message_with_reply_sync(xpc_object_t xdict); 54 | xpc_object_t jailbreak_send_jailbreakd_command_with_reply_sync(uint64_t cmd); 55 | int jailbreak_send_launchd_message(xpc_object_t xdict, xpc_object_t *xreply); 56 | int jailbreak_get_bmhash_path(char jbPath[150]); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /include/libroot.h: -------------------------------------------------------------------------------- 1 | ../src/payload/libroot/src/libroot.h -------------------------------------------------------------------------------- /include/patches/platform/patch.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLATFORM_PATCH_H 2 | #define _PLATFORM_PATCH_H 3 | #include 4 | #include 5 | 6 | void patch_platform_check(void *real_buf, void *dyld_buf, size_t dyld_len, uint32_t platform); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/patches/platform/shellcode.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLATFORM_SHC_H 2 | #define _PLATFORM_SHC_H 3 | #include 4 | 5 | uint32_t *copy_shc(void *buf, int platform, uint32_t jmp); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/payload_dylib/common.h: -------------------------------------------------------------------------------- 1 | #ifndef PAYLOAD_DYLIB_CRASHREPORTER_H 2 | #define PAYLOAD_DYLIB_CRASHREPORTER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define spin() _spin() 12 | 13 | #define likely(x) __builtin_expect(!!(x), 1) 14 | #define unlikely(x) __builtin_expect(!!(x), 0) 15 | 16 | #define CHECK_ERROR(action, msg) do { \ 17 | ret = action; \ 18 | if (unlikely(ret)) { \ 19 | _panic(msg ": %d (%s)\n", errno, strerror(errno)); \ 20 | } \ 21 | } while (0) 22 | 23 | extern uint64_t pflags; 24 | extern char** environ; 25 | 26 | extern bool bound_libiosexec; 27 | void _spin(void); 28 | int get_platform(void); 29 | 30 | extern int (*spawn_hook_common_p)(pid_t *restrict pid, const char *restrict path, 31 | const posix_spawn_file_actions_t *restrict file_actions, 32 | const posix_spawnattr_t *restrict attrp, 33 | char *const argv[restrict], 34 | char *const envp[restrict], 35 | void *pspawn_org); 36 | 37 | extern void (*MSHookFunction_p)(void *symbol, void *replace, void **result); 38 | void initSpawnHooks(void); 39 | void InitDaemonHooks(void); 40 | void InitXPCHooks(void); 41 | void load_bootstrapped_jailbreak_env(void); 42 | int bootscreend_draw_image(const char* image_path); 43 | const char* set_tweakloader_path(const char* path); 44 | extern int (*spawn_hook_common_p)(pid_t *restrict pid, const char *restrict path, 45 | const posix_spawn_file_actions_t *restrict file_actions, 46 | const posix_spawnattr_t *restrict attrp, 47 | char *const argv[restrict], 48 | char *const envp[restrict], 49 | void *pspawn_org); 50 | _Noreturn void _panic(char* fmt, ...); 51 | 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /include/payload_dylib/crashreporter.h: -------------------------------------------------------------------------------- 1 | #ifndef _PAYLOAD_DYLIB_CRASHREPORTER_H 2 | #define _PAYLOAD_DYLIB_CRASHREPORTER_H 3 | 4 | #include 5 | 6 | typedef int exception_type_t; 7 | typedef integer_t exception_data_type_t; 8 | 9 | typedef struct { 10 | mach_msg_header_t header; 11 | mach_msg_body_t msgh_body; 12 | mach_msg_port_descriptor_t thread; 13 | mach_msg_port_descriptor_t task; 14 | int unused1; 15 | exception_type_t exception; 16 | exception_data_type_t code; 17 | int unused2; 18 | int subcode; 19 | NDR_record_t ndr; 20 | } exception_raise_request; // the bits we need at least 21 | 22 | typedef struct { 23 | mach_msg_header_t header; 24 | NDR_record_t ndr; 25 | kern_return_t retcode; 26 | } exception_raise_reply; 27 | 28 | typedef struct { 29 | mach_msg_header_t header; 30 | NDR_record_t ndr; 31 | kern_return_t retcode; 32 | int flavor; 33 | mach_msg_type_number_t new_stateCnt; 34 | natural_t new_state[614]; 35 | } exception_raise_state_reply; 36 | 37 | typedef enum { 38 | kCrashReporterStateNotActive = 0, 39 | kCrashReporterStateActive = 1, 40 | kCrashReporterStatePaused = 2 41 | } crash_reporter_state; 42 | 43 | #ifdef HAVE_CRASHREPORTER 44 | void crashreporter_start(void); 45 | void crashreporter_pause(void); 46 | void crashreporter_resume(void); 47 | #else 48 | #define crashreporter_start() 49 | #define crashreporter_pause() 50 | #define crashreporter_resume() 51 | #endif 52 | 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /include/plooshfinder/asm/arm64.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | uint32_t arm64_branch(void *caller, void *target, bool link); -------------------------------------------------------------------------------- /include/plooshfinder/formats/defs/elf_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELF_DEFS_H 2 | #define _ELF_DEFS_H 3 | #include 4 | 5 | #define SHT_SYMTAB 0x2 6 | #define SHT_DYNSYM 0xb 7 | #define PT_LOAD 0x1 8 | 9 | struct elf_ident_64 { 10 | char signature[4]; 11 | uint8_t file_class; 12 | uint8_t encoding; 13 | uint8_t version; 14 | uint8_t os; 15 | uint8_t abi_version; 16 | char pad[7]; 17 | }; 18 | 19 | struct elf_header_64 { 20 | struct elf_ident_64 ident; 21 | uint16_t type; 22 | uint16_t machine; 23 | uint32_t version; 24 | uint64_t entry; 25 | uint64_t ph_off; 26 | uint64_t sh_off; 27 | uint32_t flags; 28 | uint16_t head_size; 29 | uint16_t ph_size; 30 | uint16_t ph_count; 31 | uint16_t sh_size; 32 | uint16_t sh_count; 33 | uint16_t sect_table_index; 34 | }; 35 | 36 | struct elf_pheader_64 { 37 | uint32_t type; 38 | uint32_t flags; 39 | uint64_t offset; 40 | uint64_t virtual_address; 41 | uint64_t physical_address; 42 | uint64_t file_size; 43 | uint64_t memory_size; 44 | uint64_t align; 45 | }; 46 | 47 | struct elf_sheader_64 { 48 | uint32_t name_off; 49 | uint32_t type; 50 | uint64_t flags; 51 | uint64_t address; 52 | uint64_t offset; 53 | uint64_t size; 54 | uint32_t link; 55 | uint32_t info; 56 | uint64_t align; 57 | uint64_t entry_count; 58 | }; 59 | 60 | struct elf_symbol_64 { 61 | uint32_t name; 62 | unsigned char info; 63 | unsigned char other; 64 | uint16_t sh_index; 65 | uint64_t offset; 66 | uint64_t size; 67 | }; 68 | 69 | #endif -------------------------------------------------------------------------------- /include/plooshfinder/formats/defs/macho_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef _MACHO_DEFS_H 2 | #define _MACHO_DEFS_H 3 | #include 4 | 5 | #define LC_SEGMENT_64 0x19 6 | #define LC_BUILD_VERSION 0x32 7 | #define LC_SYMTAB 0x2 8 | #define CPU_TYPE_ARM64 0xc000001 9 | #define LC_FILESET_ENTRY 0x80000035 10 | 11 | struct mach_header_64 { 12 | uint32_t magic; 13 | uint32_t cputype; 14 | uint32_t cpusubtype; 15 | uint32_t filetype; 16 | uint32_t ncmds; 17 | uint32_t sizeofcmds; 18 | uint32_t flags; 19 | uint32_t reserved; 20 | }; 21 | 22 | struct fat_header { 23 | uint32_t magic; 24 | uint32_t nfat_arch; 25 | }; 26 | 27 | struct fat_arch { 28 | uint32_t cputype; 29 | uint32_t cpusubtype; 30 | uint32_t offset; 31 | uint32_t size; 32 | uint32_t align; 33 | }; 34 | 35 | struct section_64 { 36 | char sectname[16]; 37 | char segname[16]; 38 | 39 | uint64_t addr; 40 | uint64_t size; 41 | uint32_t offset; 42 | uint32_t align; 43 | uint32_t reloff; 44 | uint32_t nreloc; 45 | uint32_t flags; 46 | uint32_t reserved1; 47 | uint32_t reserved2; 48 | uint32_t reserved3; 49 | }; 50 | 51 | struct segment_command_64 { 52 | uint32_t cmd; 53 | uint32_t cmdsize; 54 | 55 | char segname[16]; 56 | uint64_t vmaddr; 57 | uint64_t vmsize; 58 | uint64_t fileoff; 59 | uint64_t filesize; 60 | uint32_t maxprot; 61 | uint32_t initprot; 62 | uint32_t nsects; 63 | uint32_t flags; 64 | }; 65 | 66 | struct load_command_64 { 67 | uint32_t cmd; 68 | uint32_t cmdsize; 69 | }; 70 | 71 | struct build_version_command { 72 | uint32_t cmd; 73 | uint32_t cmdsize; 74 | 75 | uint32_t platform; 76 | uint32_t minos; 77 | uint32_t sdk; 78 | uint32_t ntools; 79 | }; 80 | 81 | struct symtab_command { 82 | uint32_t cmd; 83 | uint32_t cmdsize; 84 | uint32_t symoff; 85 | uint32_t nsyms; 86 | uint32_t stroff; 87 | uint32_t strsize; 88 | }; 89 | 90 | struct nlist_64 { 91 | union { 92 | uint32_t str_index; 93 | } un; 94 | uint8_t type; 95 | uint8_t nsect; 96 | uint16_t desc; 97 | uint64_t offset; 98 | }; 99 | 100 | #if 0 101 | struct kmod_info { 102 | struct kmod_info *next; 103 | int32_t info_version; 104 | uint32_t id; 105 | char name[64]; 106 | char version[64]; 107 | int32_t reference_count; 108 | struct kmod_reference *reference_list; 109 | uint64_t address; 110 | uint64_t size; 111 | uint64_t hdr_size; 112 | void *start; 113 | void *stop; 114 | }; 115 | 116 | struct kmod_reference { 117 | struct kmod_reference *next; 118 | struct kmod_info *info; 119 | }; 120 | #endif 121 | 122 | struct fileset_entry_command { 123 | uint32_t cmd; 124 | uint32_t cmdsize; 125 | uint64_t vmaddr; 126 | uint64_t fileoff; 127 | uint32_t entry_id; 128 | uint32_t reserved; 129 | }; 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /include/plooshfinder/formats/elf.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELF_H 2 | #define _ELF_H 3 | #include 4 | #include 5 | #include "defs/elf_defs.h" 6 | 7 | bool elf_check(void *buf); 8 | bool is_elf(void *buf); 9 | struct elf_sheader_64 *elf_get_section(void *buf, char *name); 10 | void *elf_va_to_ptr(void *buf, uint64_t addr); 11 | uint64_t elf_ptr_to_va(void *buf, void *ptr); 12 | struct elf_symbol_64 *elf_find_symbol_stype(void *buf, char *name, uint32_t type); 13 | struct elf_symbol_64 *elf_find_symbol(void *buf, char *name); 14 | 15 | #endif -------------------------------------------------------------------------------- /include/plooshfinder/formats/macho.h: -------------------------------------------------------------------------------- 1 | #ifndef _MACHO_H 2 | #define _MACHO_H 3 | #include 4 | #include 5 | #include "defs/macho_defs.h" 6 | 7 | uint32_t macho_get_magic(void *buf); 8 | bool macho_check(void *buf); 9 | void *macho_find_arch(void *buf, uint32_t arch); 10 | uint32_t macho_get_platform(void *buf); 11 | struct segment_command_64 *macho_get_segment(void *buf, char *name); 12 | struct section_64 *macho_get_section(void *buf, struct segment_command_64 *segment, char *name); 13 | struct section_64 *macho_get_last_section(struct segment_command_64 *segment); 14 | struct section_64 *macho_find_section(void *buf, char *segment_name, char *section_name); 15 | struct fileset_entry_command *macho_get_fileset(void *buf, char *name); 16 | struct segment_command_64 *macho_get_segment_for_va(void *buf, uint64_t addr); 17 | struct section_64 *macho_get_section_for_va(struct segment_command_64 *segment, uint64_t addr); 18 | struct section_64 *macho_find_section_for_va(void *buf, uint64_t addr); 19 | void *macho_va_to_ptr(void *buf, uint64_t addr); 20 | struct segment_command_64 *macho_get_segment_for_ptr(void *buf, void *ptr); 21 | struct section_64 *macho_get_section_for_ptr(struct segment_command_64 *segment, void *buf, void *ptr); 22 | struct section_64 *macho_find_section_for_ptr(void *buf, void *ptr); 23 | uint64_t macho_ptr_to_va(void *buf, void *ptr); 24 | struct nlist_64 *macho_find_symbol(void *buf, char *name); 25 | uint64_t macho_get_symbol_size(struct nlist_64 *symbol); 26 | uint64_t macho_parse_plist_integer(void *key); 27 | struct mach_header_64 *macho_parse_prelink_info(void *buf, struct section_64 *kmod_info, char *bundle_name); 28 | uint64_t macho_xnu_untag_va(uint64_t addr); 29 | struct mach_header_64 *macho_parse_kmod_info(void *buf, struct section_64 *kmod_info, struct section_64 *kmod_start, char *bundle_name); 30 | struct mach_header_64 *macho_find_kext(void *buf, char *name); 31 | void macho_run_each_kext(void *buf, void (*function)(void *real_buf, void *kextbuf, uint64_t kext_size)); 32 | void *fileset_va_to_ptr(void *buf, void *kext, uint64_t addr); 33 | struct segment_command_64 *fileset_get_segment_for_ptr(void *buf, void *kext, void *ptr); 34 | struct section_64 *fileset_find_section_for_ptr(void *buf, void *kext, void *ptr); 35 | uint64_t fileset_ptr_to_va(void *buf, void *kext, void *ptr); 36 | struct nlist_64 *fileset_find_symbol(void *buf, void *kext, char *name); 37 | 38 | #endif -------------------------------------------------------------------------------- /include/plooshfinder/formats/multi.h: -------------------------------------------------------------------------------- 1 | #ifndef _MULTI_H 2 | #define _MULTI_H 3 | #include 4 | 5 | void *pf_va_to_ptr(void *buf, uint64_t addr); 6 | uint64_t pf_ptr_to_va(void *buf, void *ptr); 7 | 8 | #endif -------------------------------------------------------------------------------- /include/plooshfinder/formats/pe.h: -------------------------------------------------------------------------------- 1 | #ifndef _PE_H 2 | #define _PE_H 3 | #include 4 | #include 5 | #include "defs/pe_defs.h" 6 | 7 | bool dos_check(void *buf); 8 | struct COFF_Header *get_pe_header(void *buf); 9 | bool pe_check(void *buf); 10 | bool is_pe(void *buf); 11 | struct PE64_Optional_Header *get_pe_opt_header(void *buf); 12 | struct Symbol_Header *pe_get_symtab(void *buf); 13 | void *pe_get_strtab(void *buf); 14 | struct Section_Header *pe_get_section(void *buf, char *name); 15 | void *pe_va_to_ptr(void *buf, uint64_t addr); 16 | uint64_t pe_ptr_to_va(void *buf, void *ptr); 17 | struct Symbol_Header *pe_find_symbol(void *buf, char *name); 18 | 19 | #endif -------------------------------------------------------------------------------- /include/plooshfinder/plooshfinder.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLOOSHFINDER_H 2 | #define _PLOOSHFINDER_H 3 | #include 4 | #include 5 | #include 6 | 7 | // util macros 8 | #define nop 0xd503201f 9 | #define ret 0xd65f03c0 10 | 11 | struct pf_patch_t { 12 | void *matches; 13 | void *masks; 14 | bool disabled; 15 | uint32_t count; 16 | bool (*callback)(struct pf_patch_t *patch, void *stream); 17 | }; 18 | 19 | struct pf_patchset_t { 20 | struct pf_patch_t *patches; 21 | uint32_t count; 22 | void (*handler)(void *buf, size_t size, struct pf_patchset_t patch); 23 | }; 24 | 25 | // patch utils 26 | struct pf_patch_t pf_construct_patch(void *matches, void *masks, uint32_t count, bool (*callback)(struct pf_patch_t *patch, void *stream)); 27 | struct pf_patchset_t pf_construct_patchset(struct pf_patch_t *patches, uint32_t count, void (*handler)(void *buf, size_t size, struct pf_patchset_t patchset)); 28 | void pf_patchset_emit(void *buf, size_t size, struct pf_patchset_t patchset); 29 | void pf_disable_patch(struct pf_patch_t *patch); 30 | 31 | // utils for finding 32 | uint32_t *pf_find_next(uint32_t *stream, uint32_t count, uint32_t match, uint32_t mask); 33 | uint32_t *pf_find_prev(uint32_t *stream, uint32_t count, uint32_t match, uint32_t mask); 34 | int64_t pf_adrp_offset(uint32_t adrp); 35 | uint32_t *pf_follow_veneer(void *buf, uint32_t *stream); 36 | uint32_t *pf_follow_branch(void *buf, uint32_t *stream); 37 | void *pf_follow_xref(void *buf, uint32_t *stream); 38 | void *pf_find_zero_buf(void *buf, size_t size, size_t shc_count); 39 | uint32_t *fileset_follow_veneer(void *buf, void *kext, uint32_t *stream); 40 | uint32_t *fileset_follow_branch(void *buf, void *kext, uint32_t *stream); 41 | void *fileset_follow_xref(void *buf, void *kext, uint32_t *stream); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/plooshfinder/plooshfinder32.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLOOSHFINDER32_H 2 | #define _PLOOSHFINDER32_H 3 | #include 4 | #include 5 | #include 6 | 7 | struct pf_patch32_t { 8 | uint32_t *matches; 9 | uint32_t *masks; 10 | bool disabled; 11 | uint32_t count; 12 | bool (*callback)(struct pf_patch32_t *patch, void *stream); 13 | }; 14 | 15 | struct pf_patchset32_t { 16 | struct pf_patch32_t *patches; 17 | uint32_t count; 18 | void (*handler)(void *buf, size_t size, struct pf_patchset32_t patch); 19 | }; 20 | 21 | // patch utils 22 | bool pf_maskmatch32(uint32_t insn, uint32_t match, uint32_t mask); 23 | void pf_find_maskmatch32(void *buf, size_t size, struct pf_patchset32_t patchset); 24 | 25 | // utils for finding 26 | int32_t pf_signextend_32(int32_t val, uint8_t bits); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/plooshfinder/plooshfinder64.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLOOSHFINDER64_H 2 | #define _PLOOSHFINDER64_H 3 | #include 4 | #include 5 | #include 6 | 7 | struct pf_patch64_t { 8 | uint64_t *matches; 9 | uint64_t *masks; 10 | bool disabled; 11 | uint32_t count; 12 | bool (*callback)(struct pf_patch64_t *patch, void *stream); 13 | }; 14 | 15 | struct pf_patchset64_t { 16 | struct pf_patch64_t *patches; 17 | uint32_t count; 18 | void (*handler)(void *buf, size_t size, struct pf_patchset64_t patch); 19 | }; 20 | 21 | // patch utils 22 | bool pf_maskmatch64(uint64_t insn, uint64_t match, uint64_t mask); 23 | void pf_find_maskmatch64(void *buf, size_t size, struct pf_patchset64_t patchset); 24 | 25 | // utils for finding 26 | int64_t pf_signextend_64(int64_t val, uint8_t bits); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/plooshfinder/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H 2 | #define _UTILS_H 3 | #include 4 | 5 | uint32_t convert_endianness32(uint32_t val); 6 | 7 | #endif -------------------------------------------------------------------------------- /include/rootfulhooks/hooks.h: -------------------------------------------------------------------------------- 1 | #ifndef ROOTFULHOOKS_HOOKS_H 2 | #define ROOTFULHOOKS_HOOKS_H 3 | 4 | void lsdInit(void); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/rootlesshooks/hooks.h: -------------------------------------------------------------------------------- 1 | #ifndef ROOTLESSHOOKS_HOOKS_H 2 | #define ROOTLESSHOOKS_HOOKS_H 3 | 4 | void cfprefsdInit(void); 5 | void sbInit(void); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/systemhook/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define HOOK_DYLIB_PATH "/cores/binpack/usr/lib/systemhook.dylib" 8 | #define LIBROOT_DYLIB_DIRECTORY_PATH "/cores/binpack/usr/lib/libroot" 9 | 10 | #define JB_ENV_COUNT 6 11 | extern char *JB_SandboxExtensions; 12 | extern char *JB_RootPath; 13 | extern char *JB_PinfoFlags; 14 | extern char *JB_TweakLoaderPath; 15 | extern bool swh_is_debugged; 16 | extern uint64_t pflags; 17 | extern bool has_libiosexec; 18 | 19 | #define JB_ROOT_PATH(path) ({ \ 20 | char *outPath = alloca(PATH_MAX); \ 21 | strlcpy(outPath, JB_RootPath, PATH_MAX); \ 22 | strlcat(outPath, path, PATH_MAX); \ 23 | (outPath); \ 24 | }) 25 | 26 | #define SHOOK_EXPORT __attribute__((visibility ("default"))) 27 | 28 | bool stringStartsWith(const char *str, const char* prefix); 29 | bool stringEndsWith(const char* str, const char* suffix); 30 | 31 | SHOOK_EXPORT int64_t jbdswInterceptUserspacePanic(const char *messageString); 32 | 33 | 34 | int resolvePath(const char *file, const char *searchPath, int (^attemptHandler)(char *path)); 35 | SHOOK_EXPORT int spawn_hook_common(pid_t *restrict pid, const char *restrict path, 36 | const posix_spawn_file_actions_t *restrict file_actions, 37 | const posix_spawnattr_t *restrict attrp, 38 | char *const argv[restrict], 39 | char *const envp[restrict], 40 | void *pspawn_org); 41 | 42 | typedef struct { 43 | uint32_t platform; 44 | uint32_t version; 45 | } DyldBuildVersion; 46 | 47 | __API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), bridgeos(3.0)) 48 | uint32_t dyld_get_active_platform(void); 49 | 50 | __API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), bridgeos(4.0)) 51 | __attribute__((visibility ("hidden"))) 52 | bool _availability_version_check_hook(uint32_t count, DyldBuildVersion versions[]); 53 | 54 | __API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0), bridgeos(4.0)) 55 | bool _availability_version_check(uint32_t count, DyldBuildVersion versions[]); 56 | 57 | #define CONSTRUCT_V(major, minor, subminor) ((major & 0xffff) << 16) | ((minor & 0xff) << 8) | (subminor & 0xff) 58 | -------------------------------------------------------------------------------- /include/systemhook/envbuf.h: -------------------------------------------------------------------------------- 1 | int envbuf_len(const char *envp[]); 2 | char **envbuf_mutcopy(const char *envp[]); 3 | void envbuf_free(char *envp[]); 4 | int envbuf_find(const char *envp[], const char *name); 5 | const char *envbuf_getenv(const char *envp[], const char *name); 6 | void envbuf_setenv(char **envpp[], const char *name, const char *value); 7 | void envbuf_unsetenv(char **envpp[], const char *name); -------------------------------------------------------------------------------- /include/systemhook/launchd.h: -------------------------------------------------------------------------------- 1 | #define OS_ALLOC_ONCE_KEY_MAX 100 2 | 3 | struct _os_alloc_once_s { 4 | long once; 5 | void *ptr; 6 | }; 7 | 8 | struct xpc_global_data { 9 | uint64_t a; 10 | uint64_t xpc_flags; 11 | mach_port_t task_bootstrap_port; /* 0x10 */ 12 | #ifndef _64 13 | uint32_t padding; 14 | #endif 15 | xpc_object_t xpc_bootstrap_pipe; /* 0x18 */ 16 | // and there's more, but you'll have to wait for MOXiI 2 for those... 17 | // ... 18 | }; 19 | 20 | extern struct _os_alloc_once_s _os_alloc_once_table[]; 21 | extern void* _os_alloc_once(struct _os_alloc_once_s *slot, size_t sz, os_function_t init); 22 | -------------------------------------------------------------------------------- /include/systemhook/libiosexec.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSTEMHOOK_LIBIOSEXEC_H 2 | #define SYSTEMHOOK_LIBIOSEXEC_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef HAVE_SYSTEMWIDE_IOSEXEC 9 | 10 | #define THREE_WAY_CALL(func, ...) ( ie_ ## func && !has_libiosexec ) ? ie_ ## func( __VA_ARGS__ ) : (orig_ ## func ? orig_ ## func( __VA_ARGS__ ) : func( __VA_ARGS__ )) 11 | #define RET_TWC(...) return THREE_WAY_CALL( __VA_ARGS__ ) 12 | #define DECLARE_THREE(retval, func, ...) retval (*ie_ ## func)( __VA_ARGS__ ); retval (*orig_ ## func)( __VA_ARGS__ ); retval (func ## _hook)( __VA_ARGS__ ); 13 | 14 | int get_libiosexec(void); 15 | extern void* libiosexec_handle; 16 | extern bool has_libiosexec; 17 | 18 | DECLARE_THREE(char*, getusershell, void); 19 | DECLARE_THREE(void, setusershell, void); 20 | DECLARE_THREE(void, endusershell, void); 21 | 22 | DECLARE_THREE(struct passwd *, getpwent, void); 23 | DECLARE_THREE(struct passwd*, getpwnam, const char*); 24 | DECLARE_THREE(int, getpwnam_r, const char *name, struct passwd *pw, char *buf, size_t buflen, struct passwd **pwretp); 25 | DECLARE_THREE(struct passwd*, getpwuid, uid_t uid); 26 | DECLARE_THREE(int, getpwuid_r, uid_t uid, struct passwd *pw, char *buf, size_t buflen, struct passwd **pwretp); 27 | DECLARE_THREE(int, setpassent, int stayopen); 28 | DECLARE_THREE(void, setpwent, void); 29 | DECLARE_THREE(void, endpwent, void); 30 | DECLARE_THREE(char*, user_from_uid, uid_t, int); 31 | 32 | DECLARE_THREE(struct group*, getgrgid, gid_t gid); 33 | DECLARE_THREE(int, getgrgid_r, gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct group **result); 34 | DECLARE_THREE(struct group*, getgrnam, const char* name); 35 | DECLARE_THREE(int, getgrnam_r, const char *name, struct group *grp, char *buffer, size_t bufsize, struct group **result); 36 | DECLARE_THREE(struct group*, getgrent, void); 37 | DECLARE_THREE(void, setgrent, void); 38 | DECLARE_THREE(void, endgrent, void); 39 | DECLARE_THREE(char*, group_from_gid, gid_t, int); 40 | 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /include/universalhooks/hooks.h: -------------------------------------------------------------------------------- 1 | #ifndef UNIVERSALHOOKS_HOOKS_H 2 | #define UNIVERSALHOOKS_HOOKS_H 3 | 4 | #include 5 | #include 6 | 7 | extern uint64_t pflags; 8 | extern bool rootful; 9 | 10 | void lsdRootlessInit(void); 11 | void securitydInit(void); 12 | void watchdogdInit(void); 13 | void springboardInit(void); 14 | void cfprefsdInit(void); 15 | void pineboardInit(void); 16 | void lsdUniversalInit(void); 17 | void headboardInit(void); 18 | void trollstorehelperInit(char* executablePath); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /plooshInit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /plooshInit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /plooshInit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /shared/boot.jp2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palera1n/jbinit/c1015df65dad3704ace43feb6ebc310542c60422/shared/boot.jp2 -------------------------------------------------------------------------------- /shared/copyright/License-Dopamine.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Lars Fröder (opa334) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /shared/copyright/License-curl.txt: -------------------------------------------------------------------------------- 1 | COPYRIGHT AND PERMISSION NOTICE 2 | 3 | Copyright (c) 1996 - 2023, Daniel Stenberg, , and many 4 | contributors, see the THANKS file. 5 | 6 | All rights reserved. 7 | 8 | Permission to use, copy, modify, and distribute this software for any purpose 9 | with or without fee is hereby granted, provided that the above copyright 10 | notice and this permission notice appear in all copies. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN 15 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 17 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 18 | OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | Except as contained in this notice, the name of a copyright holder shall not 21 | be used in advertising or otherwise to promote the sale, use or other dealings 22 | in this Software without prior written authorization of the copyright holder. 23 | -------------------------------------------------------------------------------- /shared/copyright/License-dobby.txt: -------------------------------------------------------------------------------- 1 | Apache-2.0.txt -------------------------------------------------------------------------------- /shared/copyright/License-ellekit.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Évelyne Bélanger All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither ElleKit nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /shared/copyright/License-ellekit2.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Charlotte Belanger All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither ElleKit nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /shared/copyright/License-ellekit3.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Charlotte Belanger All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | 2. 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the 14 | distribution. 15 | 16 | 3. All advertising materials mentioning features or 17 | use of this software must display the following acknowledgement: 18 | This product includes software developed by the organization. 19 | 20 | 4. Neither the name of the copyright holder nor the names the 21 | copyright holder nor the names of its contributors may be used to 22 | endorse or promote products derived from this software without 23 | specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS 26 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY 29 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 33 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 34 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 | POSSIBILITY OF SUCH DAMAGE. 36 | -------------------------------------------------------------------------------- /shared/copyright/License-launchctl.txt: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2022-2023 Procursus Team 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /shared/copyright/License-ldid.txt: -------------------------------------------------------------------------------- 1 | agpl-3.0.txt -------------------------------------------------------------------------------- /shared/copyright/License-less.txt: -------------------------------------------------------------------------------- 1 | gpl-3.0.txt -------------------------------------------------------------------------------- /shared/copyright/License-mksh.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2 | 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 3 | 2019, 2020 4 | mirabilos 5 | 6 | Provided that these terms and disclaimer and all copyright notices 7 | are retained or reproduced in an accompanying document, permission 8 | is granted to deal in this work without restriction, including un- 9 | limited rights to use, publicly perform, distribute, sell, modify, 10 | merge, give away, or sublicence. 11 | 12 | This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 13 | the utmost extent permitted by applicable law, neither express nor 14 | implied; without malicious intent or gross negligence. In no event 15 | may a licensor, author or contributor be held liable for indirect, 16 | direct, other damage, loss, or other issues arising in any way out 17 | of dealing in the work, even if advised of the possibility of such 18 | damage or existence of a defect, except proven that it results out 19 | of said person's immediate fault when using the work as intended. 20 | -------------------------------------------------------------------------------- /shared/copyright/License-ncurses.txt: -------------------------------------------------------------------------------- 1 | Copyright 2018-2022,2023 Thomas E. Dickey 2 | Copyright 1998-2017,2018 Free Software Foundation, Inc. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, distribute with modifications, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 19 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | Except as contained in this notice, the name(s) of the above copyright 24 | holders shall not be used in advertising or otherwise to promote the 25 | sale, use or other dealings in this Software without prior written 26 | authorization. 27 | 28 | -- vile:txtmode fc=72 29 | -- $Id: COPYING,v 1.12 2023/01/07 17:55:53 tom Exp $ 30 | -------------------------------------------------------------------------------- /shared/copyright/License-snaputil.txt: -------------------------------------------------------------------------------- 1 | Apache-2.0.txt -------------------------------------------------------------------------------- /shared/copyright/License-trustcache.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Cameron Katri. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY CAMERON KATRI AND CONTRIBUTORS ``AS IS'' AND 13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 | ARE DISCLAIMED. IN NO EVENT SHALL CAMERON KATRI OR CONTRIBUTORS BE LIABLE 16 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 18 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 19 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 20 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 21 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 22 | SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /shared/copyright/License-zstd.txt: -------------------------------------------------------------------------------- 1 | gpl-2.0.txt -------------------------------------------------------------------------------- /shared/debug-shell.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palera1n/jbinit/c1015df65dad3704ace43feb6ebc310542c60422/shared/debug-shell.plist -------------------------------------------------------------------------------- /shared/dropbear-2.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palera1n/jbinit/c1015df65dad3704ace43feb6ebc310542c60422/shared/dropbear-2.plist -------------------------------------------------------------------------------- /shared/dropbear-3.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palera1n/jbinit/c1015df65dad3704ace43feb6ebc310542c60422/shared/dropbear-3.plist -------------------------------------------------------------------------------- /shared/dropbear-5.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palera1n/jbinit/c1015df65dad3704ace43feb6ebc310542c60422/shared/dropbear-5.plist -------------------------------------------------------------------------------- /shared/palera1nd.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palera1n/jbinit/c1015df65dad3704ace43feb6ebc310542c60422/shared/palera1nd.plist -------------------------------------------------------------------------------- /shared/payload.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palera1n/jbinit/c1015df65dad3704ace43feb6ebc310542c60422/shared/payload.plist -------------------------------------------------------------------------------- /shared/telnetd.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palera1n/jbinit/c1015df65dad3704ace43feb6ebc310542c60422/shared/telnetd.plist -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | ramdisk 2 | ramdisk.dmg 3 | binpack.tar 4 | binpack 5 | palera1nLoader 6 | loader.dmg 7 | palera1nLoader.ipa 8 | -------------------------------------------------------------------------------- /src/bridgehook/.gitignore: -------------------------------------------------------------------------------- 1 | bridgehook.* 2 | -------------------------------------------------------------------------------- /src/bridgehook/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -mappletvos-version-min=12.0 -std=gnu17 -fvisibility=hidden 2 | LDFLAGS += -Wl,-dead_strip -Wno-unused-command-line-argument 3 | CXXFLAGS = -mappletvos-version-min=12.0 -fvisibility=hidden 4 | CXXFLAGS += -Wl,-dead_strip -Wno-unused-command-line-argument 5 | OBJDIR = obj 6 | C_SRC = $(wildcard *.c) 7 | OBJC_SRC = $(wildcard *.m) 8 | LIBS += -framework Foundation -lobjc ./dobby/build/libdobby.a -lc++ -shared 9 | OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.c.o)) $(patsubst %,$(OBJDIR)/%,$(OBJC_SRC:.m=.m.o)) 10 | 11 | ifeq ($(ASAN),1) 12 | CFLAGS += -fsanitize=address,undefined 13 | LDFLAGS += -rpath /cores 14 | endif 15 | 16 | all: bridgehook.dylib 17 | 18 | $(OBJDIR): 19 | @mkdir -p $(OBJDIR) 20 | 21 | $(OBJDIR)/%.c.o: %.c $(OBJDIR) 22 | $(CC) $(CFLAGS) -c -o $@ $< 23 | 24 | $(OBJDIR)/%.m.o: %.m $(OBJDIR) 25 | $(CC) $(CFLAGS) -c -o $@ $< 26 | 27 | dobby/build/libdobby.a: 28 | mkdir -p "dobby/build" 29 | cd "dobby/build" && cmake \ 30 | -DCMAKE_BUILD_TYPE=Release \ 31 | -DCMAKE_C_COMPILER="$(CC)" \ 32 | -DCMAKE_CXX_COMPILER="$(CXX)" \ 33 | -DCMAKE_C_FLAGS="$(CFLAGS)" \ 34 | -DCMAKE_CXX_FLAGS="$(CXXFLAGS)" \ 35 | -DCMAKE_CROSSCOMPILING=true \ 36 | -DCMAKE_EXE_LINKER_FLAGS="-mappletvos-version-min=12.0" \ 37 | -DCMAKE_SYSTEM_NAME=Darwin \ 38 | -DCMAKE_OSX_DEPLOYMENT_TARGET=12.0 \ 39 | -DCMAKE_SYSTEM_PROCESSOR=arm64 \ 40 | -DDOBBY_BUILD_SILICON=ON \ 41 | -DCMAKE_OSX_SYSROOT="$(TARGET_SYSROOT)" \ 42 | -DCMAKE_OSX_ARCHITECTURES="arm64" \ 43 | "$(ROOT)/src/bridgehook/dobby" 44 | $(MAKE) -C "dobby/build" dobby_static 45 | 46 | bridgehook.dylib: $(OBJS) dobby/build/libdobby.a 47 | $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJS) -o $@ 48 | $(DSYMUTIL) $@ 49 | ifneq ($(DEV_BUILD),1) 50 | $(STRIP) -x $@ 51 | endif 52 | $(LDID) -S $@ 53 | 54 | clean: 55 | rm -rf bridgehook.dylib* bridgehook.dylib.dSYM obj dobby/build 56 | 57 | .PHONY: all clean 58 | -------------------------------------------------------------------------------- /src/ellekit/.gitignore: -------------------------------------------------------------------------------- 1 | ellekit_build 2 | -------------------------------------------------------------------------------- /src/ellekit/Makefile: -------------------------------------------------------------------------------- 1 | ELLEKIT = ellekit_build/Build/Products/Release-iphoneos/libellekit.dylib 2 | ELLEKIT_PLATFORM = iphoneos 3 | 4 | all: $(ELLEKIT) 5 | 6 | $(ELLEKIT): ../../.git/modules/src/rootlesshooks/ellekit/refs/heads/main 7 | ifeq ($(MAC),1) 8 | cd ellekit; \ 9 | CC="" CXX="" LD="" xcodebuild build -arch arm64 -sdk $(ELLEKIT_PLATFORM) -scheme ellekit -configuration Release -derivedDataPath ../ellekit_build \ 10 | APPLETVOS_DEPLOYMENT_TARGET=14.0 \ 11 | CODE_SIGNING_ALLOWED=NO \ 12 | LD_DYLIB_INSTALL_NAME="@rpath/CydiaSubstrate.framework/CydiaSubstrate" 13 | ifneq ($(DEV_BUILD),1) 14 | $(STRIP) -x $(ELLEKIT) 15 | endif 16 | $(LDID) -S $(ELLEKIT); 17 | else 18 | @echo "ElleKit cannot be built on this machine" 19 | mkdir -p ellekit_build/Build/Products/Release-$(ELLEKIT_PLATFORM) 20 | cp libellekit.dylib $(ELLEKIT) 21 | endif 22 | clean: 23 | @echo "distclean to clean ellekit" 24 | 25 | distclean: 26 | rm -rf ellekit_build obj 27 | 28 | .PHONY: all clean distclean 29 | -------------------------------------------------------------------------------- /src/fakedyld/.gitignore: -------------------------------------------------------------------------------- 1 | dyld 2 | -------------------------------------------------------------------------------- /src/fakedyld/Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS = asm lib main patch_dyld 2 | CFLAGS += -nostdlib -nostdlibinc -fno-stack-protector -fomit-frame-pointer -fvisibility=hidden 3 | CFLAGS += --target=arm64-apple-tvos12.0 -std=gnu17 -ffreestanding -U__nonnull 4 | LDFLAGS += -e __dyld_start -Wl,-dylinker -Wl,-dylinker_install_name,/usr/lib/dyld 5 | LDFLAGS += -static -Wl,-fatal_warnings -Wl,-dead_strip -Wl,-Z -Wno-unused-command-line-argument 6 | 7 | export CFLAGS LDFLAGS 8 | 9 | all: $(patsubst %, %-all, $(SUBDIRS)) dyld 10 | 11 | clean: $(patsubst %, %-clean, $(SUBDIRS)) 12 | rm -rf dyld dyld.dSYM 13 | 14 | dyld: $(patsubst %, %-all, $(SUBDIRS)) 15 | $(CC) $(CFLAGS) $(LDFLAGS) $$(find . -name '*.o' | grep 'obj/.*o') -o dyld 16 | $(DSYMUTIL) $@ 17 | ifneq ($(DEV_BUILD),1) 18 | $(STRIP) $@ 19 | endif 20 | $(LDID) -Icom.apple.dyld -S $@ 21 | 22 | $(patsubst %, %-all, $(SUBDIRS)): 23 | $(MAKE) -C $(shell echo $@ | cut -d- -f1) 24 | 25 | $(patsubst %, %-clean, $(SUBDIRS)): 26 | $(MAKE) -C $(shell echo $@ | cut -d- -f1) clean 27 | 28 | .PHONY: all $(patsubst %, %-all, $(SUBDIRS)) $(patsubst %, %-clean, $(SUBDIRS)) 29 | -------------------------------------------------------------------------------- /src/fakedyld/asm/Makefile: -------------------------------------------------------------------------------- 1 | OBJDIR = obj 2 | SRC = $(wildcard *.S) 3 | OBJS = $(patsubst %,$(OBJDIR)/%,$(SRC:.S=.o)) 4 | 5 | all: $(OBJS) 6 | 7 | $(OBJDIR): 8 | @mkdir -p $(OBJDIR) 9 | 10 | $(OBJDIR)/%.o: %.S $(OBJDIR) 11 | $(CC) $(CFLAGS) -c -o $@ $< 12 | 13 | clean: 14 | rm -rf obj 15 | 16 | .PHONY: all clean 17 | -------------------------------------------------------------------------------- /src/fakedyld/asm/start.S: -------------------------------------------------------------------------------- 1 | .globl __dyld_start 2 | .align 4 3 | 4 | __dyld_start: 5 | mov x0, sp 6 | movn x8, #0xf 7 | mov x7, sp 8 | and x7, x7, x8 9 | mov sp, x7 10 | bl start 11 | movz x16, #0x1 12 | svc 0x80 13 | 14 | .globl dyld_stub_binder 15 | dyld_stub_binder: 16 | -------------------------------------------------------------------------------- /src/fakedyld/asm/syscall.S: -------------------------------------------------------------------------------- 1 | .globl _msyscall 2 | .globl _thread_switch 3 | .globl ___error 4 | .align 4 5 | 6 | #include 7 | 8 | _msyscall: 9 | mov x16, x0 10 | ldp x0, x1, [sp] 11 | ldp x2, x3, [sp, 0x10] 12 | ldp x4, x5, [sp, 0x20] 13 | ldp x6, x7, [sp, 0x30] 14 | svc 0x80 15 | b.cs Lbotch 16 | ret 17 | 18 | _fork: 19 | mov x16, #SYS_fork 20 | svc 0x80 21 | b.cs Lbotch 22 | cbz x1, Lparent 23 | // child 24 | mov w0, #0 25 | ret 26 | 27 | Lbotch: 28 | stp x0, lr, [sp, #-0x10]! 29 | bl ___error 30 | ldp x8, lr, [sp], #0x10 31 | str x8, [x0] 32 | mov x0, #-1 33 | ret 34 | 35 | Lparent: 36 | ret 37 | 38 | _thread_switch: 39 | movn x16, #0x3c 40 | svc 0x80 41 | ret 42 | -------------------------------------------------------------------------------- /src/fakedyld/lib/Makefile: -------------------------------------------------------------------------------- 1 | OBJDIR = obj 2 | SRC = $(wildcard *.c) 3 | OBJS = $(patsubst %,$(OBJDIR)/%,$(SRC:.c=.o)) 4 | 5 | all: $(OBJS) 6 | 7 | $(OBJDIR): 8 | @mkdir -p $(OBJDIR) 9 | 10 | $(OBJDIR)/%.o: %.c $(OBJDIR) 11 | $(CC) $(CFLAGS) -c -o $@ $< 12 | 13 | clean: 14 | rm -rf obj 15 | 16 | .PHONY: all clean 17 | -------------------------------------------------------------------------------- /src/fakedyld/lib/atoi.c: -------------------------------------------------------------------------------- 1 | /* This file is part of Embedded Artistry libc */ 2 | 3 | #include 4 | 5 | int atoi(const char* str) { 6 | bool neg = false; 7 | int val = 0; 8 | 9 | switch(*str) 10 | { 11 | case '-': 12 | neg = true; 13 | /* intentional fallthrough to advance str */ 14 | case '+': 15 | str++; 16 | default: 17 | break; // proceed without action 18 | } 19 | 20 | while(isdigit(*str)) 21 | { 22 | val = (10 * val) + (*str++ - '0'); 23 | } 24 | 25 | return (neg ? -val : val); 26 | } 27 | -------------------------------------------------------------------------------- /src/fakedyld/lib/bzero.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void bzero (void *s, size_t n) { 4 | for (size_t i = 0; i < n; i++) { 5 | *((char*)s + i) = '\0'; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/fakedyld/lib/fs_snapshot.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fs_snapshot_list(int dirfd, struct attrlist *alist, void *attrbuf, size_t bufsize, uint32_t flags) { 4 | if (flags != 0) { 5 | errno = EINVAL; 6 | return -1; 7 | } 8 | 9 | return getattrlistbulk(dirfd, alist, attrbuf, bufsize, FSOPT_LIST_SNAPSHOT); 10 | } 11 | 12 | int fs_snapshot_create(int dirfd, const char *name, uint32_t flags) { 13 | return fs_snapshot(SNAPSHOT_OP_CREATE, dirfd, name, NULL, NULL, flags); 14 | } 15 | 16 | int fs_snapshot_delete(int dirfd, const char *name, uint32_t flags) { 17 | return fs_snapshot(SNAPSHOT_OP_DELETE, dirfd, name, NULL, NULL, flags); 18 | } 19 | 20 | int fs_snapshot_rename(int dirfd, const char *old, const char *new, uint32_t flags) { 21 | return fs_snapshot(SNAPSHOT_OP_RENAME, dirfd, old, new, NULL, flags); 22 | } 23 | 24 | int fs_snapshot_revert(int dirfd, const char *name, uint32_t flags) { 25 | return fs_snapshot(SNAPSHOT_OP_REVERT, dirfd, name, NULL, NULL, flags); 26 | } 27 | 28 | int fs_snapshot_root(int dirfd, const char *name, uint32_t flags) { 29 | return fs_snapshot(SNAPSHOT_OP_ROOT, dirfd, name, NULL, NULL, flags); 30 | } 31 | 32 | int fs_snapshot_mount(int dirfd, const char *dir, const char *snapshot, uint32_t flags) { 33 | return fs_snapshot(SNAPSHOT_OP_MOUNT, dirfd, snapshot, dir, NULL, flags); 34 | } 35 | -------------------------------------------------------------------------------- /src/fakedyld/lib/isalpha.c: -------------------------------------------------------------------------------- 1 | int isalpha(int c) { 2 | return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ? 1 : 0); 3 | } 4 | -------------------------------------------------------------------------------- /src/fakedyld/lib/isdigit.c: -------------------------------------------------------------------------------- 1 | int isdigit(int c) { 2 | return (c >= '0' && c <= '9' ? 1 : 0); 3 | } 4 | -------------------------------------------------------------------------------- /src/fakedyld/lib/isspace.c: -------------------------------------------------------------------------------- 1 | int isspace(int c) { 2 | return (c == '\t' || c == '\n' || 3 | c == '\v' || c == '\f' || c == '\r' || c == ' ' ? 1 : 0); 4 | } 5 | -------------------------------------------------------------------------------- /src/fakedyld/lib/isupper.c: -------------------------------------------------------------------------------- 1 | int isupper(int c) { 2 | return (c >= 'A' && c >= 'Z'); 3 | } 4 | -------------------------------------------------------------------------------- /src/fakedyld/lib/memcpy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void *memcpy(void *dst, const void *src, size_t n) 4 | { 5 | const char *s = src; 6 | char *d = dst; 7 | int pos = 0, dir = 1; 8 | 9 | if (d > s) { 10 | dir = -1; 11 | pos = n - 1; 12 | } 13 | 14 | while (n--) { 15 | d[pos] = s[pos]; 16 | pos += dir; 17 | } 18 | 19 | return dst; 20 | } 21 | 22 | void *memmove(void *dest, const void *src, size_t n) 23 | { 24 | return memcpy(dest, src, n); 25 | } 26 | -------------------------------------------------------------------------------- /src/fakedyld/lib/memmem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define UCHAR_MAX 255 3 | 4 | unsigned char * 5 | boyermoore_horspool_memmem(const unsigned char* haystack, size_t hlen, 6 | const unsigned char* needle, size_t nlen) 7 | { 8 | size_t last, scan = 0; 9 | size_t bad_char_skip[UCHAR_MAX + 1]; /* Officially called: 10 | * bad character shift */ 11 | 12 | /* Sanity checks on the parameters */ 13 | if (nlen <= 0 || !haystack || !needle) 14 | return NULL; 15 | 16 | /* ---- Preprocess ---- */ 17 | /* Initialize the table to default value */ 18 | /* When a character is encountered that does not occur 19 | * in the needle, we can safely skip ahead for the whole 20 | * length of the needle. 21 | */ 22 | for (scan = 0; scan <= UCHAR_MAX; scan = scan + 1) 23 | bad_char_skip[scan] = nlen; 24 | 25 | /* C arrays have the first byte at [0], therefore: 26 | * [nlen - 1] is the last byte of the array. */ 27 | last = nlen - 1; 28 | 29 | /* Then populate it with the analysis of the needle */ 30 | for (scan = 0; scan < last; scan = scan + 1) 31 | bad_char_skip[needle[scan]] = last - scan; 32 | 33 | /* ---- Do the matching ---- */ 34 | 35 | /* Search the haystack, while the needle can still be within it. */ 36 | while (hlen >= nlen) 37 | { 38 | /* scan from the end of the needle */ 39 | for (scan = last; haystack[scan] == needle[scan]; scan = scan - 1) 40 | if (scan == 0) /* If the first byte matches, we've found it. */ 41 | return (void *)haystack; 42 | 43 | /* otherwise, we need to skip some bytes and start again. 44 | Note that here we are getting the skip value based on the last byte 45 | of needle, no matter where we didn't match. So if needle is: "abcd" 46 | then we are skipping based on 'd' and that value will be 4, and 47 | for "abcdd" we again skip on 'd' but the value will be only 1. 48 | The alternative of pretending that the mismatched character was 49 | the last character is slower in the normal case (E.g. finding 50 | "abcd" in "...azcd..." gives 4 by using 'd' but only 51 | 4-2==2 using 'z'. */ 52 | hlen -= bad_char_skip[haystack[last]]; 53 | haystack += bad_char_skip[haystack[last]]; 54 | } 55 | 56 | return NULL; 57 | } 58 | 59 | void * 60 | memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen) 61 | { 62 | size_t i, j; 63 | if (!nlen) { 64 | return (void *)haystack; 65 | } 66 | if (nlen > hlen) { 67 | return NULL; 68 | } 69 | if (nlen >= 4 && hlen >= 256) { 70 | return boyermoore_horspool_memmem(haystack, hlen, needle, nlen); 71 | } 72 | for (j = 0, i = 0; i < hlen; i++) { 73 | if (((unsigned char *)haystack)[i] == ((unsigned char *)needle)[j]) { 74 | j++; 75 | if (j == nlen) { 76 | return (char *)haystack + i - nlen + 1; 77 | } 78 | } else { 79 | i -= j; 80 | j = 0; 81 | } 82 | } 83 | return NULL; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/fakedyld/lib/memset.c: -------------------------------------------------------------------------------- 1 | /* This file is part of Embedded Artistry libc */ 2 | 3 | #include 4 | #include 5 | 6 | void* memset(void* dest, int c, size_t n) 7 | { 8 | unsigned char* s = dest; 9 | size_t k; 10 | 11 | /* Fill head and tail with minimal branching. Each 12 | * conditional ensures that all the subsequently used 13 | * offsets are well-defined and in the dest region. */ 14 | 15 | if(!n) 16 | { 17 | return dest; 18 | } 19 | 20 | s[0] = s[n - 1] = (unsigned char)c; 21 | 22 | if(n <= 2) 23 | { 24 | return dest; 25 | } 26 | 27 | s[1] = s[n - 2] = (unsigned char)c; 28 | s[2] = s[n - 3] = (unsigned char)c; 29 | 30 | if(n <= 6) 31 | { 32 | return dest; 33 | } 34 | 35 | s[3] = s[n - 4] = (unsigned char)c; 36 | 37 | if(n <= 8) 38 | { 39 | return dest; 40 | } 41 | 42 | /* Advance pointer to align it at a 4-byte boundary, 43 | * and truncate n to a multiple of 4. The previous code 44 | * already took care of any head/tail that get cut off 45 | * by the alignment. */ 46 | 47 | k = -(uintptr_t)s & 3; 48 | s += k; 49 | n -= k; 50 | n &= (unsigned long)-4; 51 | n /= 4; 52 | 53 | // Cast to void first to prevent alignment warning 54 | uint32_t* ws = (uint32_t*)(void*)s; 55 | uint32_t wc = c & 0xFF; 56 | wc |= ((wc << 8) | (wc << 16) | (wc << 24)); 57 | 58 | /* Pure C fallback with no aliasing violations. */ 59 | for(; n; n--, ws++) 60 | { 61 | *ws = wc; 62 | } 63 | 64 | return dest; 65 | } 66 | -------------------------------------------------------------------------------- /src/fakedyld/lib/putchar.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static int gfd_console; 4 | 5 | void _putchar(char character) { 6 | static size_t counter = 0; 7 | static char printbuf[0x100]; 8 | printbuf[counter++] = character; 9 | if (character == '\n' || counter == sizeof(printbuf)) { 10 | write(gfd_console, printbuf, counter); 11 | counter = 0; 12 | } 13 | } 14 | 15 | void set_fd_console(int fd_console) { 16 | gfd_console = fd_console; 17 | } 18 | -------------------------------------------------------------------------------- /src/fakedyld/lib/strchr.c: -------------------------------------------------------------------------------- 1 | /* This file is part of Embedded Artistry libc */ 2 | 3 | #include 4 | 5 | char *strchr(const char *p, int ch) { 6 | char c; 7 | 8 | c = ch; 9 | for (;; ++p) { 10 | if (*p == c) 11 | return ((char *)p); 12 | if (*p == '\0') 13 | return (NULL); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/fakedyld/lib/strcmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * PJ: my own strcmp implementation 5 | * 6 | * strcmp with short-circuit support: very common when you have const strings 7 | * combined by the compiler. 8 | * Otherwise we compare the strings as normal. 9 | * We bail out when s1 ends (null-term) 10 | */ 11 | 12 | int strcmp(const char* s1, const char* s2) 13 | { 14 | int r = -1; 15 | 16 | if(s1 == s2) 17 | { 18 | // short circuit - same string 19 | return 0; 20 | } 21 | 22 | // I don't want to panic with a NULL ptr - we'll fall through and fail w/ -1 23 | if(s1 != NULL && s2 != NULL) 24 | { 25 | // iterate through strings until they don't match or s1 ends (null-term) 26 | for(; *s1 == *s2; ++s1, ++s2) 27 | { 28 | if(*s1 == 0) 29 | { 30 | r = 0; 31 | break; 32 | } 33 | } 34 | 35 | // handle case where we didn't break early - set return code. 36 | if(r != 0) 37 | { 38 | r = *(const char*)s1 - *(const char*)s2; 39 | } 40 | } 41 | 42 | return r; 43 | } 44 | -------------------------------------------------------------------------------- /src/fakedyld/lib/strlen.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | size_t strlen(const char* str) { 4 | size_t len = 0; 5 | while (*str++) { 6 | len++; 7 | } 8 | 9 | return len; 10 | } 11 | -------------------------------------------------------------------------------- /src/fakedyld/lib/strncmp.c: -------------------------------------------------------------------------------- 1 | /* This file is part of Embedded Artistry libc */ 2 | 3 | #include 4 | 5 | /* 6 | * PJ: my own strncmp implementation 7 | * 8 | * strncmp with short-circuit support: very common when you have const strings 9 | * combined by the compiler. 10 | * Otherwise we compare the strings as normal 11 | * We bail out when s1 ends (null-term) or n bytes have been analyzed 12 | */ 13 | 14 | int strncmp(const char* s1, const char* s2, size_t n) 15 | { 16 | int r = -1; 17 | 18 | if(s1 == s2) 19 | { 20 | // short circuit - same string 21 | return 0; 22 | } 23 | 24 | // I don't want to panic with a NULL ptr - we'll fall through and fail 25 | if(s1 != NULL && s2 != NULL) 26 | { 27 | // iterate through strings until they don't match, s1 ends, or n == 0 28 | for(; n && *s1 == *s2; ++s1, ++s2, n--) 29 | { 30 | if(*s1 == 0) 31 | { 32 | r = 0; 33 | break; 34 | } 35 | } 36 | 37 | // handle case where we didn't break early - set return code. 38 | if(n == 0) 39 | { 40 | r = 0; 41 | } 42 | else if(r != 0) 43 | { 44 | r = *s1 - *s2; 45 | } 46 | } 47 | 48 | return r; 49 | } 50 | -------------------------------------------------------------------------------- /src/fakedyld/lib/stroul.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1990 Regents of the University of California. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. [rescinded 22 July 1999] 14 | * 4. Neither the name of the University nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 | * SUCH DAMAGE. 29 | */ 30 | 31 | #include 32 | #include 33 | 34 | /* 35 | * Convert a string to an unsigned long integer. 36 | * 37 | * Ignores `locale' stuff. Assumes that the upper and lower case 38 | * alphabets and digits are each contiguous. 39 | */ 40 | unsigned long 41 | strtoul(const char *nptr, char **endptr, register int base) 42 | { 43 | register const char *s = nptr; 44 | register unsigned long acc; 45 | register int c; 46 | register unsigned long cutoff; 47 | register int neg = 0, any, cutlim; 48 | 49 | /* 50 | * See strtol for comments as to the logic used. 51 | */ 52 | do { 53 | c = *s++; 54 | } while (isspace(c)); 55 | if (c == '-') { 56 | neg = 1; 57 | c = *s++; 58 | } else if (c == '+') 59 | c = *s++; 60 | if ((base == 0 || base == 16) && 61 | c == '0' && (*s == 'x' || *s == 'X')) { 62 | c = s[1]; 63 | s += 2; 64 | base = 16; 65 | } 66 | if (base == 0) 67 | base = c == '0' ? 8 : 10; 68 | cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 69 | cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 70 | for (acc = 0, any = 0;; c = *s++) { 71 | if (isdigit(c)) 72 | c -= '0'; 73 | else if (isalpha(c)) 74 | c -= isupper(c) ? 'A' - 10 : 'a' - 10; 75 | else 76 | break; 77 | if (c >= base) 78 | break; 79 | if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 80 | any = -1; 81 | else { 82 | any = 1; 83 | acc *= base; 84 | acc += c; 85 | } 86 | } 87 | if (any < 0) { 88 | acc = ULONG_MAX; 89 | //errno = ERANGE; 90 | } else if (neg) 91 | acc = -acc; 92 | if (endptr != 0) 93 | *endptr = (char *) (any ? s - 1 : nptr); 94 | return (acc); 95 | } 96 | -------------------------------------------------------------------------------- /src/fakedyld/lib/stroull.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Regents of the University of California. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. [rescinded 22 July 1999] 14 | * 4. Neither the name of the University nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 | * SUCH DAMAGE. 29 | */ 30 | 31 | #include 32 | #include 33 | 34 | /* 35 | * Convert a string to an unsigned long long integer. 36 | * 37 | * Ignores `locale' stuff. Assumes that the upper and lower case 38 | * alphabets and digits are each contiguous. 39 | */ 40 | unsigned long long strtoull(const char *nptr, char **endptr, register int base) 41 | { 42 | register const char *s = nptr; 43 | register unsigned long long acc; 44 | register int c; 45 | register unsigned long long cutoff; 46 | register int neg = 0, any, cutlim; 47 | 48 | /* 49 | * See strtol for comments as to the logic used. 50 | */ 51 | do { 52 | c = *s++; 53 | } while (isspace(c)); 54 | if (c == '-') { 55 | neg = 1; 56 | c = *s++; 57 | } else if (c == '+') 58 | c = *s++; 59 | if ((base == 0 || base == 16) && 60 | c == '0' && (*s == 'x' || *s == 'X')) { 61 | c = s[1]; 62 | s += 2; 63 | base = 16; 64 | } 65 | if (base == 0) 66 | base = c == '0' ? 8 : 10; 67 | cutoff = (unsigned long long)ULLONG_MAX / (unsigned long long)base; 68 | cutlim = (unsigned long long)ULLONG_MAX % (unsigned long long)base; 69 | for (acc = 0, any = 0;; c = *s++) { 70 | if (isdigit(c)) 71 | c -= '0'; 72 | else if (isalpha(c)) 73 | c -= isupper(c) ? 'A' - 10 : 'a' - 10; 74 | else 75 | break; 76 | if (c >= base) 77 | break; 78 | if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 79 | any = -1; 80 | else { 81 | any = 1; 82 | acc *= base; 83 | acc += c; 84 | } 85 | } 86 | if (any < 0) { 87 | acc = ULLONG_MAX; 88 | //errno = ERANGE; 89 | } else if (neg) 90 | acc = -acc; 91 | if (endptr != 0) 92 | *endptr = (char *) (any ? s - 1 : nptr); 93 | return (acc); 94 | } 95 | -------------------------------------------------------------------------------- /src/fakedyld/lib/strstr.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char *strstr(const char *string, char *substring) { 4 | register char *a, *b; 5 | 6 | /* First scan quickly through the two strings looking for a 7 | * single-character match. When it's found, then compare the 8 | * rest of the substring. 9 | */ 10 | 11 | b = substring; 12 | if (*b == 0) { 13 | return (char *)string; 14 | } 15 | for ( ; *string != 0; string += 1) { 16 | if (*string != *b) { 17 | continue; 18 | } 19 | a = (char *)string; 20 | while (1) { 21 | if (*b == 0) { 22 | return (char *)string; 23 | } 24 | if (*a++ != *b++) { 25 | break; 26 | } 27 | } 28 | b = substring; 29 | } 30 | return NULL; 31 | } 32 | -------------------------------------------------------------------------------- /src/fakedyld/main/Makefile: -------------------------------------------------------------------------------- 1 | OBJDIR = obj 2 | SRC = $(wildcard *.c) 3 | OBJS = $(patsubst %,$(OBJDIR)/%,$(SRC:.c=.o)) 4 | 5 | all: $(OBJS) 6 | 7 | $(OBJDIR): 8 | @mkdir -p $(OBJDIR) 9 | 10 | $(OBJDIR)/%.o: %.c $(OBJDIR) 11 | $(CC) $(CFLAGS) -c -o $@ $< 12 | 13 | clean: 14 | rm -rf obj 15 | 16 | .PHONY: all clean 17 | -------------------------------------------------------------------------------- /src/fakedyld/main/clean_fakefs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define TEST_MOUNT_PREFIX "/fs/fake" 5 | 6 | void clean_fakefs(char* rootdev) { 7 | char dev_rootdev[32]; 8 | snprintf(dev_rootdev,32,"/dev/%s",rootdev); 9 | struct stat64 statbuf; 10 | apfs_mount_args_t arg = { 11 | dev_rootdev, 0, 1, 0 12 | }; 13 | retry_rootfs_mount: 14 | LOG("Test-mounting rootfs %s", dev_rootdev); 15 | int err = mount("apfs", TEST_MOUNT_PREFIX, 0, &arg); 16 | if (!err) { 17 | LOG("test mount rootfs OK"); 18 | } else { 19 | LOG("test mount rootfs %s FAILED with err=%d!", dev_rootdev, errno); 20 | sleep(1); 21 | goto retry_rootfs_mount; 22 | } 23 | if ((err = stat64(TEST_MOUNT_PREFIX "/private/", &statbuf))) { 24 | LOG("stat %s FAILED with err=%d!", TEST_MOUNT_PREFIX "/private/", err); 25 | sleep(1); 26 | goto retry_rootfs_mount; 27 | } else { 28 | LOG("stat %s OK", TEST_MOUNT_PREFIX "/private/"); 29 | } 30 | if (stat64(TEST_MOUNT_PREFIX "/usr/lib/nekojb", &statbuf) == 0) { 31 | LOG("Detected nekoJB fakefs"); 32 | } 33 | int dirfd = open(TEST_MOUNT_PREFIX, O_RDONLY, 0); 34 | if (dirfd < 0) { 35 | panic("could not open test rootfs"); 36 | } 37 | bool found_orig_fs = false; 38 | struct attrlist alist = { 0 }; 39 | char abuf[2048]; 40 | alist.commonattr = ATTR_BULK_REQUIRED; 41 | int count = fs_snapshot_list(dirfd, &alist, &abuf[0], sizeof (abuf), 0); 42 | if (count < 0) { 43 | panic("could not list snapshot on test rootfs"); 44 | } else if (count == 0) { 45 | goto list_done; 46 | } else { 47 | char *p = &abuf[0]; 48 | for (int i = 0; i < count; i++) { 49 | char *field = p; 50 | uint32_t len = *(uint32_t *)field; 51 | field += sizeof (uint32_t); 52 | attribute_set_t attrs = *(attribute_set_t *)field; 53 | field += sizeof (attribute_set_t); 54 | 55 | if (attrs.commonattr & ATTR_CMN_NAME) { 56 | attrreference_t ar = *(attrreference_t *)field; 57 | char *name = field + ar.attr_dataoffset; 58 | field += sizeof (attrreference_t); 59 | if (strcmp("orig-fs", name) == 0) { 60 | found_orig_fs = true; 61 | goto list_done; 62 | } 63 | } 64 | p += len; 65 | } 66 | } 67 | list_done: 68 | if (!found_orig_fs) { 69 | panic("could not find orig-fs snapshot, this function can only be used with a new enough fakefs"); 70 | } 71 | LOG("found orig-fs"); 72 | int ret = fs_snapshot_revert(dirfd, "orig-fs", 0); 73 | if (ret != 0) { 74 | panic("could not revert orig-fs"); 75 | } 76 | LOG("reverted to orig-fs"); 77 | ret = unmount(TEST_MOUNT_PREFIX, MNT_FORCE); 78 | if (ret != 0) { 79 | panic("could not unmount test rootfs"); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/fakedyld/main/mountroot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | /* 6 | * If the current platform has SSV, palerain_option_ssv 7 | * will be set by PongoOS in pinfo->flags 8 | * 9 | * PongoOS will always put something in pinfo->rootdev. 10 | * 11 | * The user can choose between "rootful" and "rootless", 12 | * The definition of rootful (fakefs or realfs) will be 13 | * determined by PongoOS by setting the palerain_option_ssv 14 | * flag. 15 | * 16 | * If neither rootful and rootless is set, PongoOS will choose 17 | * one for the user based on whether the system has SSV. 18 | * 19 | * So, rootful or rootless must be set by the time we get here 20 | */ 21 | 22 | void mountroot(struct paleinfo* pinfo_p, struct systeminfo* sysinfo_p) { 23 | /* we trust pongoOS and mount whatever is in pinfo_p->rootdev */ 24 | /* ...unless rootful setup is requested */ 25 | int ret; 26 | char dev_rootdev[32]; 27 | char dev_realfs[32]; 28 | snprintf(dev_realfs, 32, "/dev/%s", pinfo_p->rootdev); 29 | dev_realfs[strlen(dev_realfs)-1] = '1'; 30 | 31 | if ((pinfo_p->flags & palerain_option_setup_rootful) == 0) { 32 | snprintf(dev_rootdev, 32, "/dev/%s", pinfo_p->rootdev); 33 | } else { 34 | snprintf(dev_rootdev, 32, "%s", dev_realfs); 35 | } 36 | LOG("waiting for roots..."); 37 | /* wait for realfs */ 38 | struct stat64 st; 39 | while ((ret = stat64(dev_realfs, &st))) { 40 | if (errno != ENOENT) { 41 | LOG("wait realfs error: %d", errno); 42 | } 43 | sleep(1); 44 | } 45 | /* since realfs had shown up, target fs should be here too if it exists */ 46 | if ((ret = stat64(dev_rootdev, &st))) { 47 | panic("cannot find target fs %s: %d", dev_rootdev, errno); 48 | } 49 | int rootopts = MNT_RDONLY; 50 | if (!(pinfo_p->flags & palerain_option_bind_mount)) { 51 | rootopts |= MNT_UNION; 52 | } 53 | apfs_mount_args_t rootargs = { dev_rootdev, rootopts, APFS_MOUNT_FILESYSTEM , 0, 0, { "" }, NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0 }; 54 | retry_rootfs_mount: 55 | ret = mount("apfs", "/", rootopts, &rootargs); 56 | if (ret) { 57 | LOG("mount rootfs %s failed: %d"); 58 | sleep(1); 59 | goto retry_rootfs_mount; 60 | } 61 | if ((ret = stat64("/private/", &st))) { 62 | LOG("stat %s FAILED with err=%d!", "/private/", errno); 63 | sleep(1); 64 | goto retry_rootfs_mount; 65 | } else { 66 | LOG("stat %s OK\n", "/private/"); 67 | } 68 | CHECK_ERROR(mount("devfs", "/dev", 0, "devfs"), "failed to mount devfs"); 69 | } 70 | -------------------------------------------------------------------------------- /src/fakedyld/main/pinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void get_pinfo(struct paleinfo* pinfo_p) { 4 | int rmd0 = open(RAW_RAMDISK, O_RDONLY, 0); 5 | if (rmd0 == -1) { 6 | panic("could not get paleinfo!"); 7 | } 8 | off_t off = lseek(rmd0, 0, SEEK_SET); 9 | if (off == -1) { 10 | panic("failed to lseek ramdisk to 0"); 11 | } 12 | uint32_t pinfo_off; 13 | ssize_t didRead = read(rmd0, &pinfo_off, sizeof(uint32_t)); 14 | if (didRead != (ssize_t)sizeof(uint32_t)) { 15 | panic("read %lld bytes does not match expected %llu bytes\n", didRead, sizeof(uint32_t)); 16 | } 17 | off = lseek(rmd0, pinfo_off, SEEK_SET); 18 | if (off == -1) { 19 | panic("failed to lseek ramdisk to %lld", pinfo_off); 20 | } 21 | didRead = read(rmd0, pinfo_p, sizeof(struct paleinfo)); 22 | if (didRead != (ssize_t)sizeof(struct paleinfo)) { 23 | panic("read %lld bytes does not match expected %llu bytes", didRead, sizeof(struct paleinfo)); 24 | } 25 | if (pinfo_p->magic != PALEINFO_MAGIC) { 26 | panic("Detected corrupted paleinfo!"); 27 | } 28 | if (pinfo_p->version != PALEINFO_VERSION) { 29 | panic("unexpected paleinfo version: %u, expected %u", pinfo_p->version, PALEINFO_VERSION); 30 | } 31 | close(rmd0); 32 | } 33 | -------------------------------------------------------------------------------- /src/fakedyld/main/pinfo_check.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef FAKEDYLD_ENABLE_LOGGING 4 | #define COMBINATION(opt, msg) {opt, msg} 5 | #else 6 | #define COMBINATION(opt, msg) {opt, ""} 7 | #endif 8 | 9 | /* 10 | * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL 11 | * NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and 12 | * "OPTIONAL" in this document are to be interpreted as described in 13 | * RFC 2119. 14 | */ 15 | 16 | /* 17 | * paleinfo sanity checks 18 | * unlike in old jbinit, the check here should concern the 19 | * internal consistency of the paleinfo only. 20 | * That is, do not consider boot args. 21 | */ 22 | void pinfo_check(struct paleinfo* pinfo_p) { 23 | /* flags that MUST NOT be set at the same time */ 24 | struct { 25 | uint64_t disallowed_combination; 26 | char* message; 27 | } disallowed_combinations[] = { 28 | COMBINATION(palerain_option_rootless | palerain_option_rootful, "cannot rootless and rootful at the same time"), 29 | COMBINATION(palerain_option_clean_fakefs | palerain_option_force_revert, "cannot force revert and clean fakefs at the same time"), 30 | COMBINATION(palerain_option_rootless_livefs | palerain_option_rootful, "cannot use rootless livefs option on rootful"), 31 | COMBINATION(palerain_option_clean_fakefs | palerain_option_setup_rootful, "canoot setup fakefs whlist cleaning fakefs"), 32 | {0, NULL} 33 | }; 34 | for (uint8_t i = 0; disallowed_combinations[i].disallowed_combination != 0; i++) { 35 | if ((pinfo_p->flags & disallowed_combinations[i].disallowed_combination) == disallowed_combinations[i].disallowed_combination) { 36 | panic("%s", disallowed_combinations[i].message); 37 | } 38 | } 39 | 40 | /* flags that MUST NOT be set when ramdisk is booted */ 41 | if ((pinfo_p->flags & ( 42 | palerain_option_dfuhelper_only | 43 | palerain_option_pongo_exit | 44 | palerain_option_demote | 45 | palerain_option_palerain_version | 46 | palerain_option_exit_recovery | 47 | palerain_option_reboot_device | 48 | palerain_option_enter_recovery | 49 | palerain_option_device_info 50 | )) != 0) { 51 | panic("ramdisk should never be booted with the options specified"); 52 | } 53 | return; 54 | } 55 | -------------------------------------------------------------------------------- /src/fakedyld/main/prepare_root.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const char* volume_prefix(void) { 5 | static char prefix[32] = {'\0'}; 6 | if (prefix[0] != '\0') return prefix; 7 | struct statfs64 rootfs_st; 8 | if (statfs64("/", &rootfs_st)) { 9 | panic("statfs64(/) failed"); 10 | } 11 | if (strcmp(rootfs_st.f_fstypename, "apfs")) { 12 | panic("unexpected filesystem type of /"); 13 | } 14 | 15 | char* pBSDName; 16 | if ((pBSDName = strstr(rootfs_st.f_mntfromname, "@/dev/"))) { 17 | pBSDName = &pBSDName[6]; 18 | } else { 19 | pBSDName = rootfs_st.f_mntfromname; 20 | } 21 | 22 | char* suffix = pBSDName; 23 | for (size_t i = 0; pBSDName[i] != '\0'; i++) { 24 | if (pBSDName[i] == 's') { 25 | suffix = &pBSDName[i+1]; 26 | } 27 | } 28 | suffix[0] = '\0'; 29 | snprintf(prefix, 32, "%s", pBSDName); 30 | return prefix; 31 | } 32 | 33 | void prepare_rootfs(struct systeminfo* sysinfo_p, struct paleinfo* pinfo_p, int platform) { 34 | int ret; 35 | struct stat64 statbuf; 36 | if (stat64("/System/Library/Frameworks/IOKit.framework", &statbuf) == 0) { 37 | return; 38 | } 39 | if (!(pinfo_p->flags & palerain_option_ssv)) return; 40 | char real_rootdev[32]; 41 | snprintf(real_rootdev, 32, "%s1", volume_prefix()); 42 | 43 | LOG("mounting realfs %s\n", real_rootdev); 44 | struct apfs_mount_args arg = { 45 | real_rootdev, 46 | MNT_RDONLY, APFS_MOUNT_FILESYSTEM /* "bdevvp failed: open" kernel panic when mount snapshot */ 47 | , 0, 0, { "" }, NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0 48 | }; 49 | ret = mount("apfs", "/cores/fs/real", MNT_RDONLY, &arg); 50 | if (ret) { 51 | panic("cannot mount %s onto %s, ret=%d", real_rootdev, "/cores/fs/real", errno); 52 | } 53 | 54 | fbi("/usr/standalone/update", "/cores/fs/real/usr/standalone/update"); 55 | if (platform == PLATFORM_IOS) { 56 | fbi("/System/Library/AccessibilityBundles", "/cores/fs/real/System/Library/AccessibilityBundles"); 57 | fbi("/System/Library/Assistant", "/cores/fs/real/System/Library/Assistant"); 58 | fbi("/System/Library/Audio", "/cores/fs/real/System/Library/Audio"); 59 | fbi("/System/Library/Fonts", "/cores/fs/real/System/Library/Fonts"); 60 | fbi("/System/Library/Frameworks", "/cores/fs/real/System/Library/Frameworks"); 61 | fbi("/System/Library/Health", "/cores/fs/real/System/Library/Health"); 62 | fbi("/System/Library/LinguisticData", "/cores/fs/real/System/Library/LinguisticData"); 63 | fbi("/System/Library/OnBoardingBundles", "/cores/fs/real/System/Library/OnBoardingBundles"); 64 | fbi("/System/Library/Photos", "/cores/fs/real/System/Library/Photos"); 65 | fbi("/System/Library/PreferenceBundles", "/cores/fs/real/System/Library/PreferenceBundles"); 66 | fbi("/System/Library/PreinstalledAssetsV2", "/cores/fs/real/System/Library/PreinstalledAssetsV2"); 67 | 68 | if (sysinfo_p->osrelease.darwinMajor < 22) { 69 | fbi("/System/Library/PrivateFrameworks", "/cores/fs/real/System/Library/PrivateFrameworks"); 70 | fbi("/System/Library/Caches", "/cores/fs/real/System/Library/Caches"); 71 | } 72 | } else { 73 | fbi("/System", "/cores/fs/real/System"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/fakedyld/main/rw_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void read_file(char* path, memory_file_handle_t* handle) { 4 | struct stat64 st; 5 | int ret; 6 | ret = stat64(path, &st); 7 | if (ret != 0) { 8 | panic("stat file %s failed: %d", path, errno); 9 | } 10 | int fd = open(path, O_RDONLY, 0); 11 | if (fd == -1) { 12 | panic("open file %s failed", path); 13 | } 14 | handle->file_p = mmap(NULL, ((st.st_size & ~0x3fff) + 0x4000), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 15 | if (handle->file_p == MAP_FAILED) { 16 | panic("mmap memory for reading file %s failed", path); 17 | } 18 | ssize_t didRead = read(fd, handle->file_p, st.st_size); 19 | printf("read %lld bytes from fd %d into %p\n", didRead, fd, handle->file_p); 20 | handle->file_len = st.st_size; 21 | if (didRead != st.st_size) { 22 | panic("unexpected data size %llu while reading file %s of size %llu", didRead, path, st.st_size); 23 | } 24 | close(fd); 25 | } 26 | 27 | void write_file(char* path, memory_file_handle_t* handle) { 28 | int fd = open(path, O_WRONLY | O_CREAT, 0755); 29 | if (fd == -1) { 30 | panic("open file %s failed", path); 31 | } 32 | ssize_t didWrite = write(fd, handle->file_p, handle->file_len);; 33 | if ((size_t)didWrite != handle->file_len) { 34 | panic("unexpected data size %llu while writing file %s of size %llu (fd: %d)", didWrite, path, handle->file_len, fd); 35 | } 36 | printf("wrote %zd bytes into %s\n", didWrite, path); 37 | handle->file_len = 0; 38 | close(fd); 39 | } 40 | -------------------------------------------------------------------------------- /src/fakedyld/main/start.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char** environ = NULL; 4 | const struct KernelArgs* gKernArgs; 5 | void* gPreDyldMH; 6 | 7 | void start(const struct KernelArgs* kernArgs, void* preDyldMH) 8 | __attribute__((noreturn)) __asm("start"); 9 | void start(const struct KernelArgs* kernArgs, void* preDyldMH) { 10 | gKernArgs = kernArgs; 11 | gPreDyldMH = preDyldMH; 12 | int argc = (int)kernArgs->argc; 13 | char** argv = (char**)&kernArgs->args[0]; 14 | char** envp = (char**)&kernArgs->args[argc + 1]; 15 | environ = envp; 16 | char** apple = envp; 17 | while (*apple != NULL) apple++; 18 | apple++; 19 | main(argc, (char**)argv, (char**)envp, (char**)apple); 20 | panic("main function returned"); 21 | } 22 | -------------------------------------------------------------------------------- /src/fakedyld/main/systeminfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern bool has_verbose_boot; 4 | void systeminfo(struct systeminfo* sysinfo_p) { 5 | size_t bootargs_len = MAX_BOOTARGS_LEN; 6 | CHECK_ERROR(sys_sysctlbyname("kern.bootargs", sizeof("kern.bootargs"), sysinfo_p->bootargs, &bootargs_len, NULL, 0), "Unable to read boot-args"); 7 | 8 | has_verbose_boot = (strstr(sysinfo_p->bootargs, "serial=") != NULL); 9 | 10 | size_t kversion_len = MAX_KVERSION_LEN; 11 | CHECK_ERROR(sys_sysctlbyname("kern.version", sizeof("kern.version"), sysinfo_p->kversion, &kversion_len, NULL, 0), "Unable to get kernel version"); 12 | 13 | char* p = strstr(sysinfo_p->kversion, "Darwin Kernel Version "); 14 | if (p == NULL) { 15 | LOG("failed to find \"Darwin Kernel Version \" in kernel version"); 16 | goto kver_fail; 17 | } 18 | p += (sizeof("Darwin Kernel Version ")-1); 19 | 20 | if (!isdigit(*p)) goto kver_fail; 21 | sysinfo_p->osrelease.darwinMajor = atoi(p); 22 | if (sysinfo_p->osrelease.darwinMajor == 0) { 23 | LOG("darwinMajor parsing error"); 24 | goto kver_fail; 25 | } 26 | 27 | p = (strchr(p, '.')); 28 | if (p == NULL) { 29 | LOG("darwinMinor parsing error"); 30 | goto kver_fail; 31 | } 32 | sysinfo_p->osrelease.darwinMinor = atoi(p+1); 33 | 34 | p += 1; 35 | p = (strchr(p, '.')); 36 | if (p == NULL) { 37 | LOG("darwinRevision parsing error"); 38 | goto kver_fail; 39 | } 40 | sysinfo_p->osrelease.darwinRevision = atoi(p+1); 41 | 42 | p += 1; 43 | char* xnu_p; 44 | if ((xnu_p = strstr(p, "root:xnu-")) != NULL) { 45 | p = xnu_p + (sizeof("root:xnu-")-1); 46 | } else if ((xnu_p = strstr(p, "root:xnu_development-")) != NULL) { 47 | p = xnu_p + (sizeof("root:xnu_development-")-1); 48 | } else if ((xnu_p = strstr(p, "root:xnu_debug-")) != NULL) { 49 | p = xnu_p + (sizeof("root:xnu_debug-")-1); 50 | } else if ((xnu_p = strstr(p, "root:xnu_kasan-")) != NULL) { 51 | p = xnu_p + (sizeof("root:xnu_kasan-")-1); 52 | } else { 53 | LOG("xnuMajor location failed"); 54 | goto kver_fail; 55 | } 56 | 57 | sysinfo_p->xnuMajor = atoi(p); 58 | if (sysinfo_p->xnuMajor == 0) { 59 | LOG("xnuMajor parsing error: %p", p); 60 | goto kver_fail; 61 | } 62 | return; 63 | kver_fail: 64 | panic("Error parsing kernel version"); 65 | __builtin_unreachable(); 66 | } 67 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/Makefile: -------------------------------------------------------------------------------- 1 | OBJDIR = obj 2 | SUBDIRS = plooshfinder patches 3 | SRC = $(wildcard *.c) 4 | OBJS = $(patsubst %,$(OBJDIR)/%,$(SRC:.c=.o)) 5 | CFLAGS += -I$(ROOT)/include/plooshfinder 6 | 7 | all: $(OBJS) $(patsubst %, %-all, $(SUBDIRS)) 8 | 9 | $(patsubst %, %-all, $(SUBDIRS)): 10 | $(MAKE) -C $(shell echo $@ | cut -d- -f1) 11 | 12 | $(patsubst %, %-clean, $(SUBDIRS)): 13 | $(MAKE) -C $(shell echo $@ | cut -d- -f1) clean 14 | 15 | $(OBJDIR): 16 | @mkdir -p $(OBJDIR) 17 | 18 | $(OBJDIR)/%.o: %.c $(OBJDIR) 19 | $(CC) $(CFLAGS) -c -o $@ $< 20 | 21 | clean: $(patsubst %, %-clean, $(SUBDIRS)) 22 | rm -rf obj 23 | 24 | .PHONY: all clean $(patsubst %, %-all, $(SUBDIRS)) $(patsubst %, %-clean, $(SUBDIRS)) 25 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/patches/Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS = platform 2 | 3 | $(patsubst %, %-all, $(SUBDIRS)): 4 | $(MAKE) -C $(shell echo $@ | cut -d- -f1) 5 | 6 | $(patsubst %, %-clean, $(SUBDIRS)): 7 | $(MAKE) -C $(shell echo $@ | cut -d- -f1) clean 8 | 9 | all: $(patsubst %, %-all, $(SUBDIRS)) 10 | 11 | clean: $(patsubst %, %-clean, $(SUBDIRS)) 12 | 13 | .PHONY: all $(patsubst %, %-all, $(SUBDIRS)) $(patsubst %, %-clean, $(SUBDIRS)) 14 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/patches/platform/Makefile: -------------------------------------------------------------------------------- 1 | OBJDIR = obj 2 | SRC = $(wildcard *.c) 3 | OBJS = $(patsubst %,$(OBJDIR)/%,$(SRC:.c=.o)) 4 | 5 | all: $(OBJS) 6 | 7 | $(OBJDIR): 8 | @mkdir -p $(OBJDIR) 9 | 10 | $(OBJDIR)/%.o: %.c $(OBJDIR) 11 | $(CC) $(CFLAGS) -c -o $@ $< 12 | 13 | clean: 14 | rm -rf obj 15 | 16 | .PHONY: all clean 17 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/patches/platform/patch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "asm/arm64.h" 5 | #include "plooshfinder.h" 6 | #include "plooshfinder32.h" 7 | #include "patches/platform/patch.h" 8 | #include "patches/platform/shellcode.h" 9 | 10 | int _internal_platform = 0; 11 | void *_internal_rbuf; 12 | bool has_found_platform_patch = false; 13 | 14 | bool inject_shc(struct pf_patch32_t __attribute__((unused)) *patch, uint32_t *stream) { 15 | uint32_t *shc_loc = copy_shc(_internal_rbuf, _internal_platform, stream[0]); 16 | 17 | if (!shc_loc) { 18 | printf("%s: no shellcode location??\n", __FUNCTION__); 19 | return false; 20 | } 21 | 22 | stream[0] = arm64_branch(stream, shc_loc, !pf_maskmatch32(stream[0], 0xd61f0000, 0xfffffc1f)); // branch to our shellcode to determine if we should change platform or leave it 23 | printf("%s: Patched platform check (shc b: 0x%x)\n", __FUNCTION__, stream[0]); 24 | 25 | has_found_platform_patch = true; 26 | return true; 27 | } 28 | 29 | void patch_platform_check(void *real_buf, void *dyld_buf, size_t dyld_len, uint32_t platform) { 30 | _internal_rbuf = real_buf; 31 | _internal_platform = platform; 32 | 33 | // r2: /x 00001fd6:1ffcdfff 34 | uint32_t matches[] = { 35 | 0xd61f0000 // b{l}r 36 | }; 37 | 38 | uint32_t masks[] = { 39 | 0xffdffc1f 40 | }; 41 | 42 | struct pf_patch_t patch = pf_construct_patch(matches, masks, sizeof(matches) / sizeof(uint32_t), (void *) inject_shc); 43 | 44 | struct pf_patch_t patches[] = { 45 | patch 46 | }; 47 | 48 | struct pf_patchset_t patchset = pf_construct_patchset(patches, sizeof(patches) / sizeof(struct pf_patch_t), (void *) pf_find_maskmatch32); 49 | 50 | pf_patchset_emit(dyld_buf, dyld_len, patchset); 51 | } 52 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/patches/platform/shellcode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "plooshfinder.h" 5 | #include "plooshfinder32.h" 6 | #include "formats/macho.h" 7 | #include "patches/platform/shellcode.h" 8 | 9 | uint32_t *shc_loc = NULL; 10 | struct section_64 *section = NULL; 11 | 12 | uint32_t shellcode_br[] = { 13 | 0xf100283f, // cmp x1, 10 14 | 0x54000040, // b.eq 0x8 15 | 0xd2800001, // mov x1, {plat} 16 | 0x0, // br {reg} 17 | }; 18 | 19 | uint32_t shellcode_blr[] = { 20 | 0xa9bf7bfd, // stp fp, lr, [sp, -0x10]! 21 | 0x910003fd, // mov fp, sp 22 | 0xf100283f, // cmp x1, 10 23 | 0x54000040, // b.eq 0x8 24 | 0xd2800001, // mov x1, {plat} 25 | 0x0, // blr {reg} 26 | 0xa8c17bfd, // ldp fp, lr, [sp], 0x10 27 | ret 28 | }; 29 | 30 | uint32_t *copy_shc(void *buf, int platform, uint32_t jmp) { 31 | uint32_t *shellcode = 0; 32 | size_t shc_size = 0; 33 | 34 | bool br = pf_maskmatch32(jmp, 0xd61f0000, 0xfffffc1f); 35 | 36 | if (br) { 37 | shellcode = shellcode_br; 38 | shc_size = sizeof(shellcode_br) / sizeof(uint32_t); 39 | 40 | shellcode[2] |= platform << 5; 41 | shellcode[3] = jmp; 42 | } else { 43 | shellcode = shellcode_blr; 44 | shc_size = sizeof(shellcode_blr) / sizeof(uint32_t); 45 | 46 | shellcode[4] |= platform << 5; 47 | shellcode[5] = jmp; 48 | } 49 | 50 | if (br && shc_loc != NULL) { 51 | return shc_loc; 52 | } 53 | 54 | if (!section) { 55 | section = macho_find_section(buf, "__TEXT", "__text"); 56 | } 57 | 58 | if (!section) { 59 | printf("%s: Unable to find text section!\n", __FUNCTION__); 60 | return NULL; 61 | } 62 | 63 | shc_loc = pf_find_zero_buf(buf + section->offset, section->size, shc_size); 64 | if (!shc_loc) { 65 | printf("%s: No shellcode location!\n", __FUNCTION__); 66 | return NULL; 67 | } 68 | 69 | for (size_t i = 0; i < shc_size; i++) { 70 | shc_loc[i] = shellcode[i]; 71 | } 72 | 73 | return shc_loc; 74 | } 75 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/plooshfinder/.gitignore: -------------------------------------------------------------------------------- 1 | obj/ 2 | libplooshfinder.a 3 | .vscode -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/plooshfinder/Makefile: -------------------------------------------------------------------------------- 1 | SRC = $(wildcard src/*.c) $(wildcard src/formats/*.c) $(wildcard src/asm/*.c) 2 | OBJDIR = obj 3 | OBJS = $(patsubst src/%,$(OBJDIR)/%,$(SRC:.c=.o)) 4 | DIRS := $(OBJDIR) $(OBJDIR)/formats $(OBJDIR)/asm 5 | 6 | all: $(DIRS) $(OBJS) 7 | 8 | $(DIRS): 9 | @mkdir -p $@ 10 | 11 | clean: 12 | @rm -rf obj 13 | 14 | $(OBJDIR)/%.o: src/%.c 15 | $(CC) $(CFLAGS) -c -o $@ $< 16 | 17 | .PHONY: all clean 18 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/plooshfinder/src/asm/arm64.c: -------------------------------------------------------------------------------- 1 | #include "asm/arm64.h" 2 | 3 | uint32_t arm64_branch(void *caller, void *target, bool link) { 4 | uint32_t insn = 0x14000000; 5 | 6 | if (link) { 7 | insn |= 1 << 31; 8 | } 9 | 10 | uint32_t offset = (target - caller) >> 2; 11 | 12 | // so that we can fit in the imm field 13 | offset <<= 6; 14 | offset >>= 6; 15 | 16 | return insn | offset; 17 | } 18 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/plooshfinder/src/formats/multi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "formats/macho.h" 5 | #include "formats/elf.h" 6 | #include "formats/pe.h" 7 | #include "utils.h" 8 | // right now this is just ptr & virtual address conversion 9 | 10 | void *pf_va_to_ptr(void *buf, uint64_t addr) { 11 | void *ptr = NULL; 12 | 13 | if (macho_check(buf)) { 14 | ptr = macho_va_to_ptr(buf, addr); 15 | } else if (elf_check(buf)) { 16 | ptr = elf_va_to_ptr(buf, addr); 17 | } else if (pe_check(buf)) { 18 | ptr = pe_va_to_ptr(buf, addr); 19 | } else { 20 | printf("%s: Unknown binary format!\n", __FUNCTION__); 21 | } 22 | 23 | return ptr; 24 | } 25 | 26 | uint64_t pf_ptr_to_va(void *buf, void *ptr) { 27 | uint64_t va = 0; 28 | 29 | if (macho_check(buf)) { 30 | va = macho_ptr_to_va(buf, ptr); 31 | } else if (elf_check(buf)) { 32 | va = elf_ptr_to_va(buf, ptr); 33 | } else if (pe_check(buf)) { 34 | va = pe_ptr_to_va(buf, ptr); 35 | } else { 36 | printf("%s: Unknown binary format!\n", __FUNCTION__); 37 | } 38 | 39 | return va; 40 | } 41 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/plooshfinder/src/plooshfinder32.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "plooshfinder32.h" 5 | 6 | bool pf_maskmatch32(uint32_t insn, uint32_t match, uint32_t mask) { 7 | return (insn & mask) == match; 8 | } 9 | 10 | void pf_find_maskmatch32(void *buf, size_t size, struct pf_patchset32_t patchset) { 11 | uint32_t *stream = buf; 12 | uint64_t uint_count = size >> 2; 13 | 14 | for (uint64_t i = 0; i < uint_count; i++) { 15 | for (uint32_t p = 0; p < patchset.count; p++) { 16 | struct pf_patch32_t *patch = patchset.patches + p; 17 | if (patch->disabled) continue; 18 | 19 | uint32_t x; 20 | for (x = 0; x < patch->count; x++) { 21 | if (!pf_maskmatch32(stream[i + x], patch->matches[x], patch->masks[x])) { 22 | break; 23 | } 24 | } 25 | 26 | if (x == patch->count) { 27 | patch->callback(patch, stream + i); 28 | } 29 | } 30 | } 31 | } 32 | 33 | int32_t pf_signextend_32(int32_t val, uint8_t bits) { 34 | val = (uint32_t) val << (32 - bits); 35 | val >>= 32 - bits; 36 | 37 | return val; 38 | } 39 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/plooshfinder/src/plooshfinder64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "plooshfinder64.h" 5 | 6 | bool pf_maskmatch64(uint64_t insn, uint64_t match, uint64_t mask) { 7 | return (insn & mask) == match; 8 | } 9 | 10 | void pf_find_maskmatch64(void *buf, size_t size, struct pf_patchset64_t patchset) { 11 | uint64_t *stream = buf; 12 | uint64_t uint_count = size >> 3; 13 | 14 | for (uint64_t i = 0; i < uint_count; i++) { 15 | for (uint32_t p = 0; p < patchset.count; p++) { 16 | struct pf_patch64_t *patch = patchset.patches + p; 17 | if (patch->disabled) continue; 18 | 19 | uint32_t x; 20 | for (x = 0; x < patch->count; x++) { 21 | if (!pf_maskmatch64(stream[i + x], patch->matches[x], patch->masks[x])) { 22 | break; 23 | } 24 | } 25 | 26 | if (x == patch->count) { 27 | patch->callback(patch, stream + i); 28 | } 29 | } 30 | } 31 | } 32 | 33 | int64_t pf_signextend_64(int64_t val, uint8_t bits) { 34 | val = (uint64_t) val << (64 - bits); 35 | val >>= 64 - bits; 36 | 37 | return val; 38 | } 39 | -------------------------------------------------------------------------------- /src/fakedyld/patch_dyld/plooshfinder/src/utils.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | // the compiler will just use a bswap (optimizations) if possible 4 | // but it's here if it's needed (i.e. there's no intrinsic) 5 | uint32_t convert_endianness32(uint32_t val) { 6 | uint32_t swapped = 0; 7 | for (uint32_t i = 0; i < 4; i++) { 8 | uint32_t sh = i << 3; 9 | swapped |= ((val >> sh) & 0xff) << (sh ^ 24); 10 | } 11 | 12 | return swapped; 13 | } -------------------------------------------------------------------------------- /src/libjailbreak/.gitignore: -------------------------------------------------------------------------------- 1 | libjailbreak.a 2 | -------------------------------------------------------------------------------- /src/libjailbreak/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -mappletvos-version-min=12.0 -std=gnu17 -fvisibility=hidden 2 | LDFLAGS += -Wl,-dead_strip -Wno-unused-command-line-argument 3 | OBJDIR = obj 4 | C_SRC = $(wildcard *.c) 5 | LIBS = -framework CoreFoundation 6 | OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.c.o)) 7 | 8 | ifeq ($(ASAN),1) 9 | CFLAGS += -fsanitize=address,undefined 10 | LDFLAGS += -rpath /cores 11 | endif 12 | 13 | all: libjailbreak.a 14 | 15 | $(OBJDIR): 16 | @mkdir -p $(OBJDIR) 17 | 18 | $(OBJDIR)/%.c.o: %.c $(OBJDIR) 19 | $(CC) $(CFLAGS) -c -o $@ $< 20 | 21 | libjailbreak.a: $(OBJS) 22 | $(AR) cr libjailbreak.a $(OBJS); 23 | 24 | clean: 25 | rm -rf libjailbreak.a* obj 26 | 27 | .PHONY: all clean 28 | -------------------------------------------------------------------------------- /src/libjailbreak/bmhash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int jailbreak_get_bmhash(char* hash) 7 | { 8 | const UInt8 *bytes; 9 | CFIndex length; 10 | io_registry_entry_t chosen = IORegistryEntryFromPath(0, "IODeviceTree:/chosen"); 11 | if (!MACH_PORT_VALID(chosen)) return 1; 12 | CFDataRef manifestHash = (CFDataRef)IORegistryEntryCreateCFProperty(chosen, CFSTR("boot-manifest-hash"), kCFAllocatorDefault, 0); 13 | IOObjectRelease(chosen); 14 | if (manifestHash == NULL || CFGetTypeID(manifestHash) != CFDataGetTypeID()) 15 | { 16 | if (manifestHash != NULL) CFRelease(manifestHash); 17 | return 1; 18 | } 19 | length = CFDataGetLength(manifestHash); 20 | bytes = CFDataGetBytePtr(manifestHash); 21 | for (int i = 0; i < length; i++) 22 | { 23 | snprintf(&hash[i * 2], 3, "%02X", bytes[i]); 24 | } 25 | CFRelease(manifestHash); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /src/libjailbreak/jbdcall.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | xpc_object_t jailbreak_send_jailbreakd_message_with_reply_sync(xpc_object_t xdict) { 6 | xpc_connection_t connection = xpc_connection_create_mach_service("in.palera.palera1nd.systemwide", NULL, 0); 7 | if (xpc_get_type(connection) == XPC_TYPE_ERROR) { 8 | return connection; 9 | } 10 | xpc_connection_set_event_handler(connection, ^(xpc_object_t __unused _) {}); 11 | xpc_connection_activate(connection); 12 | xpc_object_t xreply = xpc_connection_send_message_with_reply_sync(connection, xdict); 13 | xpc_connection_cancel(connection); 14 | xpc_release(connection); 15 | return xreply; 16 | } 17 | 18 | xpc_object_t jailbreak_send_jailbreakd_command_with_reply_sync(uint64_t cmd) { 19 | xpc_object_t xdict = xpc_dictionary_create(NULL, NULL, 0); 20 | xpc_dictionary_set_uint64(xdict, "cmd", cmd); 21 | xpc_object_t xreply = jailbreak_send_jailbreakd_message_with_reply_sync(xdict); 22 | xpc_release(xdict); 23 | return xreply; 24 | } 25 | -------------------------------------------------------------------------------- /src/libjailbreak/launchd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int jailbreak_send_launchd_message(xpc_object_t xdict, xpc_object_t *xreply) { 8 | int ret = 0; 9 | xpc_dictionary_set_bool(xdict, "jailbreak", true); 10 | xpc_object_t bootstrap_pipe = ((struct xpc_global_data *)_os_alloc_once_table[OS_ALLOC_ONCE_KEY_LIBXPC].ptr)->xpc_bootstrap_pipe; 11 | if (__builtin_available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)) { 12 | ret = _xpc_pipe_interface_routine(bootstrap_pipe, 0, xdict, xreply, 0); 13 | } else { 14 | ret = xpc_pipe_routine(bootstrap_pipe, xdict, xreply); 15 | } 16 | //ret = xpc_pipe_routine(bootstrap_pipe, xdict, xreply); 17 | if (ret == 0 && (ret = (int)xpc_dictionary_get_int64(*xreply, "error")) == 0) 18 | return 0; 19 | 20 | return ret; 21 | } 22 | -------------------------------------------------------------------------------- /src/libjailbreak/prebootpath.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int jailbreak_get_prebootPath(char jbPath[150]) { 14 | struct utsname name; 15 | int ret = uname(&name); 16 | if (ret) return errno; 17 | if (atoi(name.release) < 20) return ENOTSUP; 18 | char bmhash[97]; 19 | jailbreak_get_bmhash(bmhash); 20 | snprintf(jbPath, 150, "/private/preboot/%s", bmhash); 21 | DIR* dir = opendir(jbPath); 22 | if (!dir) { 23 | return ENOENT; 24 | } 25 | char jbPathName[20]; 26 | bool has_prebootjb = false; 27 | struct dirent* d; 28 | while ((d = readdir(dir)) != NULL) { 29 | if (strncmp(d->d_name, "jb-", 3)) continue; 30 | if (has_prebootjb == true) { 31 | closedir(dir); 32 | return EEXIST; 33 | } 34 | snprintf(jbPathName, 20, "%s" ,d->d_name); 35 | has_prebootjb = true; 36 | } 37 | closedir(dir); 38 | if (!has_prebootjb) return ENOENT; 39 | snprintf(jbPath, 150, "/private/preboot/%s/%s/procursus", bmhash, jbPathName); 40 | struct stat st; 41 | if ((stat(jbPath, &st))) { 42 | return ENXIO; 43 | } 44 | if (!S_ISDIR(st.st_mode)) { 45 | return ENOTDIR; 46 | } 47 | return KERN_SUCCESS; 48 | } 49 | 50 | int jailbreak_get_bmhash_path(char jbPath[150]) { 51 | struct utsname name; 52 | int ret = uname(&name); 53 | if (ret) return errno; 54 | if (atoi(name.release) < 20) return ENOTSUP; 55 | char bmhash[97]; 56 | jailbreak_get_bmhash(bmhash); 57 | snprintf(jbPath, 150, "/private/preboot/%s", bmhash); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /src/libjailbreak/strflags.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const char* jailbreak_str_pinfo_flag(uint64_t flag) { 5 | switch (flag) { 6 | case palerain_option_rootful: 7 | return "palerain_option_rootful"; 8 | case palerain_option_rootless: 9 | return "palerain_option_rootless"; 10 | case palerain_option_setup_rootful: 11 | return "palerain_option_setup_rootful"; 12 | case palerain_option_checkrain_is_clone: 13 | return "palerain_option_checkrain_is_clone"; 14 | case palerain_option_rootless_livefs: 15 | return "palerain_option_rootless_livefs"; 16 | case palerain_option_ssv: 17 | return "palerain_option_ssv"; 18 | case palerain_option_clean_fakefs: 19 | return "palerain_option_clean_fakefs"; 20 | case palerain_option_tui: 21 | return "palerain_option_tui"; 22 | case palerain_option_dfuhelper_only: 23 | return "palerain_option_dfuhelper_only"; 24 | case palerain_option_pongo_exit: 25 | return "palerain_option_pongo_exit"; 26 | case palerain_option_demote: 27 | return "palerain_option_demote"; 28 | case palerain_option_pongo_full: 29 | return "palerain_option_pongo_full"; 30 | case palerain_option_palerain_version: 31 | return "palerain_option_palerain_version"; 32 | case palerain_option_exit_recovery: 33 | return "palerain_option_exit_recovery"; 34 | case palerain_option_reboot_device: 35 | return "palerain_option_reboot_device"; 36 | case palerain_option_enter_recovery: 37 | return "palerain_option_enter_recovery"; 38 | case palerain_option_device_info: 39 | return "palerain_option_device_info"; 40 | case palerain_option_no_colors: 41 | return "palerain_option_no_colors"; 42 | case palerain_option_bind_mount: 43 | return "palerain_option_bind_mount"; 44 | case palerain_option_overlay: 45 | return "palerain_option_overlay"; 46 | case palerain_option_force_revert: 47 | return "palerain_option_force_revert"; 48 | case palerain_option_safemode: 49 | return "palerain_option_safemode"; 50 | case palerain_option_verbose_boot: 51 | return "palerain_option_verbose_boot"; 52 | case palerain_option_cli: 53 | return "palerain_option_cli"; 54 | case palerain_option_jbinit_log_to_file: 55 | return "palerain_option_jbinit_log_to_file"; 56 | case palerain_option_setup_rootful_forced: 57 | return "palerain_option_setup_rootful_forced"; 58 | case palerain_option_failure: 59 | return "palerain_option_failure"; 60 | case palerain_option_flower_chain: 61 | return "palerain_option_flower_chain"; 62 | case palerain_option_test1: 63 | return "palerain_option_test1"; 64 | case palerain_option_test2: 65 | return "palerain_option_test2"; 66 | default: 67 | return "palera1n_option_undefined"; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/libs/substrate.tbd: -------------------------------------------------------------------------------- 1 | --- !tapi-tbd 2 | tbd-version: 4 3 | targets: [ arm64-ios, arm64-tvos, arm64-bridgeos ] 4 | uuids: 5 | - target: arm64-ios 6 | value: 847B3DA6-A02C-309E-844B-EF89824075EC 7 | - target: arm64-tvos 8 | value: 847B3DA6-A02C-309E-844B-EF89824075EF 9 | - target: arm64-tvos 10 | value: 847B3DA6-A02C-309E-844B-EF89824075AA 11 | flags: [ not_app_extension_safe ] 12 | install-name: '@rpath/CydiaSubstrate.framework/CydiaSubstrate' 13 | exports: 14 | - targets: [ arm64-ios, arm64-tvos, arm64-bridgeos ] 15 | symbols: [ _MSHookFunction, _MSHookMessageEx, _MSGetImageByName, _MSCloseImage, _MSFindSymbol, 16 | _MSHookClassPair, _MSHookIvar, _MSHookMemory ] 17 | ... 18 | -------------------------------------------------------------------------------- /src/mount_cores/.gitignore: -------------------------------------------------------------------------------- 1 | mount_cores* 2 | -------------------------------------------------------------------------------- /src/mount_cores/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -mappletvos-version-min=12.0 -std=gnu17 -U__nonnull -DMOUNT_CORES 2 | CFLAGS += -isystem $(ROOT)/apple-include 3 | LDFLAGS += -Wl,-dead_strip -Wno-unused-command-line-argument 4 | SRC = $(wildcard *.c) 5 | OBJDIR = obj 6 | OBJS = $(patsubst %,$(OBJDIR)/%,$(SRC:.c=.o)) 7 | LIBS = -framework CoreFoundation ../libs/IOKit.tbd 8 | PLATFORMS = 2 3 5 9 | 10 | all: $(patsubst %, mount_cores.%, $(PLATFORMS)) 11 | 12 | OBJS = $(patsubst %,$(OBJDIR)/%,$(SRC:.c=.o)) 13 | 14 | $(OBJDIR): 15 | @mkdir -p $(OBJDIR) 16 | 17 | $(OBJDIR)/%.o: %.c $(OBJDIR) 18 | $(CC) $(CFLAGS) -c -o $@ $< 19 | 20 | mount_cores: $(OBJS) 21 | $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ 22 | $(DSYMUTIL) $@ 23 | ifeq ($(DEV_BUILD),1) 24 | $(STRIP) $@ 25 | endif 26 | 27 | mount_cores.%: mount_cores entitlements.xml 28 | $(VTOOL) -remove-build-version 3 -output $@ $< 29 | if [ "$@" = "mount_cores.5" ]; then \ 30 | os=3; \ 31 | else os=12; \ 32 | fi; \ 33 | $(VTOOL) -set-build-version $$(echo $@ | cut -d. -f2) $$os $$os -replace -output $@ $@ 34 | $(LDID) -Sentitlements.xml $@ 35 | 36 | clean: 37 | rm -fr mount_cores* obj 38 | -------------------------------------------------------------------------------- /src/mount_cores/entitlements.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.private.diskimages.kext.user-client-access 6 | 7 | com.apple.private.security.disk-device-access 8 | 9 | com.apple.private.security.no-container 10 | 11 | com.apple.security.iokit-user-client-class 12 | 13 | IOHDIXControllerUserClient 14 | 15 | platform-application 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/mount_cores/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int attach_dmg(const char *source, char* device_path, size_t device_path_len); 10 | 11 | _Noreturn void spin(int fd_console) { 12 | dprintf(fd_console, "jbinit DIED!\n"); 13 | while(1) { 14 | sleep(3600); 15 | } 16 | } 17 | 18 | int main(void) { 19 | spin(1); 20 | int fd_console = open("/dev/console", O_RDWR); 21 | if (fd_console == -1) { 22 | spin(fd_console); 23 | } 24 | dprintf(fd_console, "mounting /cores"); 25 | /*if (getppid() != 1) { 26 | fprintf(stderr, "this is a plooshra1n internal utility, do not use\n"); 27 | return -1; 28 | }*/ 29 | char device_path[50]; 30 | int ret = attach_dmg("ram://2048", device_path, 50); 31 | if (ret) spin(fd_console); 32 | pid_t pid; 33 | posix_spawn_file_actions_t actions; 34 | posix_spawn_file_actions_init(&actions); 35 | posix_spawn_file_actions_addopen(&actions, STDIN_FILENO, "/dev/console", O_RDWR, 0); 36 | posix_spawn_file_actions_addopen(&actions, STDOUT_FILENO, "/dev/console", O_WRONLY, 0); 37 | posix_spawn_file_actions_addopen(&actions, STDERR_FILENO, "/dev/console", O_WRONLY, 0); 38 | ret = posix_spawn(&pid, "/sbin/newfs_hfs", &actions, NULL, (char*[]){ "/sbin/newfs_hfs", "-s", "-v", "nebula is a furry", device_path, NULL } , NULL); 39 | posix_spawn_file_actions_destroy(&actions); 40 | if (ret) { 41 | dprintf(fd_console, "faild to spawn /sbin/newfs_hfs: %d\n", errno); 42 | spin(fd_console); 43 | } 44 | int status; 45 | waitpid(pid, &status, 0); 46 | if (!WIFEXITED(status) || WEXITSTATUS(status)) { 47 | dprintf(fd_console, "/sbin/newfs_hfs failed\n"); 48 | spin(fd_console); 49 | } 50 | struct hfs_mount_args cores_mountarg = { device_path, 0, 0, 0, 0, { 0, 0 }, HFSFSMNT_EXTENDED_ARGS, 0, 0, 1 }; 51 | ret = mount("hfs", "/cores", 0, &cores_mountarg); 52 | if (ret) { 53 | dprintf(fd_console, "mount failed: %d\n", errno); 54 | spin(fd_console); 55 | } 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /src/payload/.gitignore: -------------------------------------------------------------------------------- 1 | obj 2 | payload 3 | -------------------------------------------------------------------------------- /src/payload/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palera1n/jbinit/c1015df65dad3704ace43feb6ebc310542c60422/src/payload/Info.plist -------------------------------------------------------------------------------- /src/payload/Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS = loader p1ctl jailbreakd 2 | CFLAGS += -mappletvos-version-min=12.0 -std=gnu17 3 | CFLAGS += -Wno-nullability-completeness 4 | LDFLAGS += -Wl,-dead_strip -Wno-unused-command-line-argument 5 | LDFLAGS += -Wl,-sectcreate,__TEXT,__info_plist,Info.plist 6 | OBJDIR = obj 7 | C_SRC = $(wildcard *.c) 8 | LIBS = -framework CoreFoundation ../libs/IOKit.tbd -framework Foundation 9 | LIBS += -framework Security ../libs/IOMobileFramebuffer.tbd 10 | LIBS += -framework CoreGraphics -framework ImageIO -framework IOSurface 11 | LIBS += ../libs/APFS.tbd ../libjailbreak/libjailbreak.a 12 | OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.c.o)) 13 | 14 | LAUNCHCTL_OBJ = bootstrap.o xpc_helper.o load.o 15 | 16 | ifeq ($(ASAN),1) 17 | CFLAGS += -fsanitize=address,undefined 18 | LDFLAGS += -rpath /cores 19 | endif 20 | 21 | export CFLAGS LDFLAGS 22 | 23 | all: $(patsubst %, %-all, $(SUBDIRS)) payload 24 | 25 | $(OBJDIR): 26 | @mkdir -p $(OBJDIR) launchctl/$(OBJDIR) 27 | 28 | $(OBJDIR)/%.c.o: %.c $(OBJDIR) 29 | $(CC) $(CFLAGS) -c -o $@ $< 30 | 31 | $(patsubst %.o, launchctl/%.o, $(LAUNCHCTL_OBJ)): $(patsubst %.o, launchctl/%.c, $(LAUNCHCTL_OBJ)) 32 | CFLAGS="$(CFLAGS) -Wno-unused-parameter" $(MAKE) -C launchctl $(shell echo $@ | cut -d/ -f2) 33 | 34 | payload: $(patsubst %, %-all, $(SUBDIRS)) $(OBJS) $(patsubst %.o, launchctl/%.o, $(LAUNCHCTL_OBJ)) 35 | $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(patsubst %.o, launchctl/%.o, $(LAUNCHCTL_OBJ)) $$(find . -name '*.o' | grep 'obj/.*o') -o payload 36 | $(DSYMUTIL) payload 37 | ifneq ($(DEV_BUILD),1) 38 | $(STRIP) payload 39 | endif 40 | $(LDID) -Sentitlements.xml -Icom.apple.payload payload 41 | 42 | $(patsubst %, %-all, $(SUBDIRS)): 43 | $(MAKE) -C $$(echo $@ | cut -d- -f1) 44 | 45 | $(patsubst %, %-clean, $(SUBDIRS)): 46 | $(MAKE) -C $$(echo $@ | cut -d- -f1) clean 47 | 48 | clean: $(patsubst %, %-clean, $(SUBDIRS)) 49 | rm -rf payload payload.dSYM $(OBJDIR) launchctl/*.o 50 | 51 | .PHONY: all $(patsubst %, %-all, $(SUBDIRS)) $(patsubst %, %-clean, $(SUBDIRS)) 52 | -------------------------------------------------------------------------------- /src/payload/jailbreakd/Makefile: -------------------------------------------------------------------------------- 1 | OBJDIR = obj 2 | C_SRC = $(wildcard *.c) 3 | OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.c.o)) 4 | 5 | all: $(OBJS) 6 | 7 | $(OBJDIR): 8 | @mkdir -p $(OBJDIR) 9 | 10 | $(OBJDIR)/%.c.o: %.c $(OBJDIR) 11 | $(CC) $(CFLAGS) -c -o $@ $< 12 | 13 | clean: 14 | rm -rf obj 15 | 16 | .PHONY: all clean 17 | -------------------------------------------------------------------------------- /src/payload/jailbreakd/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void reload_launchd_env(void) { 15 | xpc_object_t launchd_dict = xpc_dictionary_create(NULL, NULL, 0); 16 | xpc_object_t launchd_reply; 17 | xpc_dictionary_set_uint64(launchd_dict, "cmd", LAUNCHD_CMD_RELOAD_JB_ENV); 18 | jailbreak_send_launchd_message(launchd_dict, &launchd_reply); 19 | xpc_release(launchd_dict); 20 | xpc_release(launchd_reply); 21 | } 22 | 23 | ssize_t write_fdout(int fd, void* buf, size_t len) { 24 | ssize_t to_write = len, written = 0; 25 | uint8_t* buf_current = buf; 26 | do { 27 | if (to_write > INT_MAX) to_write = INT_MAX; 28 | ssize_t didWrite = write(fd, buf_current, to_write); 29 | if (didWrite == -1) return -1; 30 | written += didWrite; 31 | len -= didWrite; 32 | to_write = len; 33 | buf_current += didWrite; 34 | } while (len > 0); 35 | return written; 36 | } 37 | 38 | void palera1nd_handler(xpc_object_t peer, xpc_object_t event, struct paleinfo* pinfo); 39 | int palera1nd_main(int __unused argc, char* __unused argv[]) { 40 | PALERA1ND_LOG_DEBUG("starting palera1nd"); 41 | struct paleinfo pinfo; 42 | int ret = get_pinfo(&pinfo); 43 | if (ret) return -1; 44 | 45 | xpc_connection_t connection = xpc_connection_create_mach_service("in.palera.palera1nd.systemwide", dispatch_get_main_queue(), XPC_CONNECTION_MACH_SERVICE_LISTENER); 46 | 47 | xpc_connection_set_event_handler(connection, ^(xpc_object_t peer) { 48 | char* desc = xpc_copy_description(peer); 49 | free(desc); 50 | if (xpc_get_type(peer) == XPC_TYPE_CONNECTION) { 51 | xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { 52 | char* desc = xpc_copy_description(event); 53 | if (xpc_get_type(event) == XPC_TYPE_ERROR) { 54 | PALERA1ND_LOG_DEBUG("received error dictionary: %s", desc); 55 | free(desc); 56 | return; 57 | } 58 | free(desc); 59 | 60 | palera1nd_handler(peer, event, (struct paleinfo*)&pinfo); 61 | }); 62 | 63 | xpc_connection_resume(peer); 64 | } else if (xpc_get_type(peer) == XPC_TYPE_ERROR) { 65 | return; 66 | } 67 | }); 68 | 69 | xpc_connection_activate(connection); 70 | dispatch_main(); 71 | return -1; 72 | } 73 | -------------------------------------------------------------------------------- /src/payload/jailbreakd/obliterate.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #define TARGET_OS_IPHONE 1 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | extern char** environ; 26 | 27 | void revert_snapshot(void); 28 | void clean_fakefs(void); 29 | int reboot3(uint64_t howto, ...); 30 | 31 | int revert_rootful(xpc_object_t xreply, struct paleinfo* pinfo) { 32 | int unload_cmd_ret, remove_ret; 33 | xpc_object_t msg; 34 | unload_cmd_ret = load_cmd(&msg, 2, (char*[]){ "unload", "/Library/LaunchDaemons", NULL }, environ, (char*[]){ NULL }); 35 | remove_ret = remove_jailbreak_files(pinfo->flags); 36 | xpc_release(msg); 37 | 38 | /* if force revert is set then do not anything to the root fs */ 39 | if ((pinfo->flags & palerain_option_force_revert) == 0) { 40 | if (pinfo->flags & palerain_option_ssv) clean_fakefs(); 41 | else revert_snapshot(); 42 | } 43 | 44 | xpc_dictionary_set_int64(xreply, "unload_cmd_ret", (int64_t)unload_cmd_ret); 45 | xpc_dictionary_set_int64(xreply, "remove_ret", (int64_t)remove_ret); 46 | return remove_ret; 47 | } 48 | 49 | int revert_rootless(xpc_object_t xreply, struct paleinfo* pinfo) { 50 | int unload_cmd_ret, remove_ret; 51 | xpc_object_t msg; 52 | unload_cmd_ret = load_cmd(&msg, 2, (char*[]){ "unload", "/var/jb/Library/LaunchDaemons", NULL }, environ, (char*[]){ NULL }); 53 | xpc_release(msg); 54 | remove_ret = remove_jailbreak_files(pinfo->flags); 55 | 56 | xpc_dictionary_set_int64(xreply, "unload_cmd_ret", (int64_t)unload_cmd_ret); 57 | xpc_dictionary_set_int64(xreply, "remove_ret", (int64_t)remove_ret); 58 | return remove_ret; 59 | } 60 | 61 | void obliterate(xpc_object_t xrequest, xpc_object_t xreply, struct paleinfo* pinfo) { 62 | if ((pinfo->flags & (palerain_option_rootful | palerain_option_ssv)) == (palerain_option_rootful | palerain_option_ssv)) { 63 | if (!xpc_dictionary_get_bool(xrequest, "keep-fakefs")) { 64 | xpc_dictionary_set_string(xreply, "errorDescription", "oblierating jailbreak while booted is not supported on rootful fakefs"); 65 | xpc_dictionary_set_int64(xreply, "error", ENOTSUP); 66 | return; 67 | } 68 | } 69 | int remove_ret; 70 | if (pinfo->flags & palerain_option_rootful) 71 | remove_ret = revert_rootful(xreply, pinfo); 72 | else 73 | remove_ret = revert_rootless(xreply, pinfo); 74 | 75 | if (remove_ret) { 76 | xpc_dictionary_set_string(xreply, "errorDescription", "remove_jailbreak_files returned non-zero code"); 77 | } else { 78 | if (pinfo->flags & palerain_option_rootful) { 79 | xpc_dictionary_set_string(xreply, "message", "Success. Now rebooting."); 80 | } else { 81 | xpc_dictionary_set_string(xreply, "message", "Success"); 82 | } 83 | } 84 | 85 | reload_launchd_env(); 86 | 87 | if (pinfo->flags & palerain_option_rootful) reboot3(RB_AUTOBOOT); 88 | return; 89 | } 90 | -------------------------------------------------------------------------------- /src/payload/jailbreakd/reboot3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #define TARGET_OS_IPHONE 1 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #define ENOENTITLEMENT 144 28 | #define ENOTPLATFORM 154 29 | #define RB2_USERREBOOT (0x2000000000000000llu) 30 | #define ITHINK_PURPOSE (0x0100000000000000llu) 31 | int reboot3(uint64_t howto, ...); 32 | 33 | void perform_reboot3(xpc_object_t peer, xpc_object_t xreply, xpc_object_t request, struct paleinfo* __unused pinfo_p) { 34 | audit_token_t token; 35 | xpc_connection_get_audit_token(peer, &token); 36 | pid_t pid = xpc_connection_get_pid(peer); 37 | if (pid == -1) { 38 | xpc_dictionary_set_int64(xreply, "error", errno); 39 | return; 40 | } 41 | int status; 42 | int ret = csops_audittoken(pid, CS_OPS_STATUS, &status, 4, &token); 43 | if (ret) { 44 | xpc_dictionary_set_int64(xreply, "error", errno); 45 | return; 46 | } 47 | if ((status & CS_PLATFORM_BINARY) == 0) { 48 | xpc_dictionary_set_int64(xreply, "error", ENOTPLATFORM); 49 | return; 50 | } 51 | xpc_object_t xpc_howto = xpc_dictionary_get_value(request, "howto"); 52 | xpc_object_t xpc_purpose = xpc_dictionary_get_value(request, "purpose"); 53 | if (!xpc_howto) { 54 | xpc_dictionary_set_int64(xreply, "error", EINVAL); 55 | xpc_dictionary_set_string(xreply, "errorDescription", "howto not supplied"); 56 | return; 57 | } 58 | uint64_t howto = xpc_uint64_get_value(xpc_howto); 59 | if (howto & RB2_USERREBOOT) { 60 | bool entitled = false; 61 | xpc_object_t value = xpc_connection_copy_entitlement_value(peer, "com.apple.private.xpc.launchd.userspace-reboot"); 62 | if (value && xpc_get_type(value) == XPC_TYPE_BOOL) { 63 | entitled = true; 64 | } 65 | if (value) xpc_release(value); 66 | if (!entitled) { 67 | xpc_dictionary_set_int64(xreply, "error", ENOENTITLEMENT); 68 | return; 69 | } 70 | } 71 | if ((howto & ITHINK_PURPOSE) && !xpc_purpose) { 72 | xpc_dictionary_set_int64(xreply, "error", EINVAL); 73 | xpc_dictionary_set_string(xreply, "errorDescription", "reboot flags included the purpose flag, but no purpose supplied in request"); 74 | return; 75 | } 76 | 77 | unmount("/Developer", MNT_FORCE); 78 | if (howto & ITHINK_PURPOSE) { 79 | ret = reboot3(howto, (uint32_t)xpc_uint64_get_value(xpc_purpose)); 80 | } else ret = reboot3(howto); 81 | 82 | if (ret) { 83 | xpc_dictionary_set_int64(xreply, "error", ret); 84 | return; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/payload/launchctl/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= 2 | DESTDIR ?= 3 | 4 | SRC := attach.c blame.c bootstrap.c enable.c env.c error.c examine.c kickstart.c 5 | SRC += kill.c launchctl.c limit.c list.c load.c manager.c plist.c print.c reboot.c 6 | SRC += remove.c runstats.c start_stop.c userswitch.c version.c xpc_helper.c 7 | 8 | ifeq ($(DEBUG),1) 9 | CFLAGS += -O0 -g -fsanitize=address,undefined -fno-omit-frame-pointer 10 | LDFLAGS += -O0 -g -fsanitize=address,undefined -fno-omit-frame-pointer 11 | endif 12 | 13 | all: launchctl 14 | 15 | launchctl: $(SRC:.c=.o) Info.plist launchctl.xml 16 | $(CC) $(LDFLAGS) $(filter %.o,$^) $(LOADLIBES) $(LDLIBS) -o $@ -Wl,-sectcreate,__TEXT,__info_plist,Info.plist 17 | ldid -Icom.apple.xpc.launchctl -Slaunchctl.xml -Cadhoc launchctl 18 | 19 | clean: 20 | rm -rf launchctl launchctl.dSYM $(SRC:%.c=%.o) 21 | 22 | install: launchctl 23 | install -d $(DESTDIR)$(PREFIX)/bin/ 24 | install -m755 launchctl $(DESTDIR)$(PREFIX)/bin/launchctl 25 | 26 | .PHONY: all clean install 27 | -------------------------------------------------------------------------------- /src/payload/launchctl/os_alloc_once.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * SPDX-License-Identifier: BSD-2-Clause 3 | * 4 | * Copyright (c) 2022 Procursus Team 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * 2. Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | #include 29 | #include 30 | 31 | #define OS_ALLOC_ONCE_KEY_LIBXPC 1 32 | 33 | struct xpc_global_data { 34 | uint64_t a; 35 | uint64_t xpc_flags; 36 | mach_port_t task_bootstrap_port; /* 0x10 */ 37 | #ifndef _64 38 | uint32_t padding; 39 | #endif 40 | xpc_object_t xpc_bootstrap_pipe; /* 0x18 */ 41 | }; 42 | 43 | #define OS_ALLOC_ONCE_KEY_MAX 100 44 | 45 | struct _os_alloc_once_s { 46 | long once; 47 | void *ptr; 48 | }; 49 | 50 | extern struct _os_alloc_once_s _os_alloc_once_table[]; 51 | -------------------------------------------------------------------------------- /src/payload/loader/Makefile: -------------------------------------------------------------------------------- 1 | OBJDIR = obj 2 | C_SRC = $(wildcard *.c) 3 | OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.c.o)) 4 | 5 | all: $(OBJS) 6 | 7 | $(OBJDIR): 8 | @mkdir -p $(OBJDIR) 9 | 10 | $(OBJDIR)/%.c.o: %.c $(OBJDIR) 11 | $(CC) $(CFLAGS) -c -o $@ $< 12 | 13 | clean: 14 | rm -rf obj 15 | 16 | .PHONY: all clean 17 | -------------------------------------------------------------------------------- /src/payload/loader/fixup_user_groups.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #ifdef HAVE_SYSTEMWIDE_IOSEXEC 14 | int fixup_pwgrp_file(char* sysfile, char* jbfile) { 15 | if (access(sysfile, F_OK) != 0) { 16 | fprintf(stderr, "cannot access %s\n", sysfile); 17 | return -1; 18 | } 19 | if (access(jbfile, F_OK) != 0) { 20 | fprintf(stderr, "cannot access %s\n", jbfile); 21 | return -1; 22 | } 23 | printf("fixing up %s with %s\n", jbfile, sysfile); 24 | int sys_fd, jb_fd; 25 | CHECK_ERROR((sys_fd = open(sysfile, O_RDONLY)) == -1, 1, "open %s", sysfile); 26 | CHECK_ERROR((jb_fd = open(jbfile, O_RDWR | O_APPEND)) == -1, 1, "open %s", jbfile); 27 | struct stat st; 28 | CHECK_ERROR(fstat(sys_fd, &st), 1, "fstat"); 29 | char* sys_file_buf = calloc(1, st.st_size+1); 30 | if (!sys_file_buf) { 31 | fprintf(stderr, "calloc failed\n"); 32 | spin(); 33 | } 34 | ssize_t didRead = read(sys_fd, sys_file_buf, st.st_size); 35 | printf("read %zd bytes from %s\n", didRead, sysfile); 36 | 37 | CHECK_ERROR(fstat(jb_fd, &st), 1, "fstat"); 38 | char* jb_file_buf = calloc(1, st.st_size+2); 39 | if (!jb_file_buf) { 40 | fprintf(stderr, "calloc failed\n"); 41 | spin(); 42 | } 43 | 44 | jb_file_buf[0] = '\n'; 45 | jb_file_buf[st.st_size+1] = '\0'; 46 | didRead = read(jb_fd, jb_file_buf+1, st.st_size); 47 | printf("read %zd bytes from %s\n", didRead, jbfile); 48 | puts("sysfile: "); 49 | puts(sys_file_buf); 50 | puts("jbfile: "); 51 | puts(jb_file_buf); 52 | 53 | char* entry; 54 | while ((entry = strsep(&sys_file_buf, "\n")) != NULL) { 55 | char* entry2 = strdup(entry); 56 | if (!entry2) { 57 | fprintf(stderr, "strdup() failed\n"); 58 | spin(); 59 | } 60 | char* name = strsep(&entry, ":"); 61 | if (!name) { 62 | free(entry2); 63 | continue; 64 | } 65 | if (name[0] == '#' || name[0] == '\0' || name[0] == ' ') continue; 66 | char newlinename[260]; 67 | snprintf(newlinename, 260, "\n%s:", name); 68 | if (strstr(jb_file_buf, newlinename) != NULL) continue; 69 | printf("missing name %s in %s\n", name, jbfile); 70 | CHECK_ERROR(lseek(jb_fd, SEEK_END, 0) == -1, 1, "lseek"); 71 | CHECK_ERROR(write_fdout(jb_fd, entry2, strlen(entry2)) != strlen(entry2), 1, "write"); 72 | CHECK_ERROR(write_fdout(jb_fd, "\n", 1) != 1, 1, "write"); 73 | free(entry2); 74 | } 75 | 76 | free(jb_file_buf); 77 | close(sys_fd); 78 | close(jb_fd); 79 | return 0; 80 | } 81 | 82 | int fixup_databases(void) { 83 | fixup_pwgrp_file("/etc/passwd", "/var/jb/etc/passwd"); 84 | fixup_pwgrp_file("/etc/master.passwd", "/var/jb/etc/master.passwd"); 85 | fixup_pwgrp_file("/etc/group", "/var/jb/etc/group"); 86 | return 0; 87 | } 88 | #endif 89 | -------------------------------------------------------------------------------- /src/payload/loader/load_etc_rc_d.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | extern char** environ; 17 | 18 | char* waitpid_decode(int status) { 19 | char* retbuf = calloc(50, 1); 20 | if (!retbuf) return NULL; 21 | 22 | if (WIFEXITED(status)) { 23 | snprintf(retbuf, 50, "exited with code %d", WEXITSTATUS(status)); 24 | } else if (WIFSIGNALED(status)) { 25 | if (WCOREDUMP(status)) 26 | snprintf(retbuf, 50, "terminated by signal %d (Core Dumped)", WTERMSIG(status)); 27 | else 28 | snprintf(retbuf, 50, "terminated by signal %d", WTERMSIG(status)); 29 | } else if (WIFSTOPPED(status)) { 30 | snprintf(retbuf, 50, "stopped by signal %d", WTERMSIG(status)); 31 | } 32 | 33 | return retbuf; 34 | 35 | } 36 | 37 | int load_etc_rc_d(uint64_t pflags) { 38 | if (pflags & (palerain_option_force_revert | palerain_option_safemode)) return 0; 39 | char* etcRcD; 40 | etcRcD = pflags & palerain_option_rootful ? "/etc/rc.d" : "/var/jb/etc/rc.d"; 41 | DIR* dir = opendir(etcRcD); 42 | if (!dir) return 0; 43 | struct dirent* d; 44 | while ((d = readdir(dir))) { 45 | if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; 46 | char path[PATH_MAX]; 47 | snprintf(path, PATH_MAX, "%s/%s", etcRcD, d->d_name); 48 | pid_t pid; 49 | int status; 50 | int ret = posix_spawn(&pid, path, NULL, NULL, (char*[]){ path, NULL }, environ); 51 | if (ret) { 52 | fprintf(stderr, "posix_spawn %s failed: %d (%s)\n", path, ret, strerror(ret)); 53 | } 54 | ret = waitpid(pid, &status, 0); 55 | if (ret == -1) { 56 | fprintf(stderr, "waitpid %d failed: %d (%s)\n", pid, errno, strerror(errno)); 57 | } else { 58 | char* desc = waitpid_decode(status); 59 | if (desc) { 60 | printf("%s %s\n", path, desc); 61 | free(desc); 62 | } 63 | } 64 | } 65 | closedir(dir); 66 | return 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/payload/loader/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | int loader_main(int argc, char* argv[]) { 19 | if (getuid() != 0) goto out; 20 | struct paleinfo pinfo; 21 | CHECK_ERROR(get_pinfo(&pinfo), 1, "read paleinfo failed"); 22 | uint32_t payload_options = 0; 23 | int ch; 24 | while ((ch = getopt(argc, argv, "usjft")) != -1) { 25 | switch(ch) { 26 | case 'u': 27 | payload_options |= payload_option_userspace_rebooted; 28 | break; 29 | case 's': 30 | payload_options |= payload_option_sysstatuscheck; 31 | break; 32 | case 'j': 33 | payload_options |= payload_option_launchdaemons; 34 | break; 35 | case 'f': 36 | payload_options |= payload_option_prelaunchd; 37 | break; 38 | case 't': 39 | payload_options |= payload_option_true; 40 | break; 41 | default: 42 | goto out; 43 | } 44 | } 45 | if (payload_options & payload_option_true) return 0; 46 | if (getenv("XPC_USERSPACE_REBOOTED")) payload_options |= payload_option_userspace_rebooted; 47 | if (payload_options & payload_option_prelaunchd) return prelaunchd(payload_options, &pinfo); 48 | else if (payload_options & payload_option_sysstatuscheck) return sysstatuscheck(payload_options, pinfo.flags); 49 | else if (payload_options & payload_option_launchdaemons) return launchdaemons(payload_options, pinfo.flags); 50 | out: 51 | fprintf(stderr, "this is a plinit internal utility, do not run\n"); 52 | return -1; 53 | } 54 | -------------------------------------------------------------------------------- /src/payload/loader/platform.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /* copied from plooshfinder */ 12 | bool macho_check(const void *buf) { 13 | uint32_t *buf_ptr = (uint32_t *) buf; 14 | uint32_t magic = buf_ptr[0]; 15 | 16 | if (magic == 0xfeedfacf || magic == 0xbebafeca) { 17 | return true; 18 | } 19 | 20 | return false; 21 | } 22 | 23 | /* this function retuns 0 on failure */ 24 | uint32_t macho_get_platform(const void *buf) { 25 | if (!macho_check(buf)) { 26 | errno = EINVAL; 27 | return 0; 28 | } 29 | 30 | const struct load_command *after_header = buf + sizeof(struct mach_header_64); 31 | const struct mach_header_64 *header = buf; 32 | 33 | for (uint32_t i = 0; i < header->ncmds; i++) { 34 | if (after_header->cmd == LC_BUILD_VERSION) { 35 | const struct build_version_command *cmd = (const struct build_version_command *) after_header; 36 | 37 | if (cmd->platform > 20) { 38 | errno = EINVAL; 39 | return 0; 40 | } 41 | 42 | return cmd->platform; 43 | } 44 | 45 | after_header = (const struct load_command *) ((const char *) after_header + after_header->cmdsize); 46 | } 47 | 48 | errno = ENOTSUP; 49 | return 0; 50 | } 51 | 52 | int get_platform(void) { 53 | static int cached_platform = -1; 54 | if (cached_platform != -1) return cached_platform; 55 | struct stat st; 56 | int ret = stat("/usr/lib/dyld", &st); 57 | if (ret) return ret; 58 | int fd_dyld = open("/usr/lib/dyld", O_RDONLY); 59 | if (fd_dyld == -1) return -1; 60 | void* dyld_buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd_dyld, 0); 61 | if (dyld_buf == MAP_FAILED) return -1; 62 | uint32_t platform = macho_get_platform(dyld_buf); 63 | if (!platform) return -1; 64 | munmap(dyld_buf, st.st_size); 65 | close(fd_dyld); 66 | cached_platform = (int)platform; 67 | return (int)platform; 68 | } 69 | -------------------------------------------------------------------------------- /src/payload/loader/remount.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int remount_rootfs(struct utsname* name_p) { 16 | struct statfs fs; 17 | int ret = statfs("/", &fs); 18 | if (ret) return ret; 19 | int mntflags = MNT_UPDATE; 20 | apfs_mount_args_t arg = { fs.f_mntfromname, 0, APFS_MOUNT_FILESYSTEM, 0, 0, { "" }, NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0 }; 21 | return mount(fs.f_fstypename, fs.f_mntonname, mntflags, &arg); 22 | } 23 | 24 | int remount_preboot(struct utsname* __unused name_p) { 25 | struct statfs fs; 26 | int ret = statfs("/private/preboot", &fs); 27 | if (ret == ENOENT) return 0; 28 | if (ret) return ret; 29 | int mntflags = MNT_UPDATE; 30 | apfs_mount_args_t arg = { fs.f_mntfromname, 0, APFS_MOUNT_FILESYSTEM, 0, 0, { "" }, NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0 }; 31 | return mount(fs.f_fstypename, fs.f_mntonname, mntflags, &arg); 32 | } 33 | 34 | int remount(void) { 35 | int ret; 36 | struct utsname name; 37 | ret = uname(&name); 38 | if (ret) { 39 | fprintf(stderr, "uname() failed: %d (%s)\n", errno, strerror(errno)); 40 | return -1; 41 | } 42 | if ( 43 | access("/.installed_palera1n", F_OK) == 0 || 44 | access("/.mount_rw", F_OK) == 0 || 45 | access("/.procursus_strapped", F_OK) == 0 46 | ) 47 | { 48 | ret = remount_rootfs(&name); 49 | if (ret) { 50 | fprintf(stderr, "mount(/) failed: %d (%s)\n", errno, strerror(errno)); 51 | return ret; 52 | } 53 | } 54 | ret = remount_preboot(&name); 55 | if (ret) { 56 | fprintf(stderr, "mount(/private/preboot) failed: %d (%s)\n", errno, strerror(errno)); 57 | return ret; 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /src/payload/loader/runcmd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern char** environ; 6 | 7 | int runCommand(char* argv[]) { 8 | fprintf(stderr, "Running command: `"); 9 | for (int i = 0; argv[i] != NULL; i++) { 10 | fprintf(stderr, "%s", argv[i]); 11 | if (argv[i+1] != NULL) fprintf(stderr, " "); 12 | } 13 | fprintf(stderr, "`\n"); 14 | pid_t pid; 15 | int ret = posix_spawn(&pid, argv[0], NULL, NULL, argv, environ); 16 | if (ret) return -1; 17 | int status; 18 | waitpid(pid, &status, 0); 19 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) return 0; 20 | return status; 21 | } 22 | -------------------------------------------------------------------------------- /src/payload/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | os_log_t palera1nd_log; 8 | 9 | _Noreturn void spin(void) { 10 | setenv("PATH", "/cores/binpack/usr/bin:/cores/binpack/usr/sbin:/cores/binpack/bin:/cores/binpack/sbin:/usr/bin:/usr/sbin:/bin:/sbin",1); 11 | if (access("/cores/binpack/bin/sh", F_OK) == 0) { 12 | runCommand((char*[]){ "/cores/binpack/bin/sh", "-i", NULL }); 13 | } 14 | while(1) sleep(86400); 15 | } 16 | 17 | int main(int argc, char* argv[]) { 18 | char* name = basename(argv[0]); 19 | if (!strcmp(name, "payload")) { 20 | palera1nd_log = os_log_create("com.apple.payload", "plooshInit payload"); 21 | return loader_main(argc, argv); 22 | } else if (!strcmp(name, "p1ctl")) { 23 | return p1ctl_main(argc, argv); 24 | } else if (!strcmp(name, "palera1nd")) { 25 | palera1nd_log = os_log_create("com.apple.payload", "palera1n Daemon"); 26 | return palera1nd_main(argc, argv); 27 | } else if (!strcmp(name, "bootscreend")) { 28 | return bootscreend_main(); 29 | } else { 30 | return -1; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/payload/p1ctl/Makefile: -------------------------------------------------------------------------------- 1 | OBJDIR = obj 2 | C_SRC = $(wildcard *.c) 3 | OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.c.o)) 4 | 5 | all: $(OBJS) 6 | 7 | $(OBJDIR): 8 | @mkdir -p $(OBJDIR) 9 | 10 | $(OBJDIR)/%.c.o: %.c $(OBJDIR) 11 | $(CC) $(CFLAGS) -U__nonnull -c -o $@ $< 12 | 13 | clean: 14 | rm -rf obj 15 | 16 | .PHONY: all clean 17 | -------------------------------------------------------------------------------- /src/payload/p1ctl/bootstrap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define PRINT_XPC(obj) do { char* desc=xpc_copy_description(obj);puts(desc);free(desc); } while (0) 8 | 9 | int bootstrap_main(int argc, char* argv[]) { 10 | int ch; 11 | bool no_password = false; 12 | char* password = NULL; 13 | char bootstrap[PATH_MAX]; 14 | while ((ch = getopt(argc, argv, "sS:")) != -1) { 15 | switch(ch) { 16 | case 's': 17 | no_password = true; 18 | break; 19 | case 'S': 20 | password = optarg; 21 | break; 22 | default: 23 | return -1; 24 | } 25 | } 26 | 27 | argc -= optind; 28 | argv += optind; 29 | 30 | if (no_password && password) { 31 | fprintf(stderr, "The -s and -S options are not allowed at the same time\n"); 32 | return -1; 33 | } 34 | 35 | if (argc < 1) { 36 | fprintf(stderr, "No bootstrap file specified\n"); 37 | return -1; 38 | } 39 | 40 | char* status = realpath(argv[0], bootstrap); 41 | if (!status) { 42 | fprintf(stderr, "Could not resolve path '%s', caused by: '%s'\n", argv[0], bootstrap); 43 | return -1; 44 | } 45 | 46 | printf("Will install bootstrap: %s\n", bootstrap); 47 | 48 | if (!no_password && !password) { 49 | printf("You need to set a new terminal password to use command line tools like \"sudo\".\n\n"); 50 | char* confirm = NULL; 51 | do { 52 | if (confirm) { 53 | printf("Passwords does not match or is empty, try again\n"); 54 | } 55 | password = getpass("New Password: "); 56 | confirm = getpass("Retype New Password: "); 57 | } while (strcmp(confirm, password) || confirm[0] == '\0'); 58 | } 59 | 60 | xpc_object_t xdict = xpc_dictionary_create(NULL, NULL, 0); 61 | 62 | xpc_dictionary_set_string(xdict, "path", bootstrap); 63 | xpc_dictionary_set_uint64(xdict, "cmd", JBD_CMD_DEPLOY_BOOTSTRAP); 64 | xpc_dictionary_set_string(xdict, "bootstrapper-name", "p1ctl"); 65 | xpc_dictionary_set_string(xdict, "bootstrapper-version", "3.0"); 66 | xpc_dictionary_set_bool(xdict, "no-password", no_password); 67 | 68 | if (password) xpc_dictionary_set_string(xdict, "password", password); 69 | xpc_object_t xreply = jailbreak_send_jailbreakd_message_with_reply_sync(xdict); 70 | xpc_release(xdict); 71 | if (xpc_get_type(xreply) == XPC_TYPE_ERROR) { 72 | char* desc = xpc_copy_description(xreply); 73 | fprintf(stderr, "jailbreakd upcall failed: %s\n", desc); 74 | fprintf(stderr, "%s\n", desc); 75 | free(desc); 76 | xpc_release(xreply); 77 | return -1; 78 | } 79 | 80 | int retval = print_jailbreakd_reply(xreply); 81 | xpc_release(xreply); 82 | return retval; 83 | } 84 | -------------------------------------------------------------------------------- /src/payload/p1ctl/libroot.c: -------------------------------------------------------------------------------- 1 | ../libroot/src/dyn.c -------------------------------------------------------------------------------- /src/payload/p1ctl/libroot_cmd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int libroot_main(int argc, char* argv[]) { 10 | if (argc < 2) { 11 | fprintf(stderr, "Error: no command specified.\n"); 12 | return -1; 13 | } 14 | if (strcasecmp(argv[1], "jbroot") == 0) { 15 | printf("%s\n", libroot_dyn_get_jbroot_prefix()); 16 | return 0; 17 | } else if (strcasecmp(argv[1], "root") == 0) { 18 | printf("%s\n", libroot_dyn_get_root_prefix()); 19 | return 0; 20 | } else if (strcasecmp(argv[1], "jbrand") == 0) { 21 | printf("%s\n", libroot_dyn_get_boot_uuid()); 22 | return 0; 23 | } 24 | 25 | fprintf(stderr, "Error: unknown command %s\n", argv[1]); 26 | 27 | return -1; 28 | } 29 | -------------------------------------------------------------------------------- /src/payload/p1ctl/obliterate.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int obliterate_main(int __unused argc, char* __unused argv[]) { 8 | P1CTL_UPCALL_JBD_WITH_ERR_CHECK(xreply, JBD_CMD_OBLITERATE_JAILBREAK); 9 | 10 | int retval = print_jailbreakd_reply(xreply); 11 | xpc_release(xreply); 12 | return retval; 13 | } 14 | -------------------------------------------------------------------------------- /src/payload/p1ctl/overwrite.c: -------------------------------------------------------------------------------- 1 | // 2 | // overwrite.c 3 | // dummy 4 | // 5 | // Created by Nick Chan on 30/1/2024. 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef DEV_BUILD 16 | 17 | int overwrite_main(int argc, char* argv[]) { 18 | mode_t mode = 0; 19 | bool has_mode = false; 20 | int ch; 21 | while ((ch = getopt(argc, argv, "m:")) != -1) { 22 | switch(ch) { 23 | case 'm': 24 | { 25 | has_mode = true; 26 | char* endptr; 27 | mode = strtoul(optarg, &endptr, 0); 28 | if (*endptr != '\0' || optarg[0] == '\0') { 29 | fprintf(stderr, "Error: invalid file mode supplied"); 30 | return -1; 31 | } 32 | } 33 | 34 | break; 35 | default: 36 | return -1; 37 | } 38 | } 39 | 40 | argc -= optind; 41 | argv += optind; 42 | 43 | if (argc < 1) { 44 | fprintf(stderr, "Error: No source file specified\n"); 45 | return -1; 46 | } 47 | 48 | if (argc < 2) { 49 | fprintf(stderr, "Error: No destination file specified\n"); 50 | return -1; 51 | } 52 | 53 | char source[PATH_MAX], destination[PATH_MAX]; 54 | realpath(argv[0], source); 55 | realpath(argv[1], destination); 56 | int fd = open(source, O_RDONLY); 57 | if (fd == -1) { 58 | fprintf(stderr, "Error: open source file failed: %d (%s)\n", errno, strerror(errno)); 59 | return errno; 60 | } 61 | ssize_t size = (ssize_t)lseek(fd, 0, SEEK_END); 62 | if (size == -1) { 63 | fprintf(stderr, "Error: lseek failed: %d (%s)\n", errno, strerror(errno)); 64 | close(fd); 65 | return errno; 66 | } 67 | uint8_t* data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); 68 | if (data == MAP_FAILED) { 69 | fprintf(stderr, "Error: mmap failed: %d (%s)\n", errno, strerror(errno)); 70 | close(fd); 71 | return errno; 72 | } 73 | 74 | xpc_object_t xdict = xpc_dictionary_create(NULL, NULL, 0); 75 | if (has_mode) xpc_dictionary_set_uint64(xdict, "mode", mode); 76 | xpc_dictionary_set_data(xdict, "data", data, size); 77 | xpc_dictionary_set_string(xdict, "path", destination); 78 | xpc_dictionary_set_uint64(xdict, "cmd", JBD_CMD_OVERWRITE_FILE_WITH_CONTENT); 79 | 80 | xpc_object_t xreply = jailbreak_send_jailbreakd_message_with_reply_sync(xdict); 81 | print_jailbreakd_reply(xreply); 82 | 83 | xpc_release(xreply); 84 | xpc_release(xdict); 85 | munmap(data, size); 86 | close(fd); 87 | 88 | return 0; 89 | } 90 | 91 | #endif 92 | 93 | -------------------------------------------------------------------------------- /src/payload/p1ctl/palera1n_flags.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int palera1n_flags_main(int argc, char* argv[]) { 8 | int ch; 9 | bool stringify = false, disk = false; 10 | while ((ch = getopt(argc, argv, "sd")) != -1) { 11 | switch(ch) { 12 | case 's': 13 | stringify = true; 14 | break; 15 | case 'd': 16 | disk = true; 17 | break; 18 | default: 19 | return -1; 20 | } 21 | } 22 | uint64_t pflags; 23 | if (!disk) { 24 | P1CTL_UPCALL_JBD_WITH_ERR_CHECK(xreply, JBD_CMD_GET_PINFO_FLAGS); 25 | uint64_t error = xpc_dictionary_get_int64(xreply, "error"); 26 | if (error) { 27 | fprintf(stderr, "get pinfo failed: %d (%s)\n", (int)error, xpc_strerror((int)error)); 28 | return -1; 29 | } 30 | 31 | pflags = xpc_dictionary_get_uint64(xreply, "flags"); 32 | xpc_release(xreply); 33 | } else { 34 | struct paleinfo pinfo; 35 | int ret = get_pinfo(&pinfo); 36 | if (ret) { 37 | fprintf(stderr, "get pinfo failed: %d (%s)\n", errno, strerror(errno)); 38 | return -1; 39 | } 40 | pflags = pinfo.flags; 41 | } 42 | if (!stringify) { 43 | printf("0x%llx\n", pflags); 44 | } else { 45 | for (uint64_t i = 0; i < 63; i++) { 46 | if (pflags & (UINT64_C(1) << i)) { 47 | printf("%s\n", jailbreak_str_pinfo_flag(pflags & (UINT64_C(1) << i))); 48 | } 49 | } 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /src/payload/p1ctl/preboot_path.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int preboot_path_main(int __unused argc, char* __unused argv[]) { 8 | int retval = 0; 9 | P1CTL_UPCALL_JBD_WITH_ERR_CHECK(xreply, JBD_CMD_GET_PINFO_FLAGS); 10 | const char* path = NULL; 11 | if ((path = xpc_dictionary_get_string(xreply, "path"))) { 12 | puts(path); 13 | } else { 14 | uint64_t error = xpc_dictionary_get_int64(xreply, "error"); 15 | if (error) { 16 | fprintf(stderr, "get preboot path failed: %d (%s)\n", (int)error, xpc_strerror((int)error)); 17 | return -1; 18 | } 19 | retval = -1; 20 | } 21 | xpc_release(xreply); 22 | return retval; 23 | } 24 | -------------------------------------------------------------------------------- /src/payload/p1ctl/print_jailbreakd_reply.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define PRINT_XPC(obj) do { char* desc=xpc_copy_description(obj);puts(desc);free(desc); } while (0) 6 | 7 | int print_jailbreakd_reply(xpc_object_t xreply) { 8 | int retval = 0; 9 | int error = (int)xpc_dictionary_get_int64(xreply, "error"); 10 | const char* _Nullable errorDescription = xpc_dictionary_get_string(xreply, "errorDescription"); 11 | if (error || errorDescription) { 12 | if (error && !errorDescription) { 13 | fprintf(stderr, "Error: %d (%s)\n", error, xpc_strerror(error)); 14 | } else if (!error && errorDescription) { 15 | fprintf(stderr, "Error: %s\n", errorDescription); 16 | } else if (error && errorDescription) { 17 | fprintf(stderr, "Error: %s: %d (%s)\n", errorDescription, error, xpc_strerror(error)); 18 | } 19 | retval = -1; 20 | } 21 | 22 | const char* _Nullable message; 23 | if ((message = xpc_dictionary_get_string(xreply, "message"))) { 24 | fprintf(stderr, "%s\n", message); 25 | } 26 | 27 | return retval; 28 | } 29 | -------------------------------------------------------------------------------- /src/payload/pinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int get_pinfo(struct paleinfo* pinfo_p) { 9 | int ret; 10 | ssize_t didRead; 11 | uint32_t ramdisk_size; 12 | 13 | int fd = open("/dev/rmd0", O_RDONLY); 14 | if (unlikely(fd == -1)) return -1; 15 | 16 | didRead = read(fd, &ramdisk_size, 4); 17 | if (unlikely(didRead == -1)) return -1; 18 | 19 | ret = (int)lseek(fd, (off_t)ramdisk_size, SEEK_SET); 20 | if (unlikely(ret == -1)) return -1; 21 | 22 | didRead = read(fd, pinfo_p, sizeof(struct paleinfo)); 23 | 24 | if (unlikely(didRead == -1)) return -1; 25 | else if (didRead != sizeof(struct paleinfo)) { 26 | errno = EAGAIN; 27 | return -1; 28 | } 29 | return 0; 30 | } 31 | 32 | int set_pinfo(struct paleinfo* pinfo_p) { 33 | int ret; 34 | ssize_t didRead; 35 | uint32_t ramdisk_size; 36 | 37 | int fd = open("/dev/rmd0", O_RDWR); 38 | if (fd == -1) return -1; 39 | 40 | didRead = read(fd, &ramdisk_size, 4); 41 | if (unlikely(didRead == -1)) return -1; 42 | 43 | ret = (int)lseek(fd, (off_t)ramdisk_size, SEEK_SET); 44 | if (unlikely(ret == -1)) return -1; 45 | 46 | ret = (int)write_fdout(fd, pinfo_p, sizeof(struct paleinfo)); 47 | close(fd); 48 | return ret; 49 | } 50 | -------------------------------------------------------------------------------- /src/payload_dylib/.gitignore: -------------------------------------------------------------------------------- 1 | payload.dylib 2 | -------------------------------------------------------------------------------- /src/payload_dylib/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -mappletvos-version-min=12.0 -std=gnu17 -fvisibility=hidden 2 | CFLAGS += -DHAVE_CRASHREPORTER 3 | LDFLAGS += -Wl,-dead_strip -Wno-unused-command-line-argument 4 | LDFLAGS += -install_name /cores/payload.dylib 5 | OBJDIR = obj 6 | C_SRC = $(wildcard *.c) 7 | OBJC_SRC = $(wildcard *.m) 8 | LIBS = -framework CoreFoundation ../libjailbreak/libjailbreak.a 9 | LIBS += ../libs/IOKit.tbd -framework Foundation 10 | OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.c.o)) $(patsubst %,$(OBJDIR)/%,$(OBJC_SRC:.m=.m.o)) 11 | 12 | ifeq ($(ASAN),1) 13 | CFLAGS += -fsanitize=address,undefined 14 | LDFLAGS += -rpath /cores 15 | endif 16 | 17 | all: payload.dylib 18 | 19 | $(OBJDIR): 20 | @mkdir -p $(OBJDIR) 21 | 22 | $(OBJDIR)/%.c.o: %.c $(OBJDIR) 23 | $(CC) $(CFLAGS) -c -o $@ $< 24 | 25 | $(OBJDIR)/%.m.o: %.m $(OBJDIR) 26 | $(CC) $(CFLAGS) -c -o $@ $< 27 | 28 | payload.dylib: $(OBJS) 29 | $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJS) -shared -o $@ 30 | $(DSYMUTIL) $@ 31 | ifneq ($(DEV_BUILD),1) 32 | $(STRIP) -x $@ 33 | endif 34 | $(LDID) -S $@ 35 | 36 | clean: 37 | rm -rf payload.dylib* payload.dylib.dSYM obj 38 | 39 | .PHONY: all clean 40 | -------------------------------------------------------------------------------- /src/payload_dylib/platform.c: -------------------------------------------------------------------------------- 1 | ../payload/loader/platform.c -------------------------------------------------------------------------------- /src/systemhook/.gitignore: -------------------------------------------------------------------------------- 1 | systemhook.dylib* 2 | -------------------------------------------------------------------------------- /src/systemhook/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -mappletvos-version-min=12.0 -std=gnu17 -fvisibility=hidden 2 | LDFLAGS += -Wl,-dead_strip -Wno-unused-command-line-argument 3 | LDFLAGS += -install_name /cores/binpack/usr/lib/systemhook.dylib 4 | OBJDIR = obj 5 | C_SRC = $(wildcard *.c) 6 | LIBS = -framework CoreFoundation ../libjailbreak/libjailbreak.a 7 | OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.c.o)) 8 | DYLIB_NAME = systemhook 9 | 10 | ifeq ($(ASAN),1) 11 | CFLAGS += -fsanitize=address,undefined 12 | LDFLAGS += -rpath /cores 13 | endif 14 | 15 | all: $(DYLIB_NAME).dylib 16 | 17 | $(OBJDIR): 18 | @mkdir -p $(OBJDIR) 19 | 20 | $(OBJDIR)/%.c.o: %.c $(OBJDIR) 21 | $(CC) $(CFLAGS) -c -o $@ $< 22 | 23 | $(DYLIB_NAME).dylib: $(OBJS) 24 | $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJS) -shared -o $(DYLIB_NAME).dylib 25 | $(DSYMUTIL) $@ 26 | ifneq ($(DEV_BUILD),1) 27 | $(STRIP) -x $@ 28 | endif 29 | $(LDID) -S $@ 30 | 31 | clean: 32 | rm -rf $(DYLIB_NAME).dylib* obj 33 | 34 | .PHONY: all clean 35 | -------------------------------------------------------------------------------- /src/systemhook/envbuf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int envbuf_len(const char *envp[]) 5 | { 6 | if (envp == NULL) return 1; 7 | 8 | int k = 0; 9 | const char *env = envp[k++]; 10 | while (env != NULL) { 11 | env = envp[k++]; 12 | } 13 | return k; 14 | } 15 | 16 | char **envbuf_mutcopy(const char *envp[]) 17 | { 18 | if (envp == NULL) return NULL; 19 | 20 | int len = envbuf_len(envp); 21 | char **envcopy = malloc(len * sizeof(char *)); 22 | 23 | for (int i = 0; i < len-1; i++) { 24 | envcopy[i] = strdup(envp[i]); 25 | } 26 | envcopy[len-1] = NULL; 27 | 28 | return envcopy; 29 | } 30 | 31 | void envbuf_free(char *envp[]) 32 | { 33 | if (envp == NULL) return; 34 | 35 | int len = envbuf_len((const char**)envp); 36 | for (int i = 0; i < len-1; i++) { 37 | free(envp[i]); 38 | } 39 | free(envp); 40 | } 41 | 42 | int envbuf_find(const char *envp[], const char *name) 43 | { 44 | if (envp) { 45 | unsigned long nameLen = strlen(name); 46 | int k = 0; 47 | const char *env = envp[k++]; 48 | while (env != NULL) { 49 | unsigned long envLen = strlen(env); 50 | if (envLen > nameLen) { 51 | if (!strncmp(env, name, nameLen)) { 52 | if (env[nameLen] == '=') { 53 | return k-1; 54 | } 55 | } 56 | } 57 | env = envp[k++]; 58 | } 59 | } 60 | return -1; 61 | } 62 | 63 | const char *envbuf_getenv(const char *envp[], const char *name) 64 | { 65 | if (envp) { 66 | unsigned long nameLen = strlen(name); 67 | int envIndex = envbuf_find(envp, name); 68 | if (envIndex >= 0) { 69 | return &envp[envIndex][nameLen+1]; 70 | } 71 | } 72 | return NULL; 73 | } 74 | 75 | void envbuf_setenv(char **envpp[], const char *name, const char *value) 76 | { 77 | if (envpp) { 78 | char **envp = *envpp; 79 | if (!envp) { 80 | // treat NULL as [NULL] 81 | envp = malloc(sizeof(const char *)); 82 | envp[0] = NULL; 83 | } 84 | 85 | char *envToSet = malloc(strlen(name)+strlen(value)+2); 86 | strcpy(envToSet, name); 87 | strcat(envToSet, "="); 88 | strcat(envToSet, value); 89 | 90 | int existingEnvIndex = envbuf_find((const char **)envp, name); 91 | if (existingEnvIndex >= 0) { 92 | // if already exists: deallocate old variable, then replace pointer 93 | free(envp[existingEnvIndex]); 94 | envp[existingEnvIndex] = envToSet; 95 | } 96 | else { 97 | // if doesn't exist yet: increase env buffer size, place at end 98 | int prevLen = envbuf_len((const char **)envp); 99 | *envpp = realloc(envp, (prevLen+1)*sizeof(const char *)); 100 | envp = *envpp; 101 | envp[prevLen-1] = envToSet; 102 | envp[prevLen] = NULL; 103 | } 104 | } 105 | } 106 | 107 | void envbuf_unsetenv(char **envpp[], const char *name) 108 | { 109 | if (envpp) { 110 | char **envp = *envpp; 111 | if (!envp) return; 112 | 113 | int existingEnvIndex = envbuf_find((const char **)envp, name); 114 | if (existingEnvIndex >= 0) { 115 | free(envp[existingEnvIndex]); 116 | int prevLen = envbuf_len((const char **)envp); 117 | for (int i = existingEnvIndex; i < (prevLen-1); i++) { 118 | envp[i] = envp[i+1]; 119 | } 120 | *envpp = realloc(envp, (prevLen-1)*sizeof(const char *)); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/systemhook/get_libiosexec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef HAVE_SYSTEMWIDE_IOSEXEC 7 | #define BIND_IOSEXEC_SYMBOL(sym) ie_ ## sym = dlsym(libiosexec_handle, "ie_" #sym) 8 | 9 | void* libiosexec_handle; 10 | int get_libiosexec(void) { 11 | if (has_libiosexec) return -1; 12 | if (libiosexec_handle) return 0; 13 | /* on rootful libiosexec will call into us => infinite recursion */ 14 | if (pflags & (palerain_option_force_revert | palerain_option_rootful)) return -1; 15 | const char* ie_path = JB_ROOT_PATH("/usr/lib/libiosexec.1.dylib"); 16 | if (access(ie_path, F_OK) != 0) return -1; 17 | libiosexec_handle = dlopen(ie_path, RTLD_NOW); 18 | if (!libiosexec_handle) return -1; 19 | 20 | BIND_IOSEXEC_SYMBOL(getusershell); 21 | BIND_IOSEXEC_SYMBOL(setusershell); 22 | BIND_IOSEXEC_SYMBOL(endusershell); 23 | BIND_IOSEXEC_SYMBOL(getpwent); 24 | BIND_IOSEXEC_SYMBOL(getpwnam); 25 | BIND_IOSEXEC_SYMBOL(getpwnam_r); 26 | BIND_IOSEXEC_SYMBOL(getpwuid); 27 | BIND_IOSEXEC_SYMBOL(getpwuid_r); 28 | BIND_IOSEXEC_SYMBOL(getpwuid_r); 29 | BIND_IOSEXEC_SYMBOL(setpassent); 30 | BIND_IOSEXEC_SYMBOL(setpwent); 31 | BIND_IOSEXEC_SYMBOL(endpwent); 32 | BIND_IOSEXEC_SYMBOL(user_from_uid); 33 | BIND_IOSEXEC_SYMBOL(getgrgid); 34 | BIND_IOSEXEC_SYMBOL(getgrgid_r); 35 | BIND_IOSEXEC_SYMBOL(getgrnam); 36 | BIND_IOSEXEC_SYMBOL(getgrnam_r); 37 | BIND_IOSEXEC_SYMBOL(getgrent); 38 | BIND_IOSEXEC_SYMBOL(setgrent); 39 | BIND_IOSEXEC_SYMBOL(endgrent); 40 | BIND_IOSEXEC_SYMBOL(group_from_gid); 41 | 42 | return 0; 43 | } 44 | 45 | #define ELLEKIT_PATH "/cores/binpack/usr/lib/libellekit.dylib" 46 | #define INIT_IOSEXEC_HOOK(func) MSHookFunction_p(func, func ## _hook, (void**)&orig_ ## func) 47 | 48 | void (*MSHookFunction_p)(void*, void*, void**); 49 | /* this function will be called by launchd */ 50 | SHOOK_EXPORT int init_libiosexec_hook_with_ellekit(void) { 51 | if (get_libiosexec()) return -1; 52 | void* ellekit_handle = dlopen(ELLEKIT_PATH, RTLD_NOW); 53 | if (!ellekit_handle) return -1; 54 | MSHookFunction_p = dlsym(ellekit_handle, "MSHookFunction"); 55 | if (!MSHookFunction_p) return -1; 56 | 57 | INIT_IOSEXEC_HOOK(getusershell); 58 | INIT_IOSEXEC_HOOK(setusershell); 59 | INIT_IOSEXEC_HOOK(endusershell); 60 | INIT_IOSEXEC_HOOK(getpwent); 61 | INIT_IOSEXEC_HOOK(getpwnam); 62 | INIT_IOSEXEC_HOOK(getpwnam_r); 63 | INIT_IOSEXEC_HOOK(getpwuid); 64 | INIT_IOSEXEC_HOOK(getpwuid_r); 65 | INIT_IOSEXEC_HOOK(setpassent); 66 | INIT_IOSEXEC_HOOK(setpwent); 67 | INIT_IOSEXEC_HOOK(endpwent); 68 | INIT_IOSEXEC_HOOK(user_from_uid); 69 | INIT_IOSEXEC_HOOK(getgrgid); 70 | INIT_IOSEXEC_HOOK(getgrgid_r); 71 | INIT_IOSEXEC_HOOK(getgrnam); 72 | INIT_IOSEXEC_HOOK(getgrnam_r); 73 | INIT_IOSEXEC_HOOK(getgrent); 74 | INIT_IOSEXEC_HOOK(setgrent); 75 | INIT_IOSEXEC_HOOK(endgrent); 76 | INIT_IOSEXEC_HOOK(group_from_gid); 77 | return 0; 78 | } 79 | #endif 80 | -------------------------------------------------------------------------------- /src/systemhook/getgrent.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef HAVE_SYSTEMWIDE_IOSEXEC 6 | struct group * 7 | getgrgid_hook(gid_t gid) { 8 | RET_TWC(getgrgid, gid); 9 | } 10 | 11 | int 12 | getgrgid_r_hook(gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct group **result) { 13 | RET_TWC(getgrgid_r, gid, grp, buffer, bufsize, result); 14 | } 15 | 16 | struct group * 17 | getgrnam_hook(const char *name) { 18 | RET_TWC(getgrnam, name); 19 | } 20 | 21 | int 22 | getgrnam_r_hook(const char *name, struct group *grp, char *buffer, size_t bufsize, struct group **result) { 23 | RET_TWC(getgrnam_r, name, grp, buffer, bufsize, result); 24 | } 25 | 26 | struct group * 27 | getgrent_hook(void) { 28 | RET_TWC(getgrent); 29 | } 30 | 31 | void 32 | setgrent_hook(void) { 33 | RET_TWC(setgrent); 34 | } 35 | 36 | void 37 | endgrent_hook(void) { 38 | RET_TWC(endgrent); 39 | } 40 | 41 | char* 42 | group_from_gid_hook(gid_t gid, int nouser) { 43 | RET_TWC(group_from_gid, gid, nouser); 44 | } 45 | 46 | DYLD_INTERPOSE(getgrgid_hook, getgrgid); 47 | DYLD_INTERPOSE(getgrgid_r_hook, getgrgid_r); 48 | DYLD_INTERPOSE(getgrnam_hook, getgrnam); 49 | DYLD_INTERPOSE(getgrnam_r_hook, getgrnam_r); 50 | DYLD_INTERPOSE(getgrent_hook, getgrent); 51 | DYLD_INTERPOSE(setgrent_hook, setgrent); 52 | DYLD_INTERPOSE(endgrent_hook, endgrent); 53 | DYLD_INTERPOSE(group_from_gid_hook, group_from_gid); 54 | #endif 55 | -------------------------------------------------------------------------------- /src/systemhook/getpwent.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef HAVE_SYSTEMWIDE_IOSEXEC 6 | struct passwd * 7 | getpwuid_hook(uid_t uid) { 8 | RET_TWC(getpwuid, uid); 9 | } 10 | 11 | int 12 | getpwuid_r_hook(uid_t uid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result) { 13 | RET_TWC(getpwuid_r, uid, pw, buffer, bufsize, result); 14 | } 15 | 16 | struct passwd * 17 | getpwnam_hook(const char *name) { 18 | RET_TWC(getpwnam, name); 19 | } 20 | 21 | int 22 | getpwnam_r_hook(const char *name, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result) { 23 | RET_TWC(getpwnam_r, name, pw, buffer, bufsize, result); 24 | } 25 | 26 | struct passwd * 27 | getpwent_hook(void) { 28 | RET_TWC(getpwent); 29 | } 30 | 31 | void 32 | setpwent_hook(void) { 33 | RET_TWC(setpwent); 34 | } 35 | 36 | void 37 | endpwent_hook(void) { 38 | RET_TWC(endpwent); 39 | } 40 | 41 | char* 42 | user_from_uid_hook(uid_t uid, int nouser) { 43 | RET_TWC(user_from_uid, uid, nouser); 44 | } 45 | 46 | int 47 | setpassent_hook(int stayopen) { 48 | RET_TWC(setpassent, stayopen); 49 | } 50 | 51 | DYLD_INTERPOSE(getpwuid_hook, getpwuid); 52 | DYLD_INTERPOSE(getpwuid_r_hook, getpwuid_r); 53 | DYLD_INTERPOSE(getpwnam_hook, getpwnam); 54 | DYLD_INTERPOSE(getpwnam_r_hook, getpwnam_r); 55 | DYLD_INTERPOSE(getpwent_hook, getpwent); 56 | DYLD_INTERPOSE(setpwent_hook, setpwent); 57 | DYLD_INTERPOSE(setpassent_hook ,setpassent); 58 | DYLD_INTERPOSE(endpwent_hook, endpwent); 59 | DYLD_INTERPOSE(user_from_uid_hook, user_from_uid); 60 | #endif 61 | -------------------------------------------------------------------------------- /src/systemhook/getusershell.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef HAVE_SYSTEMWIDE_IOSEXEC 6 | char* getusershell_hook(void) { 7 | RET_TWC(getusershell); 8 | } 9 | 10 | void endusershell_hook(void) { 11 | RET_TWC(endusershell); 12 | } 13 | 14 | void setusershell_hook(void) { 15 | RET_TWC(setusershell); 16 | } 17 | 18 | DYLD_INTERPOSE(getusershell_hook, getusershell); 19 | DYLD_INTERPOSE(endusershell_hook, endusershell); 20 | DYLD_INTERPOSE(setusershell_hook, setusershell); 21 | #endif 22 | -------------------------------------------------------------------------------- /src/universalhooks/.gitignore: -------------------------------------------------------------------------------- 1 | *.dSYM 2 | *.dylib 3 | -------------------------------------------------------------------------------- /src/universalhooks/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -mappletvos-version-min=14.0 -std=gnu17 -fvisibility=hidden 2 | LDFLAGS += -Wl,-dead_strip -Wno-unused-command-line-argument 3 | OBJDIR = obj 4 | C_SRC = $(wildcard *.c) 5 | OBJC_SRC = $(wildcard *.m) 6 | OBJCFLAGS = -fobjc-arc 7 | LIBS = -lobjc ../libs/IOKit.tbd -framework CoreFoundation ../libs/substrate.tbd 8 | LIBS += -framework Security -framework Foundation ../libjailbreak/libjailbreak.a 9 | OBJS = $(patsubst %,$(OBJDIR)/%,$(OBJC_SRC:.m=.m.o) $(C_SRC:.c=.c.o)) 10 | 11 | ifeq ($(ASAN),1) 12 | CFLAGS += -fsanitize=address,undefined 13 | LDFLAGS += -rpath /cores 14 | endif 15 | 16 | all: universalhooks.dylib 17 | 18 | $(OBJDIR): 19 | @mkdir -p $(OBJDIR) 20 | 21 | $(OBJDIR)/%.m.o: %.m $(OBJDIR) 22 | $(OBJC) $(CFLAGS) $(OBJCFLAGS) -c -o $@ $< 23 | 24 | $(OBJDIR)/%.c.o: %.c $(OBJDIR) 25 | $(CC) $(CFLAGS) -c -o $@ $< 26 | 27 | universalhooks.dylib: $(OBJS) $(ELLEKIT) 28 | $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJS) -shared \ 29 | -rpath /Library/Frameworks \ 30 | -rpath /usr/lib \ 31 | -rpath /cores/binpack/Library/Frameworks \ 32 | -rpath /cores/binpack/usr/lib \ 33 | -install_name /cores/binpack/usr/lib/universalhooks.dylib \ 34 | -o $@ 35 | $(DSYMUTIL) $@ 36 | ifneq ($(DEV_BUILD),1) 37 | $(STRIP) -x $@ 38 | endif 39 | $(LDID) -S $@ 40 | 41 | clean: 42 | rm -rf universalhooks.dylib* universalhooks.dylib.dSYM obj 43 | 44 | .PHONY: all clean 45 | 46 | -------------------------------------------------------------------------------- /src/universalhooks/headboard.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void headboardInit(void) { 5 | xpc_object_t xreply = jailbreak_send_jailbreakd_command_with_reply_sync(JBD_CMD_RESUME_PAYLOAD); 6 | xpc_release(xreply); 7 | return; 8 | } 9 | -------------------------------------------------------------------------------- /src/universalhooks/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | struct hook_info { 11 | const char* executablePath; 12 | void (*rootlessInit)(void); 13 | void (*rootfulInit)(void); 14 | void (*universalInit)(void); 15 | }; 16 | 17 | struct hook_info info[] = { 18 | { "/usr/libexec/securityd", NULL, NULL, securitydInit }, 19 | { "/usr/libexec/trustd", NULL, NULL, securitydInit }, 20 | { "/usr/libexec/watchdogd", NULL, NULL, watchdogdInit }, 21 | { "/System/Library/CoreServices/SpringBoard.app/SpringBoard", springboardInit, NULL, NULL }, 22 | { "/usr/libexec/lsd", lsdRootlessInit, NULL, lsdUniversalInit }, 23 | { "/usr/sbin/cfprefsd", cfprefsdInit, NULL, NULL }, 24 | { "/Applications/PineBoard.app/PineBoard", NULL, NULL, pineboardInit }, 25 | { "/Applications/HeadBoard.app/HeadBoard", NULL, NULL, headboardInit }, 26 | }; 27 | 28 | bool stringEndsWith(const char* str, const char* suffix) 29 | { 30 | if (!str || !suffix) { 31 | return false; 32 | } 33 | 34 | size_t str_len = strlen(str); 35 | size_t suffix_len = strlen(suffix); 36 | 37 | if (str_len < suffix_len) { 38 | return false; 39 | } 40 | 41 | return !strcmp(str + str_len - suffix_len, suffix); 42 | } 43 | 44 | uint64_t pflags; 45 | bool rootful; 46 | __attribute__((constructor))void universalhooks_main(void) { 47 | pflags = strtoull(getenv("JB_PINFO_FLAGS"), NULL, 0); 48 | rootful = pflags & palerain_option_rootful; 49 | 50 | char path[PATH_MAX]; 51 | uint32_t pathmax = PATH_MAX; 52 | if (_NSGetExecutablePath(path, &pathmax)) { 53 | return; 54 | } 55 | 56 | for (size_t i = 0; i < (sizeof(info) / sizeof(struct hook_info)); i++) { 57 | if (strcmp(path, info[i].executablePath)) continue; 58 | if (rootful && info[i].rootfulInit) info[i].rootfulInit(); 59 | else if (info[i].rootlessInit && !rootful) info[i].rootlessInit(); 60 | 61 | if (info[i].universalInit) info[i].universalInit(); 62 | } 63 | 64 | if (stringEndsWith(path, "/TrollStore.app/trollstorehelper")) { 65 | trollstorehelperInit(path); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/universalhooks/pineboard.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | @interface PBAppInfo : NSObject 7 | - (BOOL) isEnabled; 8 | @end 9 | 10 | @interface PBAppState : NSObject 11 | - (BOOL) isEnabledForApplicationWithIdentifier; 12 | @end 13 | 14 | @interface PBSMutableAppState : NSObject 15 | - (BOOL) isEnabled; 16 | @end 17 | 18 | void* PBAppInfo_isEnabled_orig; 19 | void* PBAppState_isEnabledForApplicationWithIdentifier_orig; 20 | void* PBSMutableAppState_isEnabled_orig; 21 | bool returns_true(void) { 22 | return true; 23 | } 24 | 25 | void pineboardInit(void) { 26 | Class PBAppInfo = objc_getClass("PBAppInfo"); 27 | if (PBAppInfo) { 28 | MSHookMessageEx(PBAppInfo, @selector(isEnabled), (IMP)&returns_true, (IMP*)&PBAppInfo_isEnabled_orig); 29 | } 30 | 31 | Class PBAppState = objc_getClass("PBAppState"); 32 | if (PBAppState) { 33 | MSHookMessageEx(PBAppState, @selector(isEnabledForApplicationWithIdentifier), (IMP)&returns_true, (IMP*)&PBAppState_isEnabledForApplicationWithIdentifier_orig); 34 | 35 | } 36 | 37 | Class PBSMutableAppState = objc_getClass("PBSMutableAppState"); 38 | if (PBSMutableAppState) { 39 | MSHookMessageEx(PBSMutableAppState, @selector(isEnabled), (IMP)&returns_true, (IMP*)&PBSMutableAppState_isEnabled_orig); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/universalhooks/securityd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //#ifdef DEV_BUILD 5 | #if 0 6 | bool SecIsInternalRelease(void); 7 | 8 | bool (*orig_SecIsInternalRelease)(void); 9 | bool new_SecIsInternalRelease(void) { 10 | return true; 11 | } 12 | 13 | #endif 14 | void securitydInit(void) { 15 | //#ifdef DEV_BUILD 16 | #if 0 17 | MSHookFunction(SecIsInternalRelease, (void*)new_SecIsInternalRelease, (void**)&orig_SecIsInternalRelease); 18 | #endif 19 | } 20 | -------------------------------------------------------------------------------- /src/universalhooks/springboard.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | @interface XBSnapshotContainerIdentity : NSObject 6 | @property (nonatomic, readonly, copy) NSString* bundleIdentifier; 7 | - (NSString*) snapshotContainerPath; 8 | @end 9 | 10 | @class XBSnapshotContainerIdentity; 11 | static NSString * (*orig_XBSnapshotContainerIdentity_snapshotContainerPath)(XBSnapshotContainerIdentity*, SEL); 12 | 13 | static NSString * XBSnapshotContainer_Identity_snapshotContainerPath(XBSnapshotContainerIdentity* self, SEL _cmd) { 14 | NSString* path = orig_XBSnapshotContainerIdentity_snapshotContainerPath(self, _cmd); 15 | 16 | if([path hasPrefix:@"/var/mobile/Library/SplashBoard/Snapshots/"] && ![self.bundleIdentifier hasPrefix:@"com.apple."]) { 17 | NSLog(@"redirect snapshotContainerPath %@: %@", self.bundleIdentifier, path); 18 | path = [NSString stringWithFormat:@"/var/jb/%@", path]; 19 | } 20 | 21 | return path; 22 | } 23 | 24 | void springboardInit(void) 25 | { 26 | Class class_XBSnapshotContainerIdentity = objc_getClass("XBSnapshotContainerIdentity"); 27 | MSHookMessageEx( 28 | class_XBSnapshotContainerIdentity, 29 | @selector(snapshotContainerPath), 30 | (IMP)&XBSnapshotContainer_Identity_snapshotContainerPath, 31 | (IMP*)&orig_XBSnapshotContainerIdentity_snapshotContainerPath 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/universalhooks/trollstorehelper.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int apply_coretrust_bypass_hook(__unused char* binaryPath) { 6 | return 0; 7 | } 8 | 9 | void trollstorehelperInit(char* executablePath) { 10 | MSImageRef trollstorehelper = MSGetImageByName(executablePath); 11 | void* apply_coretrust_bypass = MSFindSymbol(trollstorehelper, "_apply_coretrust_bypass"); 12 | bool (*isPlatformVulnerableToExploitType)(uint32_t) = MSFindSymbol(trollstorehelper, "_isPlatformVulnerableToExploitType"); 13 | 14 | if (isPlatformVulnerableToExploitType && apply_coretrust_bypass) { 15 | if (!isPlatformVulnerableToExploitType(UINT32_MAX)) { 16 | MSHookFunction(apply_coretrust_bypass, apply_coretrust_bypass_hook, NULL); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/universalhooks/watchdogd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | int64_t (*jbdswInterceptUserspacePanic)(const char *messageString) = NULL; 9 | kern_return_t (*IOConnectCallStructMethod_orig)(mach_port_t connection, uint32_t selector, const void *inputStruct, size_t inputStructCnt, void *outputStruct, size_t *outputStructCnt) = NULL; 10 | kern_return_t (*IOServiceOpen_orig)(io_service_t service, task_port_t owningTask, uint32_t type, io_connect_t *connect); 11 | mach_port_t gIOWatchdogConnection = MACH_PORT_NULL; 12 | 13 | kern_return_t IOServiceOpen_hook(io_service_t service, task_port_t owningTask, uint32_t type, io_connect_t *connect) 14 | { 15 | kern_return_t orig = IOServiceOpen_orig(service, owningTask, type, connect); 16 | if (orig == KERN_SUCCESS && connect) { 17 | if (IOObjectConformsTo(service, "IOWatchdog")) { 18 | // save mach port of IOWatchdog for check later 19 | gIOWatchdogConnection = *connect; 20 | } 21 | } 22 | return orig; 23 | } 24 | 25 | kern_return_t IOConnectCallStructMethod_hook(mach_port_t connection, uint32_t selector, const void *inputStruct, size_t inputStructCnt, void *outputStruct, size_t *outputStructCnt) 26 | { 27 | if (connection == gIOWatchdogConnection) { 28 | if (selector == 2) { 29 | return (int)jbdswInterceptUserspacePanic((const char *)inputStruct); 30 | } 31 | } 32 | return IOConnectCallStructMethod_orig(connection, selector, inputStruct, inputStructCnt, outputStruct, outputStructCnt); 33 | } 34 | 35 | void watchdogdInit(void) 36 | { 37 | jbdswInterceptUserspacePanic = dlsym(RTLD_DEFAULT, "jbdswInterceptUserspacePanic"); 38 | MSHookFunction(IOServiceOpen, (void *)&IOServiceOpen_hook, (void **)&IOServiceOpen_orig); 39 | MSHookFunction(IOConnectCallStructMethod, (void *)&IOConnectCallStructMethod_hook, (void **)&IOConnectCallStructMethod_orig); 40 | } 41 | -------------------------------------------------------------------------------- /tools/Makefile: -------------------------------------------------------------------------------- 1 | CC = $(CC_FOR_BUILD) 2 | CXX = $(CXX_FOR_BUILD) 3 | LD = $(LD_FOR_BUILD) 4 | CFLAGS = $(CFLAGS_FOR_BUILD) 5 | CXXFLAGS = $(CXXFLAGS_FOR_BUILD) 6 | LDFLAGS = $(LDFLAGS_FOR_BUILD) 7 | ROOT = $(shell pwd)/.. 8 | 9 | ifeq ($(UNAME),Darwin) 10 | # zlib is included in the SDK 11 | LIBDMG_HFSPLUS_CMAKE_FLAGS += -DZLIB_LIBRARY="-lz" -DZLIB_INCLUDE_DIR=" " 12 | endif 13 | 14 | export CC CXX LD CFLAGS CXXFLAGS LDFLAGS ROOT 15 | 16 | all: libdmg-hfsplus 17 | 18 | patch_dyld-test: 19 | $(MAKE) -C patch_dyld-test 20 | 21 | libdmg-hfsplus/build/Makefile: ../.git/modules/tools/libdmg-hfsplus/HEAD 22 | mkdir -p "libdmg-hfsplus/build" 23 | cd "libdmg-hfsplus/build" && cmake \ 24 | -DCMAKE_BUILD_TYPE=Release \ 25 | -DCMAKE_C_COMPILER="$(CC)" \ 26 | -DCMAKE_C_FLAGS="$(CFLAGS)" \ 27 | $(LIBDMG_HFSPLUS_CMAKE_FLAGS) \ 28 | "$(ROOT)/tools/libdmg-hfsplus" 29 | 30 | libdmg-hfsplus/build/hfs/hfsplus: libdmg-hfsplus/build/Makefile 31 | $(MAKE) -j1 -C "$(ROOT)/tools/libdmg-hfsplus/build" hfsplus 32 | 33 | libdmg-hfsplus/build/dmg/dmg: libdmg-hfsplus/build/Makefile 34 | $(MAKE) -j1 -C "$(ROOT)/tools/libdmg-hfsplus/build" dmg-bin 35 | 36 | libdmg-hfsplus: libdmg-hfsplus/build/hfs/hfsplus libdmg-hfsplus/build/dmg/dmg 37 | 38 | clean: 39 | rm -rf libdmg-hfsplus/build 40 | $(MAKE) -C patch_dyld-test clean 41 | 42 | .PHONY: libdmg-hfsplus patch_dyld-test clean all 43 | -------------------------------------------------------------------------------- /tools/patch_dyld-test/.gitignore: -------------------------------------------------------------------------------- 1 | patch_dyld-test 2 | dyld* 3 | -------------------------------------------------------------------------------- /tools/patch_dyld-test/Makefile: -------------------------------------------------------------------------------- 1 | C_SRC = main.c $(shell find $(ROOT)/src/fakedyld/patch_dyld -name '*.c') 2 | OBJDIR = obj 3 | CFLAGS = -Iinclude -I$(ROOT)/include/plooshfinder -I$(ROOT)/include 4 | CFLAGS += -flto=full -DDEV_BUILD=1 5 | LDFLAGS = -Wl,-dead_strip 6 | EXE = patch_dyld-test 7 | 8 | OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.o)) 9 | 10 | all: $(EXE) 11 | 12 | $(OBJDIR): 13 | mkdir $(OBJDIR) 14 | 15 | $(OBJDIR)/$(shell basename %.o): %.c $(OBJDIR) 16 | $(CC) $(CFLAGS) -c -o $(OBJDIR)/$(shell basename $@) $< 17 | 18 | $(EXE): $(OBJS) 19 | $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(patsubst %,$(OBJDIR)/%,$(shell basename $(OBJS))) -o patch_dyld-test 20 | 21 | clean: 22 | rm -rf $(EXE) $(OBJDIR) 23 | 24 | .PHONY: all clean 25 | -------------------------------------------------------------------------------- /tools/patch_dyld-test/include/fakedyld/fakedyld.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCK_FAKEDYLD_H 2 | #define MOCK_FAKEDYLD_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct { 11 | char* file_p; 12 | size_t file_len; 13 | } memory_file_handle_t; 14 | 15 | 16 | void patch_dyld(memory_file_handle_t* dyld_handle, int platform); 17 | void panic(const char* format, ...); 18 | 19 | #define LOG(...) do { printf(__VA_ARGS__); printf("\n"); } while (0) 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /tools/patch_dyld-test/include/patches: -------------------------------------------------------------------------------- 1 | ../../../include/patches -------------------------------------------------------------------------------- /tools/patch_dyld-test/include/plooshfinder: -------------------------------------------------------------------------------- 1 | ../../../include/plooshfinder -------------------------------------------------------------------------------- /tools/patch_dyld-test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "include/fakedyld/fakedyld.h" 6 | #include 7 | 8 | void panic(const char* format, ...) { 9 | va_list va; 10 | va_start(va, format); 11 | vfprintf(stderr, format, va); 12 | va_end(va); 13 | fprintf(stderr, "\n"); 14 | abort(); 15 | } 16 | 17 | void *dyld_buf; 18 | size_t dyld_len; 19 | 20 | int main(int argc, char **argv) { 21 | FILE *fp = NULL; 22 | char *outfile = NULL, *patch_dy = NULL; 23 | 24 | int ch; 25 | while ((ch = getopt(argc, (char * const *)argv, "o:")) != -1) { 26 | switch(ch) { 27 | case 'o': 28 | outfile = optarg; 29 | break; 30 | } 31 | } 32 | 33 | patch_dy = argv[0]; 34 | argc -= optind; 35 | argv += optind; 36 | 37 | 38 | if (argc < 1) { 39 | printf("Usage: %s -o \n", patch_dy); 40 | return -1; 41 | } 42 | 43 | 44 | for (uint32_t i = 0; argv[i] != NULL; i++) { 45 | char* infile = argv[i]; 46 | 47 | fp = fopen(infile, "rb"); 48 | if (!fp) { 49 | printf("Failed to open dyld!\n"); 50 | return -1; 51 | } 52 | 53 | fseek(fp, 0, SEEK_END); 54 | dyld_len = ftell(fp); 55 | fseek(fp, 0, SEEK_SET); 56 | 57 | dyld_buf = (void *)malloc(dyld_len); 58 | if (!dyld_buf) { 59 | printf("Out of memory while allocating region for dyld!\n"); 60 | fclose(fp); 61 | return -1; 62 | } 63 | 64 | fread(dyld_buf, 1, dyld_len, fp); 65 | fclose(fp); 66 | 67 | memory_file_handle_t handle; 68 | handle.file_p = dyld_buf; 69 | handle.file_len = dyld_len; 70 | 71 | printf("infile: %s\n", infile); 72 | patch_dyld(&handle, 2); 73 | 74 | if (outfile) { 75 | fp = fopen(outfile, "wb"); 76 | if(!fp) { 77 | printf("Failed to open output file!\n"); 78 | free(dyld_buf); 79 | return -1; 80 | } 81 | 82 | fwrite(dyld_buf, 1, dyld_len, fp); 83 | fflush(fp); 84 | fclose(fp); 85 | free(dyld_buf); 86 | } 87 | } 88 | 89 | 90 | return 0; 91 | } 92 | --------------------------------------------------------------------------------