Skip to content

Commit 988aec8

Browse files
committed
first commit
0 parents  commit 988aec8

File tree

17 files changed

+416
-0
lines changed

17 files changed

+416
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
packages
2+
.theos
3+
.DS_Store

Makefile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
THEOS_DEVICE_IP = localhost -o StrictHostKeyChecking=no
2+
THEOS_DEVICE_PORT = 2222
3+
4+
ARCHS = arm64 arm64e
5+
6+
TARGET = iphone:clang:14.5:9.0
7+
INSTALL_TARGET_PROCESSES = lockdownd
8+
9+
10+
include $(THEOS)/makefiles/common.mk
11+
12+
TWEAK_NAME = XcodeRootDebug
13+
14+
XcodeRootDebug_FILES = Tweak.x
15+
XcodeRootDebug_CFLAGS = -fobjc-arc
16+
17+
include $(THEOS_MAKE_PATH)/tweak.mk
18+
19+
BUNDLE_NAME = XcodeRootDebugPrefs
20+
21+
XcodeRootDebugPrefs_FILES = XRDRootListController.m
22+
XcodeRootDebugPrefs_FRAMEWORKS = UIKit
23+
XcodeRootDebugPrefs_PRIVATE_FRAMEWORKS = Preferences
24+
XcodeRootDebugPrefs_INSTALL_PATH = /Library/PreferenceBundles
25+
XcodeRootDebugPrefs_CFLAGS = -fobjc-arc
26+
27+
include $(THEOS_MAKE_PATH)/bundle.mk

README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# XcodeRootDebug
2+
3+
Allows `xcode` to start a custom `debugserver` with `root` privileges for debugging.
4+
5+
Currently only tested on the following jailbroken devices:
6+
7+
* iPhone 6s 14.3
8+
* iPhone 7 13.6.1
9+
* iPhone 11 Pro 14.2
10+
11+
Theoretically supports iOS10 and above devices, including A12.
12+
13+
Repo:https://repo.byteage.com
14+
15+
# Background
16+
17+
Usually, when we use `xcode` for real machine debugging, there are the following limitations:
18+
19+
1. The debugger can only be started with `mobile` permissions
20+
2. The debugger that can be started can only be `/Developer/usr/bin/debugserver`
21+
22+
Based on the above limitations, the following problems arise:
23+
24+
1. Unable to debug system processes, such as: `Cydia``Safiri`
25+
2. Unable to debug the app downloaded from `AppStore`, the app needs to be re-signed after smashing the shell
26+
27+
To solve the above problems, you need to use `debugserver` with high permissions. For the specific configuration process, you can refer to the article [Tips and Problem Handling for Configuring DebugServer + lldb Debugging Environment under iOS12](https://iosre.com/t /ios12-debugserver-lldb/14429).
28+
29+
To solve the above limitations, you need to install this tweak.
30+
31+
After installing this tweak, it will allow developers to use `xcode` to start a custom `debugserver` with `root` privileges for debugging.
32+
33+
You can set the tweak in settings。
34+
35+
# ScreenShots
36+
37+
![](ScreenShots/20220627_235849.png)
38+
![](ScreenShots/20220628_000606_898.png)
39+
40+
# XcodeRootDebug
41+
42+
允许`xcode`使用`root`权限启动自定义的`debugserver`进行调试。
43+
44+
目前只在以下越狱设备上进行了测试:
45+
46+
* iPhone 6s 14.3
47+
* iPhone 7 13.6.1
48+
* iPhone 11 Pro 14.2
49+
50+
理论上支持iOS10以上设备,包括A12。
51+
52+
Cydia 源:https://repo.byteage.com
53+
54+
# 背景
55+
56+
通常情况下,我们使用`xcode`进行真机调试时有如下限制:
57+
58+
1. 只能以`mobile`权限启动调试器
59+
2. 启动的调试器只能是`/Developer/usr/bin/debugserver`
60+
61+
基于上面的限制,产生了以下问题:
62+
63+
1. 无法调试系统进程,如:`Cydia``Safiri`
64+
2. 无法调试`AppStore`下载的应用,应用需要砸壳后重签名
65+
66+
要解决上面的问题,需要使用具有高权限的`debugserver`,具体的配置过程,可以参考文章 [iOS12 下配置debugserver + lldb调试环境的小技巧和问题处理](https://iosre.com/t/ios12-debugserver-lldb/14429)
67+
68+
要解决上面的限制,就需要安装本插件。
69+
70+
安装本插件以后,将允许开发者使用`xcode``root`权限启动自定义的`debugserver`进行调试。
71+
72+
你可以在设置中对插件进行设置。
73+
74+
# 截图
75+
![](ScreenShots/20220627_235849.png)
76+
![](ScreenShots/20220628_000606_898.png)

Resources/Info.plist

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>English</string>
7+
<key>CFBundleExecutable</key>
8+
<string>XcodeRootDebugPrefs</string>
9+
<key>CFBundleIdentifier</key>
10+
<string>com.byteage.xcoderootdebug</string>
11+
<key>CFBundleInfoDictionaryVersion</key>
12+
<string>6.0</string>
13+
<key>CFBundlePackageType</key>
14+
<string>BNDL</string>
15+
<key>CFBundleShortVersionString</key>
16+
<string>1.0.0</string>
17+
<key>CFBundleSignature</key>
18+
<string>????</string>
19+
<key>CFBundleVersion</key>
20+
<string>1.0</string>
21+
<key>NSPrincipalClass</key>
22+
<string>XRDRootListController</string>
23+
</dict>
24+
</plist>

Resources/Root.plist

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>items</key>
6+
<array>
7+
<dict>
8+
<key>cell</key>
9+
<string>PSGroupCell</string>
10+
<key>label</key>
11+
<string>Options</string>
12+
<key>footerText</key>
13+
<string>It must be ensured that the Debug Server is properly configured and has executable permissions</string>
14+
</dict>
15+
<dict>
16+
<key>cell</key>
17+
<string>PSSwitchCell</string>
18+
<key>default</key>
19+
<true/>
20+
<key>defaults</key>
21+
<string>com.byteage.xcoderootdebug</string>
22+
<key>key</key>
23+
<string>enabled</string>
24+
<key>label</key>
25+
<string>Enabled</string>
26+
</dict>
27+
<dict>
28+
<key>cell</key>
29+
<string>PSEditTextCell</string>
30+
<key>default</key>
31+
<string>/usr/bin/debugserver</string>
32+
<key>defaults</key>
33+
<string>com.byteage.xcoderootdebug</string>
34+
<key>key</key>
35+
<string>debugserverPath</string>
36+
<key>label</key>
37+
<string>Debug Server</string>
38+
</dict>
39+
<dict>
40+
<key>cell</key>
41+
<string>PSSwitchCell</string>
42+
<key>default</key>
43+
<true/>
44+
<key>defaults</key>
45+
<string>com.byteage.xcoderootdebug</string>
46+
<key>key</key>
47+
<string>isRootUser</string>
48+
<key>label</key>
49+
<string>Permit Root</string>
50+
</dict>
51+
<dict>
52+
<key>label</key>
53+
<string>Other</string>
54+
<key>cell</key>
55+
<string>PSGroupCell</string>
56+
<key>footerText</key>
57+
<string>Click to make sure the new setting takes effect</string>
58+
</dict>
59+
<dict>
60+
<key>cell</key>
61+
<string>PSButtonCell</string>
62+
<key>action</key>
63+
<string>saveSetting</string>
64+
<key>isDestructive</key>
65+
<true/>
66+
<key>label</key>
67+
<string>Save Settings</string>
68+
</dict>
69+
<dict>
70+
<key>footerAlignment</key>
71+
<integer>1</integer>
72+
<key>cell</key>
73+
<string>PSGroupCell</string>
74+
<key>footerText</key>
75+
<string>Developed ❤ by h4ck1n</string>
76+
</dict>
77+
<dict>
78+
<key>footerAlignment</key>
79+
<integer>1</integer>
80+
<key>cell</key>
81+
<string>PSGroupCell</string>
82+
<key>footerText</key>
83+
<string>© 2022 All Rights Reserved by ByteAge.com</string>
84+
</dict>
85+
</array>
86+
<key>title</key>
87+
<string>XcodeRootDebug</string>
88+
</dict>
89+
</plist>
7.3 KB
Loading
13.5 KB
Loading

ScreenShots/20220627_235849.png

1.42 MB
Loading
109 KB
Loading

Tweak.x

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#import <CoreFoundation/CoreFoundation.h>
2+
#import <Foundation/Foundation.h>
3+
#import <Foundation/NSUserDefaults+Private.h>
4+
#include <unistd.h>
5+
#include <substrate.h>
6+
7+
extern char **environ;
8+
9+
#define LOG(fmt, ...) NSLog(@"[XcodeRootDebug] " fmt "\n", ##__VA_ARGS__)
10+
11+
static NSString * nsDomainString = @"com.byteage.xcoderootdebug";
12+
static NSString * nsNotificationString = @"com.byteage.xcoderootdebug/preferences.changed";
13+
static BOOL enabled;
14+
static NSString *debugserverPath;
15+
static BOOL isRootUser;
16+
17+
static void reloadSettings() {
18+
NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:@"/private/var/mobile/Library/Preferences/com.byteage.xcoderootdebug.plist"];
19+
NSNumber * enabledValue = (NSNumber *)[settings objectForKey:@"enabled"];
20+
enabled = (enabledValue)? [enabledValue boolValue] : YES;
21+
debugserverPath = [settings objectForKey:@"debugserverPath"];
22+
if(!debugserverPath.length) {
23+
debugserverPath = @"/usr/bin/debugserver";
24+
}
25+
NSNumber * isRootUserValue = (NSNumber *)[settings objectForKey:@"isRootUser"];
26+
isRootUser = (isRootUserValue)? [isRootUserValue boolValue] : YES;
27+
}
28+
29+
static void notificationCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
30+
// kill self
31+
exit(0);
32+
}
33+
34+
// If the compiler understands __arm64e__, assume it's paired with an SDK that has
35+
// ptrauth.h. Otherwise, it'll probably error if we try to include it so don't.
36+
#if __arm64e__
37+
#include <ptrauth.h>
38+
#endif
39+
40+
#pragma clang diagnostic push
41+
#pragma clang diagnostic ignored "-Wunused-function"
42+
43+
// Given a pointer to instructions, sign it so you can call it like a normal fptr.
44+
static void *make_sym_callable(void *ptr) {
45+
#if __arm64e__
46+
ptr = ptrauth_sign_unauthenticated(ptrauth_strip(ptr, ptrauth_key_function_pointer), ptrauth_key_function_pointer, 0);
47+
#endif
48+
return ptr;
49+
}
50+
51+
// Given a function pointer, strip the PAC so you can read the instructions.
52+
static void *make_sym_readable(void *ptr) {
53+
#if __arm64e__
54+
ptr = ptrauth_strip(ptr, ptrauth_key_function_pointer);
55+
#endif
56+
return ptr;
57+
}
58+
59+
#pragma clang diagnostic pop
60+
61+
typedef CFTypeRef AuthorizationRef;
62+
63+
bool (*original_SMJobSubmit)(CFStringRef domain, CFDictionaryRef job, AuthorizationRef auth, CFErrorRef _Nullable *error);
64+
65+
bool hooked_SMJobSubmit(CFStringRef domain, CFDictionaryRef job, AuthorizationRef auth, CFErrorRef _Nullable *error) {
66+
LOG(@"Enter hooked_SMJobSubmit %@", job);
67+
NSMutableDictionary *newJobInfo = [NSMutableDictionary dictionaryWithDictionary:(__bridge NSDictionary *)job];
68+
NSMutableArray *programArgs = [newJobInfo[@"ProgramArguments"] mutableCopy];
69+
NSString *program = programArgs[0];
70+
if (enabled) {
71+
if([program isEqualToString:@"/Developer/usr/bin/debugserver"]) {
72+
LOG("Found launch /Developer/usr/bin/debugserver");
73+
if(debugserverPath.length > 0 && access(debugserverPath.UTF8String, F_OK | X_OK) == 0){
74+
LOG("Change to launch %@", debugserverPath);
75+
programArgs[0] = debugserverPath;
76+
newJobInfo[@"ProgramArguments"] = programArgs;
77+
} else {
78+
LOG("Debug Server does not exist at %@, or does not have executable permissions", debugserverPath);
79+
}
80+
if(isRootUser) {
81+
LOG("Change to launch with root");
82+
newJobInfo[@"UserName"] = @"root";
83+
} else {
84+
newJobInfo[@"UserName"] = @"mobile";
85+
}
86+
LOG(@"Now SMJobSubmit %@", newJobInfo);
87+
} else if([program isEqualToString:debugserverPath]) {
88+
LOG("Found launch %@",debugserverPath);
89+
if(isRootUser) {
90+
LOG("Change to launch with root");
91+
newJobInfo[@"UserName"] = @"root";
92+
} else {
93+
newJobInfo[@"UserName"] = @"mobile";
94+
}
95+
LOG(@"Now SMJobSubmit %@", newJobInfo);
96+
}
97+
} else {
98+
if([program isEqualToString:debugserverPath]) {
99+
LOG("Found launch %@",debugserverPath);
100+
LOG("Restore launch /Developer/usr/bin/debugserver with mobile");
101+
programArgs[0] = @"/Developer/usr/bin/debugserver";
102+
newJobInfo[@"ProgramArguments"] = programArgs;
103+
newJobInfo[@"UserName"] = @"mobile";
104+
LOG(@"Now SMJobSubmit %@", newJobInfo);
105+
}
106+
}
107+
LOG(@"New SMJobSubmit %@", newJobInfo);
108+
return original_SMJobSubmit(domain, (__bridge CFDictionaryRef)newJobInfo, auth, error);
109+
}
110+
111+
%ctor {
112+
LOG(@"loaded in %s (%d)", getprogname(), getpid());
113+
reloadSettings();
114+
115+
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, notificationCallback, (CFStringRef)nsNotificationString, NULL, CFNotificationSuspensionBehaviorCoalesce);
116+
117+
MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/ServiceManagement.framework/ServiceManagement");
118+
if (!image) {
119+
LOG("ServiceManagement framework not found, it is impossible");
120+
return;
121+
}
122+
MSHookFunction(
123+
MSFindSymbol(image, "_SMJobSubmit"),
124+
(void *)hooked_SMJobSubmit,
125+
(void **)&original_SMJobSubmit
126+
);
127+
}

0 commit comments

Comments
 (0)