├── .clang-format ├── dyldloader ├── format.sh ├── dyldloader ├── build.sh ├── real.entitlements └── dyldloader.c ├── littlespawn ├── format.sh ├── littlespawn.entitlements ├── build.sh └── littlespawn.c ├── lldb_new_ld ├── go.sh └── runit.lldb ├── lldb_original_ld ├── go.sh └── runit.lldb ├── who_let_the_dogs_out ├── .gitignore ├── format.sh ├── build.sh ├── real.entitlements ├── who_let_the_dogs_out.c └── IOKitHeader.h ├── resign_dyld ├── thepatch_full.o ├── build.sh ├── thepatch.c ├── patch_dyld.py ├── thepatch.s └── thepatch_full.s ├── resign_any_executable ├── set_to_arm64.py ├── build.sh └── WindowServer_arm64.entitlement ├── resign_dyld_cache ├── remove_signature.py ├── fixup_signature_size.py └── resign.sh └── launch_windowserver ├── wrap_windowserver └── com.apple.WindowServer.plist /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | -------------------------------------------------------------------------------- /dyldloader/format.sh: -------------------------------------------------------------------------------- 1 | exec clang-format -i *.c 2 | -------------------------------------------------------------------------------- /littlespawn/format.sh: -------------------------------------------------------------------------------- 1 | exec clang-format -i *.c 2 | -------------------------------------------------------------------------------- /lldb_new_ld/go.sh: -------------------------------------------------------------------------------- 1 | lldb /bin/bash -s runit.lldb 2 | -------------------------------------------------------------------------------- /lldb_original_ld/go.sh: -------------------------------------------------------------------------------- 1 | lldb /bin/bash -s runit.lldb 2 | -------------------------------------------------------------------------------- /who_let_the_dogs_out/.gitignore: -------------------------------------------------------------------------------- 1 | who_let_the_dogs_out 2 | -------------------------------------------------------------------------------- /who_let_the_dogs_out/format.sh: -------------------------------------------------------------------------------- 1 | exec clang-format -i *.c 2 | -------------------------------------------------------------------------------- /dyldloader/dyldloader: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowei/iOS-run-macOS-executables-tools/HEAD/dyldloader/dyldloader -------------------------------------------------------------------------------- /resign_dyld/thepatch_full.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuowei/iOS-run-macOS-executables-tools/HEAD/resign_dyld/thepatch_full.o -------------------------------------------------------------------------------- /resign_any_executable/set_to_arm64.py: -------------------------------------------------------------------------------- 1 | import sys 2 | with open(sys.argv[1], "r+b") as infile: 3 | infile.seek(4) 4 | infile.write(b"\x0c\x00\x00\x01\x00\x00\x00\x00") 5 | 6 | -------------------------------------------------------------------------------- /resign_dyld/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | lipo -thin arm64e /usr/lib/dyld -output dyld_macos 4 | python3 patch_dyld.py dyld_macos 5 | /usr/bin/codesign --force \ 6 | --sign 52F754C59CFAC59BC5794F5A3B523EFE0667D7EB \ 7 | --timestamp=none \ 8 | dyld_macos 9 | -------------------------------------------------------------------------------- /littlespawn/littlespawn.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.private.security.no-container 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /dyldloader/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | clang -Os -target arm64-apple-ios12.0 -Wall \ 4 | -isysroot "$(xcrun --sdk iphoneos --show-sdk-path)" \ 5 | -o dyldloader \ 6 | dyldloader.c 7 | /usr/bin/codesign --force \ 8 | --sign 52F754C59CFAC59BC5794F5A3B523EFE0667D7EB \ 9 | --timestamp=none \ 10 | --entitlements real.entitlements \ 11 | dyldloader 12 | -------------------------------------------------------------------------------- /littlespawn/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | clang -Os -target arm64-apple-ios12.0 -Wall \ 4 | -isysroot "$(xcrun --sdk iphoneos --show-sdk-path)" \ 5 | -o littlespawn \ 6 | littlespawn.c 7 | /usr/bin/codesign --force \ 8 | --sign 52F754C59CFAC59BC5794F5A3B523EFE0667D7EB \ 9 | --timestamp=none \ 10 | --entitlements littlespawn.entitlements \ 11 | littlespawn 12 | -------------------------------------------------------------------------------- /resign_dyld_cache/remove_signature.py: -------------------------------------------------------------------------------- 1 | # removes the existing code signature from a dyld cache 2 | import sys 3 | import struct 4 | with open(sys.argv[1], "r+b") as infile: 5 | indata = infile.read(0x40); 6 | codeoff = struct.unpack_from("Q", indata, 0x28)[0] 7 | print(hex(codeoff)) 8 | infile.truncate(codeoff) 9 | infile.seek(0x30) 10 | infile.write(b"\x00"*8) 11 | -------------------------------------------------------------------------------- /launch_windowserver/wrap_windowserver: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | xDYLD_SHARED_REGION=private xDYLD_SHARED_CACHE_DIR=/usr/local/zhuowei \ 3 | HOME=/var/root \ 4 | MallocScribble=1 \ 5 | MallocPreScribble=1 \ 6 | exec \ 7 | /usr/local/zhuowei/littlespawn \ 8 | /usr/local/zhuowei/SkyLight.framework/Versions/A/Resources/WindowServer_arm64 \ 9 | "$@" -virtualonly >/var/root/windowserver_log 2>&1 10 | -------------------------------------------------------------------------------- /resign_dyld/thepatch.c: -------------------------------------------------------------------------------- 1 | #include 2 | bool comparePath(char* a) { 3 | return a[0] == '/' && a[1] == 'u' && a[2] == 's' && a[3] == 'r' && 4 | a[4] == '/' && a[5] == 'l' && a[6] == 'o' && a[7] == 'c' && 5 | a[8] == 'a' && a[9] == 'l' && a[10] == '/' && a[11] == 'z' && 6 | a[12] == 'h' && a[13] == 'u' && a[14] == 'o' && a[15] == 'w' && 7 | a[16] == 'e' && a[17] == 'i'; 8 | } 9 | -------------------------------------------------------------------------------- /who_let_the_dogs_out/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | clang -Os -target arm64-apple-ios12.0 -Wall \ 4 | -isysroot "$(xcrun --sdk iphoneos --show-sdk-path)" \ 5 | -o who_let_the_dogs_out \ 6 | who_let_the_dogs_out.c \ 7 | -framework IOKit 8 | /usr/bin/codesign --force \ 9 | --sign 52F754C59CFAC59BC5794F5A3B523EFE0667D7EB \ 10 | --timestamp=none \ 11 | --entitlements real.entitlements \ 12 | who_let_the_dogs_out 13 | -------------------------------------------------------------------------------- /resign_dyld/patch_dyld.py: -------------------------------------------------------------------------------- 1 | import sys 2 | with open("thepatch_full.o", "rb") as infile: 3 | indata = infile.read() 4 | patch1 = indata[indata.find(b"GOT1") + 4:indata.find(b"END1")] 5 | patch2 = indata[indata.find(b"GOT2") + 4:indata.find(b"END2")] 6 | with open(sys.argv[1], "r+b") as infile: 7 | infile.seek(0x0000000000045ac8) 8 | infile.write(patch2) 9 | infile.seek(0x0000000000063994) 10 | infile.write(patch1) 11 | 12 | -------------------------------------------------------------------------------- /resign_dyld_cache/fixup_signature_size.py: -------------------------------------------------------------------------------- 1 | # sets the signature size 2 | import sys 3 | import struct 4 | with open(sys.argv[1], "r+b") as infile: 5 | indata = infile.read(0x40); 6 | codeoff = struct.unpack_from("Q", indata, 0x28)[0] 7 | print(hex(codeoff)) 8 | endloc = infile.seek(0, 2) # end 9 | sigsize = endloc - codeoff 10 | print(hex(endloc), hex(sigsize)) 11 | infile.seek(0x30) 12 | infile.write(struct.pack("Q", sigsize)) 13 | -------------------------------------------------------------------------------- /who_let_the_dogs_out/real.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.private.iowatchdog.user-access 6 | 7 | com.apple.security.iokit-user-client-class 8 | 9 | IOWatchdogUserClient 10 | RootDomainUserClient 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /lldb_original_ld/runit.lldb: -------------------------------------------------------------------------------- 1 | process connect connect://localhost:3335 2 | b dyld`dyld3::MachOFile::currentPlatform 3 | breakpoint command add 4 | print $x0=1 5 | print $pc=$lr 6 | c 7 | DONE 8 | b dyld`arc4random 9 | breakpoint command add 10 | print $x0=0 11 | print $pc=$lr 12 | c 13 | DONE 14 | breakpoint set -n sysctlbyname -c "strcmp((char*)$x0, "kern.osvariant_status") == 0" -o true 15 | breakpoint command add 16 | print $x0=0 17 | print *(unsigned long long*)$x1 = 0x70010000f388828a 18 | print $pc=$lr 19 | c 20 | DONE 21 | -------------------------------------------------------------------------------- /resign_dyld_cache/resign.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | python3 remove_signature.py "$1" 4 | /usr/bin/codesign --force \ 5 | --sign 52F754C59CFAC59BC5794F5A3B523EFE0667D7EB \ 6 | --timestamp=none \ 7 | "$1" 8 | python3 fixup_signature_size.py "$1" 9 | target_path="/usr/local/zhuowei/dyld_shared_cache_arm64e" 10 | sha256_filename="$(echo -n "$target_path" | shasum -a 256 | cut -f 1 -d " ")" 11 | codesign -d -vvv "$1" 2>&1 |grep "^CDHash="|cut -f 2 -d "="|xxd -r -p >"$sha256_filename" 12 | echo "put $sha256_filename in /taurine/cstmp/" 13 | -------------------------------------------------------------------------------- /resign_any_executable/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | lipo -thin arm64e -output "$2" "$1" 4 | chmod +w "$2" 5 | [[ -e "$2.entitlement" ]] || codesign -d --entitlement "$2.entitlement" "$2" 6 | python3 set_to_arm64.py "$2" 7 | if [[ -s "$2.entitlement" ]] 8 | then 9 | codesign --force \ 10 | --sign 52F754C59CFAC59BC5794F5A3B523EFE0667D7EB \ 11 | --timestamp=none \ 12 | --entitlement "$2.entitlement" \ 13 | "$2" 14 | else 15 | codesign --force \ 16 | --sign 52F754C59CFAC59BC5794F5A3B523EFE0667D7EB \ 17 | --timestamp=none \ 18 | "$2" 19 | fi 20 | -------------------------------------------------------------------------------- /dyldloader/real.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | platform-application 7 | 8 | get-task-allow 9 | 10 | com.apple.system-task-ports 11 | 12 | task_for_pid-allow 13 | 14 | com.apple.private.security.no-container 15 | 16 | com.apple.private.security.no-sandbox 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /who_let_the_dogs_out/who_let_the_dogs_out.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "IOKitHeader.h" 4 | // Disables iOS's kernel watchdog, so you can unload watchdogd. 5 | int main() { 6 | // based on watchdogd's entrypoint and power listener 7 | kern_return_t err; 8 | CFMutableDictionaryRef matching_dict = IOServiceMatching("IOWatchdog"); 9 | io_service_t service = 10 | IOServiceGetMatchingService(kIOMasterPortDefault, matching_dict); 11 | if (!service) { 12 | fprintf(stderr, "Failed to discover watchdog service\n"); 13 | return 1; 14 | } 15 | io_connect_t connection; 16 | err = IOServiceOpen(service, mach_task_self_, /*type=*/1, &connection); 17 | if (err) { 18 | fprintf(stderr, "IOServiceOpen failed with error: %s\n", 19 | mach_error_string(err)); 20 | return 1; 21 | } 22 | err = IOConnectCallScalarMethod(connection, 3, 0, 0, 0, 0); 23 | if (err) { 24 | fprintf(stderr, "Failed to disable watchdog: %s\n", mach_error_string(err)); 25 | return 1; 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /littlespawn/littlespawn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | extern char** environ; 8 | int main(int argc, char** argv) { 9 | printf("%d\n", getpid()); 10 | // https://github.com/coolstar/electra/issues/53#issuecomment-359287851 11 | if (getenv("xDYLD_SHARED_CACHE_DIR")) { 12 | setenv("DYLD_SHARED_CACHE_DIR", getenv("xDYLD_SHARED_CACHE_DIR"), 1); 13 | } 14 | if (getenv("xDYLD_SHARED_REGION")) { 15 | setenv("DYLD_SHARED_REGION", getenv("xDYLD_SHARED_REGION"), 1); 16 | } 17 | if (getenv("xDYLD_ROOT_PATH")) { 18 | setenv("DYLD_ROOT_PATH", getenv("xDYLD_ROOT_PATH"), 1); 19 | } 20 | posix_spawnattr_t attr; 21 | posix_spawnattr_init(&attr); 22 | posix_spawnattr_setflags(&attr, 23 | POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETEXEC); 24 | 25 | int ret = posix_spawnp(NULL, argv[1], NULL, &attr, &argv[1], environ); 26 | if (ret) { 27 | fprintf(stderr, "failed to exec %s: %s\n", argv[1], strerror(errno)); 28 | } 29 | return 1; 30 | } 31 | -------------------------------------------------------------------------------- /who_let_the_dogs_out/IOKitHeader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // copied from IOKitLib.h 3 | 4 | #include 5 | #include 6 | 7 | typedef mach_port_t io_object_t; 8 | 9 | typedef io_object_t io_connect_t; 10 | typedef io_object_t io_service_t; 11 | 12 | extern mach_port_t kIOMasterPortDefault; 13 | 14 | CFMutableDictionaryRef 15 | IOServiceMatching( 16 | const char * name ) CF_RETURNS_RETAINED; 17 | 18 | io_service_t 19 | IOServiceGetMatchingService( 20 | mach_port_t masterPort, 21 | CFDictionaryRef matching CF_RELEASES_ARGUMENT); 22 | 23 | kern_return_t 24 | IOServiceOpen( 25 | io_service_t service, 26 | task_port_t owningTask, 27 | uint32_t type, 28 | io_connect_t * connect ); 29 | 30 | kern_return_t 31 | IOServiceOpen( 32 | io_service_t service, 33 | task_port_t owningTask, 34 | uint32_t type, 35 | io_connect_t * connect ); 36 | 37 | kern_return_t 38 | IOConnectCallScalarMethod( 39 | mach_port_t connection, // In 40 | uint32_t selector, // In 41 | const uint64_t *input, // In 42 | uint32_t inputCnt, // In 43 | uint64_t *output, // Out 44 | uint32_t *outputCnt) // In/Out 45 | AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; 46 | -------------------------------------------------------------------------------- /launch_windowserver/com.apple.WindowServer.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Label 6 | com.apple.WindowServer 7 | MachServices 8 | 9 | com.apple.iohideventsystem 10 | 11 | ResetAtClose 12 | 13 | 14 | com.apple.windowserver 15 | 16 | com.apple.windowserver.active 17 | 18 | HideUntilCheckIn 19 | 20 | 21 | com.apple.windowserver.watchdog 22 | 23 | HideUntilCheckIn 24 | 25 | 26 | com.apple.CARenderServer 27 | 28 | HideUntilCheckIn 29 | 30 | 31 | com.apple.CoreDisplay.master 32 | 33 | HideUntilCheckIn 34 | 35 | 36 | com.apple.CoreDisplay.Notification 37 | 38 | HideUntilCheckIn 39 | 40 | ResetAtClose 41 | 42 | 43 | com.apple.VirtualDisplay 44 | 45 | HideUntilCheckIn 46 | 47 | 48 | 49 | POSIXSpawnType 50 | Interactive 51 | ProgramArguments 52 | 53 | 54 | /usr/bin/dash 55 | /usr/local/zhuowei/wrap_windowserver 56 | -daemon 57 | 58 | 59 | EnablePressuredExit 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /lldb_new_ld/runit.lldb: -------------------------------------------------------------------------------- 1 | target modules search-paths add / /Volumes/F32THICKHD/macos114arm64e/out 2 | process connect connect://localhost:3335 3 | breakpoint set -n sysctlbyname -c "(int)strcmp((char*)$x0, \"kern.osvariant_status\") == 0" -o true 4 | breakpoint command add 5 | print $x0=0 6 | print *(unsigned long long*)$x1 = 0x70010000f388828a 7 | print $pc=$lr 8 | c 9 | DONE 10 | b SLXServer 11 | b exit 12 | #b _os_log_error_impl 13 | #breakpoint command add 14 | #print (char*)$x3 15 | #c 16 | #DONE 17 | #b _os_log_debug_impl 18 | #breakpoint command add 19 | #print (char*)$x3 20 | #c 21 | #DONE 22 | #b _os_log_impl 23 | #breakpoint command add 24 | #print (char*)$x3 25 | #c 26 | #DONE 27 | #b mkdir 28 | b sandbox_init_with_parameters 29 | breakpoint command add 30 | print $x0=0 31 | print $pc=$lr 32 | c 33 | DONE 34 | breakpoint set -n confstr -c "$x0 == 0x10002" 35 | breakpoint command add 36 | print $x0=9 37 | print (void)strcpy((void*)$x1, "/var/tmp") 38 | print $pc=$lr 39 | c 40 | DONE 41 | breakpoint set -n IOServiceMatching -c "(int)strcmp((char*)$x0, \"IOAccelerator\") == 0" -o true 42 | breakpoint command add 43 | print $x0=(unsigned long long)strcpy((void*)malloc(0x1000), "IOAcceleratorES"); 44 | c 45 | DONE 46 | breakpoint set -n IOServiceNameMatching -c "(int)strcmp((char*)$x0, \"IOSurfaceRoot\") == 0" -o true 47 | breakpoint command add 48 | print $x0=(unsigned long long)strcpy((void*)malloc(0x1000), "IOCoreSurfaceRoot"); 49 | c 50 | DONE 51 | b IOServiceMatching 52 | b IOServiceNameMatching 53 | b gpu_bundle_find_trusted 54 | breakpoint command add 55 | print $x0=0 56 | print (void*)strcpy((void*)$x1, "/usr/local/zhuowei/AGXMetal13_3.bundle") 57 | print $pc=$lr 58 | DONE 59 | b +[NSBundle bundleWithPath:] 60 | b -[NSBundle load] 61 | b -[CAWindowServer _detectDisplays] 62 | b IOHIDEventSystemCreate 63 | -------------------------------------------------------------------------------- /resign_dyld/thepatch.s: -------------------------------------------------------------------------------- 1 | .section __TEXT,__text,regular,pure_instructions 2 | .build_version ios, 12, 0 sdk_version 11, 1 3 | .globl _comparePath ; -- Begin function comparePath 4 | .p2align 2 5 | _comparePath: ; @comparePath 6 | .cfi_startproc 7 | ; %bb.0: 8 | ldrb w8, [x0] 9 | cmp w8, #47 ; =47 10 | b.ne LBB0_18 11 | ; %bb.1: 12 | ldrb w8, [x0, #1] 13 | cmp w8, #117 ; =117 14 | b.ne LBB0_18 15 | ; %bb.2: 16 | ldrb w8, [x0, #2] 17 | cmp w8, #115 ; =115 18 | b.ne LBB0_18 19 | ; %bb.3: 20 | ldrb w8, [x0, #3] 21 | cmp w8, #114 ; =114 22 | b.ne LBB0_18 23 | ; %bb.4: 24 | ldrb w8, [x0, #4] 25 | cmp w8, #47 ; =47 26 | b.ne LBB0_18 27 | ; %bb.5: 28 | ldrb w8, [x0, #5] 29 | cmp w8, #108 ; =108 30 | b.ne LBB0_18 31 | ; %bb.6: 32 | ldrb w8, [x0, #6] 33 | cmp w8, #111 ; =111 34 | b.ne LBB0_18 35 | ; %bb.7: 36 | ldrb w8, [x0, #7] 37 | cmp w8, #99 ; =99 38 | b.ne LBB0_18 39 | ; %bb.8: 40 | ldrb w8, [x0, #8] 41 | cmp w8, #97 ; =97 42 | b.ne LBB0_18 43 | ; %bb.9: 44 | ldrb w8, [x0, #9] 45 | cmp w8, #108 ; =108 46 | b.ne LBB0_18 47 | ; %bb.10: 48 | ldrb w8, [x0, #10] 49 | cmp w8, #47 ; =47 50 | b.ne LBB0_18 51 | ; %bb.11: 52 | ldrb w8, [x0, #11] 53 | cmp w8, #122 ; =122 54 | b.ne LBB0_18 55 | ; %bb.12: 56 | ldrb w8, [x0, #12] 57 | cmp w8, #104 ; =104 58 | b.ne LBB0_18 59 | ; %bb.13: 60 | ldrb w8, [x0, #13] 61 | cmp w8, #117 ; =117 62 | b.ne LBB0_18 63 | ; %bb.14: 64 | ldrb w8, [x0, #14] 65 | cmp w8, #111 ; =111 66 | b.ne LBB0_18 67 | ; %bb.15: 68 | ldrb w8, [x0, #15] 69 | cmp w8, #119 ; =119 70 | b.ne LBB0_18 71 | ; %bb.16: 72 | ldrb w8, [x0, #16] 73 | cmp w8, #101 ; =101 74 | b.ne LBB0_18 75 | ; %bb.17: 76 | ldrb w8, [x0, #17] 77 | cmp w8, #105 ; =105 78 | cset w0, eq 79 | ret 80 | LBB0_18: 81 | mov w0, #0 82 | ret 83 | .cfi_endproc 84 | ; -- End function 85 | .subsections_via_symbols 86 | -------------------------------------------------------------------------------- /resign_dyld/thepatch_full.s: -------------------------------------------------------------------------------- 1 | .section __TEXT,__text,regular,pure_instructions 2 | .build_version ios, 12, 0 sdk_version 11, 1 3 | .globl _comparePath ; -- Begin function comparePath 4 | .p2align 2 5 | ; patch stat64 to return error if path does not begin with /usr/local/zhuowei 6 | totalstart: 7 | .space 0x0000000000045ac8 - 4 8 | ; __ZN5dyld37closure19LaunchClosureWriterC2EPKNS0_10ImageArrayE 9 | .ascii "GOT2" 10 | comparePath: ; @comparePath 11 | LcomparePath: 12 | .cfi_startproc 13 | ; %bb.0: 14 | ldrb w8, [x0] 15 | cmp w8, #47 ; =47 16 | b.ne LBB0_18 17 | ; %bb.1: 18 | ldrb w8, [x0, #1] 19 | cmp w8, #117 ; =117 20 | b.ne LBB0_18 21 | ; %bb.2: 22 | ldrb w8, [x0, #2] 23 | cmp w8, #115 ; =115 24 | b.ne LBB0_18 25 | ; %bb.3: 26 | ldrb w8, [x0, #3] 27 | cmp w8, #114 ; =114 28 | b.ne LBB0_18 29 | ; %bb.4: 30 | ldrb w8, [x0, #4] 31 | cmp w8, #47 ; =47 32 | b.ne LBB0_18 33 | ; %bb.5: 34 | ldrb w8, [x0, #5] 35 | cmp w8, #108 ; =108 36 | b.ne LBB0_18 37 | ; %bb.6: 38 | ldrb w8, [x0, #6] 39 | cmp w8, #111 ; =111 40 | b.ne LBB0_18 41 | ; %bb.7: 42 | ldrb w8, [x0, #7] 43 | cmp w8, #99 ; =99 44 | b.ne LBB0_18 45 | ; %bb.8: 46 | ldrb w8, [x0, #8] 47 | cmp w8, #97 ; =97 48 | b.ne LBB0_18 49 | ; %bb.9: 50 | ldrb w8, [x0, #9] 51 | cmp w8, #108 ; =108 52 | b.ne LBB0_18 53 | ; %bb.10: 54 | ldrb w8, [x0, #10] 55 | cmp w8, #47 ; =47 56 | b.ne LBB0_18 57 | ; %bb.11: 58 | ldrb w8, [x0, #11] 59 | cmp w8, #122 ; =122 60 | b.ne LBB0_18 61 | ; %bb.12: 62 | ldrb w8, [x0, #12] 63 | cmp w8, #104 ; =104 64 | b.ne LBB0_18 65 | ; %bb.13: 66 | ldrb w8, [x0, #13] 67 | cmp w8, #117 ; =117 68 | b.ne LBB0_18 69 | ; %bb.14: 70 | ldrb w8, [x0, #14] 71 | cmp w8, #111 ; =111 72 | b.ne LBB0_18 73 | ; %bb.15: 74 | ldrb w8, [x0, #15] 75 | cmp w8, #119 ; =119 76 | b.ne LBB0_18 77 | ; %bb.16: 78 | ldrb w8, [x0, #16] 79 | cmp w8, #101 ; =101 80 | b.ne LBB0_18 81 | ; %bb.17: 82 | ldrb w8, [x0, #17] 83 | cmp w8, #105 ; =105 84 | b.ne LBB0_18 85 | ; yes, it does; return back 86 | mov x16, #338 87 | b Lstat64_returnhere 88 | LBB0_18: 89 | ; does not begin with /usr/local/zhuowei 90 | mov x0, #1 91 | ret 92 | .ascii "END2" 93 | .org 0x0000000000063994 - 4 94 | .ascii "GOT1" 95 | stat64_head: 96 | b LcomparePath 97 | Lstat64_returnhere: 98 | .ascii "END1" 99 | ; -- End function 100 | .cfi_endproc 101 | .subsections_via_symbols 102 | -------------------------------------------------------------------------------- /resign_any_executable/WindowServer_arm64.entitlement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.QuartzCore.debug 6 | 7 | com.apple.afk.user 8 | 9 | com.apple.appledfr.client 10 | 11 | com.apple.bluetooth.nsxpc 12 | 13 | com.apple.hid.manager.user-access-device 14 | 15 | com.apple.hid.manager.user-access-privileged 16 | 17 | com.apple.hid.multitouch.user-access 18 | 19 | com.apple.hid.system.server-access 20 | 21 | com.apple.hid.system.user-access-service 22 | 23 | com.apple.hidpreferences.privileged 24 | 25 | com.apple.iohideventsystem.server 26 | 27 | com.apple.keystore.sik.access 28 | 29 | com.apple.private.AmbientDisplay.messaging 30 | 31 | com.apple.private.allow-explicit-graphics-priority 32 | 33 | com.apple.private.colorsync.privileged 34 | 35 | com.apple.private.dfr.brightness-access 36 | 37 | com.apple.private.gpuwrangler 38 | 39 | com.apple.private.graphics-restart-no-kill 40 | 41 | com.apple.private.hid.client.admin 42 | 43 | com.apple.private.hid.client.event-monitor 44 | 45 | com.apple.private.iokit.displayservice 46 | 47 | com.apple.private.iokit.rootdomain-set-property 48 | 49 | com.apple.private.iosurfaceinfo 50 | 51 | com.apple.private.kernel.work-interval 52 | 53 | com.apple.private.tcc.allow 54 | 55 | kTCCServiceAccessibility 56 | kTCCServiceListenEvent 57 | kTCCServicePostEvent 58 | kTCCServiceScreenCapture 59 | 60 | com.apple.private.tcc.manager 61 | 62 | com.apple.private.xpc.launchd.per-user-lookup 63 | 64 | com.apple.runningboard.assertions.fuseboard 65 | 66 | com.apple.runningboard.process-state 67 | 68 | com.apple.security.exception.mach-lookup.global-name 69 | 70 | com.apple.backlightd 71 | 72 | 73 | com.apple.private.security.no-container 74 | 75 | platform-application 76 | 77 | 78 | com.apple.security.iokit-user-client-class 79 | 80 | AGXCommandQueue 81 | AGXDevice 82 | AGXDeviceUserClient 83 | AGXSharedUserClient 84 | AppleJPEGDriverUserClient 85 | IOAccelContext 86 | IOAccelContext2 87 | IOAccelDevice 88 | IOAccelDevice2 89 | IOAccelSharedUserClient 90 | IOAccelSharedUserClient2 91 | IOAccelSubmitter2 92 | IOMobileFramebufferUserClient 93 | IOSurfaceAcceleratorClient 94 | IOSurfaceRootUserClient 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /dyldloader/dyldloader.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 | void set_all_images_offset_maybe(struct segment_command_64* seg_cmd, 16 | size_t* all_images_offset) { 17 | struct section_64* sections = (void*)seg_cmd + sizeof(*seg_cmd); 18 | for (unsigned int index = 0; index < seg_cmd->nsects; index++) { 19 | struct section_64* section = §ions[index]; 20 | if (!strncmp(section->sectname, "__all_image_info", 21 | sizeof(section->sectname))) { 22 | *all_images_offset = section->addr; 23 | } 24 | } 25 | } 26 | 27 | size_t get_address_space_size(void* executable_region, 28 | size_t* all_images_offset, size_t* sigcmd_dataoff, 29 | size_t* sigcmd_datasize) { 30 | struct mach_header_64* mh = executable_region; 31 | struct load_command* cmd = executable_region + sizeof(struct mach_header_64); 32 | 33 | *all_images_offset = 0; 34 | 35 | uint64_t min_addr = ~0; 36 | uint64_t max_addr = 0; 37 | for (unsigned int index = 0; index < mh->ncmds; index++) { 38 | switch (cmd->cmd) { 39 | case LC_SEGMENT_64: { 40 | struct segment_command_64* seg_cmd = (struct segment_command_64*)cmd; 41 | min_addr = MIN(min_addr, seg_cmd->vmaddr); 42 | max_addr = MAX(max_addr, seg_cmd->vmaddr + seg_cmd->vmsize); 43 | if (!strncmp(seg_cmd->segname, "__DATA", sizeof(seg_cmd->segname))) { 44 | set_all_images_offset_maybe(seg_cmd, all_images_offset); 45 | } 46 | break; 47 | } 48 | case LC_CODE_SIGNATURE: { 49 | struct linkedit_data_command* signature_cmd = 50 | (struct linkedit_data_command*)cmd; 51 | *sigcmd_dataoff = signature_cmd->dataoff; 52 | *sigcmd_datasize = signature_cmd->datasize; 53 | } 54 | } 55 | cmd = (struct load_command*)((char*)cmd + cmd->cmdsize); 56 | } 57 | return max_addr - min_addr; 58 | } 59 | 60 | #ifdef __arm64__ 61 | static const cpu_type_t kPreferredCpuType = CPU_TYPE_ARM64; 62 | #else 63 | static const cpu_type_t kPreferredCpuType = CPU_TYPE_X86_64; 64 | #endif 65 | 66 | off_t get_fat_offset(void* fat_region) { 67 | struct fat_header* fat_header = fat_region; 68 | if (fat_header->magic != FAT_CIGAM) { 69 | fprintf(stderr, "Not a FAT executable. Assume raw.\n"); 70 | return 0; 71 | } 72 | struct fat_arch* fat_arches = fat_region + sizeof(struct fat_header); 73 | for (unsigned int index = 0; index < ntohl(fat_header->nfat_arch); index++) { 74 | struct fat_arch* fat_arch = &fat_arches[index]; 75 | if (ntohl(fat_arch->cputype) == kPreferredCpuType) { 76 | return ntohl(fat_arch->offset); 77 | } 78 | } 79 | fprintf(stderr, "No preferred slice\n"); 80 | return -1; 81 | } 82 | 83 | int remap_into_process(task_t target_task, void* executable_region, 84 | vm_address_t target_base, int executable_fd, 85 | off_t fat_offset) { 86 | struct mach_header_64* mh = executable_region; 87 | struct load_command* cmd = executable_region + sizeof(struct mach_header_64); 88 | kern_return_t err; 89 | 90 | for (unsigned int index = 0; index < mh->ncmds; index++) { 91 | switch (cmd->cmd) { 92 | case LC_SEGMENT_64: { 93 | struct segment_command_64* seg_cmd = (struct segment_command_64*)cmd; 94 | vm_address_t source_address = 95 | (vm_address_t)(executable_region + seg_cmd->fileoff); 96 | bool need_remap = true; 97 | if (need_remap) { 98 | void* remap = 99 | mmap(NULL, seg_cmd->filesize, seg_cmd->initprot, MAP_PRIVATE, 100 | executable_fd, fat_offset + seg_cmd->fileoff); 101 | if (remap == MAP_FAILED) { 102 | fprintf(stderr, "remap failed: %s", strerror(errno)); 103 | return 1; 104 | } 105 | source_address = (vm_address_t)remap; 106 | } 107 | vm_address_t target_address = target_base + seg_cmd->vmaddr; 108 | vm_prot_t cur_protection; 109 | vm_prot_t max_protection; 110 | if (seg_cmd->filesize) { 111 | err = vm_remap(target_task, &target_address, seg_cmd->filesize, 112 | /*mask=*/0, VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, 113 | mach_task_self(), source_address, 114 | /*copy=*/false, &cur_protection, &max_protection, 115 | VM_INHERIT_COPY); 116 | if (err) { 117 | fprintf(stderr, "Can't map into process: %s\n", 118 | mach_error_string(err)); 119 | return 1; 120 | } 121 | } 122 | err = vm_protect(target_task, target_address, seg_cmd->vmsize, false, 123 | seg_cmd->initprot); 124 | if (err) { 125 | fprintf(stderr, "Can't protect into process: %s\n", 126 | mach_error_string(err)); 127 | return 1; 128 | } 129 | break; 130 | } 131 | // TODO(zhuowei): handle unixthread (we currently assume dylds have the 132 | // same unixthread) 133 | } 134 | cmd = (struct load_command*)((char*)cmd + cmd->cmdsize); 135 | } 136 | return 0; 137 | } 138 | 139 | int set_entry_point(task_t target_task, vm_address_t entry_point) { 140 | kern_return_t err; 141 | thread_act_t* thread_array; 142 | mach_msg_type_number_t num_threads; 143 | err = task_threads(target_task, &thread_array, &num_threads); 144 | if (err) { 145 | fprintf(stderr, "Failed to get threads: %s\n", mach_error_string(err)); 146 | return 1; 147 | } 148 | thread_t main_thread = thread_array[0]; 149 | #ifdef __x86_64__ 150 | x86_thread_state64_t thread_state; 151 | mach_msg_type_number_t thread_state_count = x86_THREAD_STATE64_COUNT; 152 | err = thread_get_state(main_thread, x86_THREAD_STATE64, 153 | (thread_state_t)&thread_state, &thread_state_count); 154 | if (err) { 155 | fprintf(stderr, "Failed to get thread state: %s\n", mach_error_string(err)); 156 | return 1; 157 | } 158 | thread_state.__rip = entry_point; 159 | err = thread_set_state(main_thread, x86_THREAD_STATE64, 160 | (thread_state_t)&thread_state, thread_state_count); 161 | if (err) { 162 | fprintf(stderr, "Failed to set thread state: %s\n", mach_error_string(err)); 163 | return 1; 164 | } 165 | #elif __arm64__ 166 | arm_thread_state64_t thread_state; 167 | mach_msg_type_number_t thread_state_count = ARM_THREAD_STATE64_COUNT; 168 | err = thread_get_state(main_thread, ARM_THREAD_STATE64, 169 | (thread_state_t)&thread_state, &thread_state_count); 170 | if (err) { 171 | fprintf(stderr, "Failed to get thread state: %s\n", mach_error_string(err)); 172 | return 1; 173 | } 174 | thread_state.__pc = entry_point; 175 | err = thread_set_state(main_thread, ARM_THREAD_STATE64, 176 | (thread_state_t)&thread_state, thread_state_count); 177 | if (err) { 178 | fprintf(stderr, "Failed to set thread state: %s\n", mach_error_string(err)); 179 | return 1; 180 | } 181 | #endif 182 | return 0; 183 | } 184 | 185 | vm_address_t get_dyld_target_map_address(task_t target_task, 186 | size_t new_dyld_all_images_offset) { 187 | kern_return_t err; 188 | // https://opensource.apple.com/source/dyld/dyld-195.6/unit-tests/test-cases/all_image_infos-cache-slide/main.c 189 | task_dyld_info_data_t task_dyld_info; 190 | mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; 191 | err = task_info(target_task, TASK_DYLD_INFO, (task_info_t)&task_dyld_info, 192 | &count); 193 | if (err) { 194 | fprintf(stderr, "Failed to get task info: %s\n", mach_error_string(err)); 195 | return 0; 196 | } 197 | vm_address_t old_dyld_all_images_address = task_dyld_info.all_image_info_addr; 198 | return old_dyld_all_images_address - new_dyld_all_images_offset; 199 | } 200 | 201 | int map_dyld(int target_pid, const char* dyld_path) { 202 | task_t target_task; 203 | kern_return_t err; 204 | 205 | err = task_for_pid(mach_task_self(), target_pid, &target_task); 206 | if (err) { 207 | fprintf(stderr, "Failed to get task port: %s\n", mach_error_string(err)); 208 | return 1; 209 | } 210 | if (target_task == MACH_PORT_NULL) { 211 | fprintf(stderr, "Can't get task port for pid %d\n", target_pid); 212 | return 1; 213 | } 214 | 215 | int dyld_fd = open(dyld_path, O_RDONLY); 216 | if (dyld_fd == -1) { 217 | fprintf(stderr, "Can't open %s: %s", dyld_path, strerror(errno)); 218 | return 1; 219 | } 220 | struct stat dyld_stat; 221 | if (fstat(dyld_fd, &dyld_stat)) { 222 | fprintf(stderr, "Can't stat %s: %s", dyld_path, strerror(errno)); 223 | return 1; 224 | } 225 | void* dyld_map = 226 | mmap(NULL, dyld_stat.st_size, PROT_READ, MAP_PRIVATE, dyld_fd, 0); 227 | if (dyld_map == MAP_FAILED) { 228 | fprintf(stderr, "Can't map %s: %s", dyld_path, strerror(errno)); 229 | return 1; 230 | } 231 | off_t fat_offset = get_fat_offset(dyld_map); 232 | if (fat_offset == -1) { 233 | return 1; 234 | } 235 | void* executable_map = dyld_map + fat_offset; 236 | if (!executable_map) { 237 | return 1; 238 | } 239 | size_t new_dyld_all_images_offset = 0; 240 | size_t sigcmd_dataoff = 0; 241 | size_t sigcmd_datasize = 0; 242 | size_t address_space_size = 243 | get_address_space_size(executable_map, &new_dyld_all_images_offset, 244 | &sigcmd_dataoff, &sigcmd_datasize); 245 | if (!new_dyld_all_images_offset) { 246 | fprintf(stderr, "can't find all images\n"); 247 | return 1; 248 | } 249 | // ImageLoaderMachO::loadCodeSignature, Loader::mapImage 250 | fsignatures_t siginfo; 251 | siginfo.fs_file_start = fat_offset; // start of mach-o slice in fat file 252 | siginfo.fs_blob_start = 253 | (void*)(sigcmd_dataoff); // start of CD in mach-o file 254 | siginfo.fs_blob_size = sigcmd_datasize; // size of CD 255 | if (fcntl(dyld_fd, F_ADDFILESIGS_RETURN, &siginfo) == -1) { 256 | fprintf(stderr, "can't add signatures: %s\n", strerror(errno)); 257 | return 1; 258 | } 259 | // TODO(zhuowei): this _only_ works if ASLR is enabled 260 | // (since we try to align the image infos of the new dyld on top of the old, 261 | // and that would overwrite the executable if ASLR is off and dyld is right 262 | // behind the executable) at least detect if we would overwrite an existing 263 | // mapping... 264 | vm_address_t target_address = 265 | get_dyld_target_map_address(target_task, new_dyld_all_images_offset); 266 | if (!target_address) { 267 | return 1; 268 | } 269 | fprintf(stderr, "mapping dyld at %p\n", (void*)target_address); 270 | err = vm_allocate(target_task, &target_address, address_space_size, 271 | VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE); 272 | if (err) { 273 | fprintf(stderr, "Can't allocate into process: %s\n", 274 | mach_error_string(err)); 275 | return 1; 276 | } 277 | if (remap_into_process(target_task, executable_map, target_address, dyld_fd, 278 | fat_offset)) { 279 | return 1; 280 | } 281 | // TODO(zhuowei): grab entry point from unixthread 282 | if (set_entry_point(target_task, target_address + 0x1000)) { 283 | return 1; 284 | } 285 | return 0; 286 | } 287 | 288 | int main(int argc, char** argv) { 289 | if (argc != 3) { 290 | fprintf(stderr, "usage: dyldloader \n"); 291 | return 1; 292 | } 293 | int err = map_dyld(atoi(argv[2]), argv[1]); 294 | if (err) { 295 | return 1; 296 | } 297 | return 0; 298 | } 299 | --------------------------------------------------------------------------------