Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
lemon4ex committed Jun 27, 2022
0 parents commit 988aec8
Show file tree
Hide file tree
Showing 17 changed files with 416 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
packages
.theos
.DS_Store
27 changes: 27 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
THEOS_DEVICE_IP = localhost -o StrictHostKeyChecking=no
THEOS_DEVICE_PORT = 2222

ARCHS = arm64 arm64e

TARGET = iphone:clang:14.5:9.0
INSTALL_TARGET_PROCESSES = lockdownd


include $(THEOS)/makefiles/common.mk

TWEAK_NAME = XcodeRootDebug

XcodeRootDebug_FILES = Tweak.x
XcodeRootDebug_CFLAGS = -fobjc-arc

include $(THEOS_MAKE_PATH)/tweak.mk

BUNDLE_NAME = XcodeRootDebugPrefs

XcodeRootDebugPrefs_FILES = XRDRootListController.m
XcodeRootDebugPrefs_FRAMEWORKS = UIKit
XcodeRootDebugPrefs_PRIVATE_FRAMEWORKS = Preferences
XcodeRootDebugPrefs_INSTALL_PATH = /Library/PreferenceBundles
XcodeRootDebugPrefs_CFLAGS = -fobjc-arc

include $(THEOS_MAKE_PATH)/bundle.mk
76 changes: 76 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# XcodeRootDebug

Allows `xcode` to start a custom `debugserver` with `root` privileges for debugging.

Currently only tested on the following jailbroken devices:

* iPhone 6s 14.3
* iPhone 7 13.6.1
* iPhone 11 Pro 14.2

Theoretically supports iOS10 and above devices, including A12.

Repo:https://repo.byteage.com

# Background

Usually, when we use `xcode` for real machine debugging, there are the following limitations:

1. The debugger can only be started with `mobile` permissions
2. The debugger that can be started can only be `/Developer/usr/bin/debugserver`

Based on the above limitations, the following problems arise:

1. Unable to debug system processes, such as: `Cydia``Safiri`
2. Unable to debug the app downloaded from `AppStore`, the app needs to be re-signed after smashing the shell

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).

To solve the above limitations, you need to install this tweak.

After installing this tweak, it will allow developers to use `xcode` to start a custom `debugserver` with `root` privileges for debugging.

You can set the tweak in settings。

# ScreenShots

![](ScreenShots/20220627_235849.png)
![](ScreenShots/20220628_000606_898.png)

# XcodeRootDebug

允许`xcode`使用`root`权限启动自定义的`debugserver`进行调试。

目前只在以下越狱设备上进行了测试:

* iPhone 6s 14.3
* iPhone 7 13.6.1
* iPhone 11 Pro 14.2

理论上支持iOS10以上设备,包括A12。

Cydia 源:https://repo.byteage.com

# 背景

通常情况下,我们使用`xcode`进行真机调试时有如下限制:

1. 只能以`mobile`权限启动调试器
2. 启动的调试器只能是`/Developer/usr/bin/debugserver`

基于上面的限制,产生了以下问题:

1. 无法调试系统进程,如:`Cydia``Safiri`
2. 无法调试`AppStore`下载的应用,应用需要砸壳后重签名

要解决上面的问题,需要使用具有高权限的`debugserver`,具体的配置过程,可以参考文章 [iOS12 下配置debugserver + lldb调试环境的小技巧和问题处理](https://iosre.com/t/ios12-debugserver-lldb/14429)

要解决上面的限制,就需要安装本插件。

安装本插件以后,将允许开发者使用`xcode``root`权限启动自定义的`debugserver`进行调试。

你可以在设置中对插件进行设置。

# 截图
![](ScreenShots/20220627_235849.png)
![](ScreenShots/20220628_000606_898.png)
24 changes: 24 additions & 0 deletions Resources/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>XcodeRootDebugPrefs</string>
<key>CFBundleIdentifier</key>
<string>com.byteage.xcoderootdebug</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>NSPrincipalClass</key>
<string>XRDRootListController</string>
</dict>
</plist>
89 changes: 89 additions & 0 deletions Resources/Root.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>cell</key>
<string>PSGroupCell</string>
<key>label</key>
<string>Options</string>
<key>footerText</key>
<string>It must be ensured that the Debug Server is properly configured and has executable permissions</string>
</dict>
<dict>
<key>cell</key>
<string>PSSwitchCell</string>
<key>default</key>
<true/>
<key>defaults</key>
<string>com.byteage.xcoderootdebug</string>
<key>key</key>
<string>enabled</string>
<key>label</key>
<string>Enabled</string>
</dict>
<dict>
<key>cell</key>
<string>PSEditTextCell</string>
<key>default</key>
<string>/usr/bin/debugserver</string>
<key>defaults</key>
<string>com.byteage.xcoderootdebug</string>
<key>key</key>
<string>debugserverPath</string>
<key>label</key>
<string>Debug Server</string>
</dict>
<dict>
<key>cell</key>
<string>PSSwitchCell</string>
<key>default</key>
<true/>
<key>defaults</key>
<string>com.byteage.xcoderootdebug</string>
<key>key</key>
<string>isRootUser</string>
<key>label</key>
<string>Permit Root</string>
</dict>
<dict>
<key>label</key>
<string>Other</string>
<key>cell</key>
<string>PSGroupCell</string>
<key>footerText</key>
<string>Click to make sure the new setting takes effect</string>
</dict>
<dict>
<key>cell</key>
<string>PSButtonCell</string>
<key>action</key>
<string>saveSetting</string>
<key>isDestructive</key>
<true/>
<key>label</key>
<string>Save Settings</string>
</dict>
<dict>
<key>footerAlignment</key>
<integer>1</integer>
<key>cell</key>
<string>PSGroupCell</string>
<key>footerText</key>
<string>Developed ❤ by h4ck1n</string>
</dict>
<dict>
<key>footerAlignment</key>
<integer>1</integer>
<key>cell</key>
<string>PSGroupCell</string>
<key>footerText</key>
<string>© 2022 All Rights Reserved by ByteAge.com</string>
</dict>
</array>
<key>title</key>
<string>XcodeRootDebug</string>
</dict>
</plist>
Binary file added Resources/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/20220627_235849.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ScreenShots/20220628_000606_898.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 127 additions & 0 deletions Tweak.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#import <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>
#import <Foundation/NSUserDefaults+Private.h>
#include <unistd.h>
#include <substrate.h>

extern char **environ;

#define LOG(fmt, ...) NSLog(@"[XcodeRootDebug] " fmt "\n", ##__VA_ARGS__)

static NSString * nsDomainString = @"com.byteage.xcoderootdebug";
static NSString * nsNotificationString = @"com.byteage.xcoderootdebug/preferences.changed";
static BOOL enabled;
static NSString *debugserverPath;
static BOOL isRootUser;

static void reloadSettings() {
NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:@"/private/var/mobile/Library/Preferences/com.byteage.xcoderootdebug.plist"];
NSNumber * enabledValue = (NSNumber *)[settings objectForKey:@"enabled"];
enabled = (enabledValue)? [enabledValue boolValue] : YES;
debugserverPath = [settings objectForKey:@"debugserverPath"];
if(!debugserverPath.length) {
debugserverPath = @"/usr/bin/debugserver";
}
NSNumber * isRootUserValue = (NSNumber *)[settings objectForKey:@"isRootUser"];
isRootUser = (isRootUserValue)? [isRootUserValue boolValue] : YES;
}

static void notificationCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
// kill self
exit(0);
}

// If the compiler understands __arm64e__, assume it's paired with an SDK that has
// ptrauth.h. Otherwise, it'll probably error if we try to include it so don't.
#if __arm64e__
#include <ptrauth.h>
#endif

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"

// Given a pointer to instructions, sign it so you can call it like a normal fptr.
static void *make_sym_callable(void *ptr) {
#if __arm64e__
ptr = ptrauth_sign_unauthenticated(ptrauth_strip(ptr, ptrauth_key_function_pointer), ptrauth_key_function_pointer, 0);
#endif
return ptr;
}

// Given a function pointer, strip the PAC so you can read the instructions.
static void *make_sym_readable(void *ptr) {
#if __arm64e__
ptr = ptrauth_strip(ptr, ptrauth_key_function_pointer);
#endif
return ptr;
}

#pragma clang diagnostic pop

typedef CFTypeRef AuthorizationRef;

bool (*original_SMJobSubmit)(CFStringRef domain, CFDictionaryRef job, AuthorizationRef auth, CFErrorRef _Nullable *error);

bool hooked_SMJobSubmit(CFStringRef domain, CFDictionaryRef job, AuthorizationRef auth, CFErrorRef _Nullable *error) {
LOG(@"Enter hooked_SMJobSubmit %@", job);
NSMutableDictionary *newJobInfo = [NSMutableDictionary dictionaryWithDictionary:(__bridge NSDictionary *)job];
NSMutableArray *programArgs = [newJobInfo[@"ProgramArguments"] mutableCopy];
NSString *program = programArgs[0];
if (enabled) {
if([program isEqualToString:@"/Developer/usr/bin/debugserver"]) {
LOG("Found launch /Developer/usr/bin/debugserver");
if(debugserverPath.length > 0 && access(debugserverPath.UTF8String, F_OK | X_OK) == 0){
LOG("Change to launch %@", debugserverPath);
programArgs[0] = debugserverPath;
newJobInfo[@"ProgramArguments"] = programArgs;
} else {
LOG("Debug Server does not exist at %@, or does not have executable permissions", debugserverPath);
}
if(isRootUser) {
LOG("Change to launch with root");
newJobInfo[@"UserName"] = @"root";
} else {
newJobInfo[@"UserName"] = @"mobile";
}
LOG(@"Now SMJobSubmit %@", newJobInfo);
} else if([program isEqualToString:debugserverPath]) {
LOG("Found launch %@",debugserverPath);
if(isRootUser) {
LOG("Change to launch with root");
newJobInfo[@"UserName"] = @"root";
} else {
newJobInfo[@"UserName"] = @"mobile";
}
LOG(@"Now SMJobSubmit %@", newJobInfo);
}
} else {
if([program isEqualToString:debugserverPath]) {
LOG("Found launch %@",debugserverPath);
LOG("Restore launch /Developer/usr/bin/debugserver with mobile");
programArgs[0] = @"/Developer/usr/bin/debugserver";
newJobInfo[@"ProgramArguments"] = programArgs;
newJobInfo[@"UserName"] = @"mobile";
LOG(@"Now SMJobSubmit %@", newJobInfo);
}
}
LOG(@"New SMJobSubmit %@", newJobInfo);
return original_SMJobSubmit(domain, (__bridge CFDictionaryRef)newJobInfo, auth, error);
}

%ctor {
LOG(@"loaded in %s (%d)", getprogname(), getpid());
reloadSettings();

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, notificationCallback, (CFStringRef)nsNotificationString, NULL, CFNotificationSuspensionBehaviorCoalesce);

MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/ServiceManagement.framework/ServiceManagement");
if (!image) {
LOG("ServiceManagement framework not found, it is impossible");
return;
}
MSHookFunction(
MSFindSymbol(image, "_SMJobSubmit"),
(void *)hooked_SMJobSubmit,
(void **)&original_SMJobSubmit
);
}
5 changes: 5 additions & 0 deletions XRDRootListController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#import <Preferences/PSListController.h>

@interface XRDRootListController : PSListController

@end
18 changes: 18 additions & 0 deletions XRDRootListController.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#import <Foundation/Foundation.h>
#import "XRDRootListController.h"
#include <notify.h>

@implementation XRDRootListController

- (NSArray *)specifiers {
if (!_specifiers) {
_specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self];
}

return _specifiers;
}

- (void)saveSetting {
notify_post("com.byteage.xcoderootdebug/preferences.changed");
}
@end
7 changes: 7 additions & 0 deletions XcodeRootDebug.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
Filter = {
Executables = (
lockdownd,
);
};
}
9 changes: 9 additions & 0 deletions control
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Package: com.byteage.xcoderootdebug
Name: XcodeRootDebug
Version: 0.0.1
Architecture: iphoneos-arm
Description: 允许xcode使用root权限启动自定义的debugserver进行调试
Maintainer: h4ck1n
Author: h4ck1n
Section: Tweaks
Depends: mobilesubstrate (>= 0.9.5000), preferenceloader (>= 2.2.3)
Loading

0 comments on commit 988aec8

Please sign in to comment.