├── .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 |
--------------------------------------------------------------------------------