Run an App as root on iOS11 and iOS12 with Theos

注意事项

  • 测试环境
    • macOS: 10.14.6
    • iPhoneOS: iOS11.0、iOS12.0、
    • iPhone机型:两个iPhone6
    • 越狱工具:unc0ver3.6.2
    • 没有测试:iOS13和iOS10,也许可以。
  • 实现目标:点击按钮执行killall -9 SpringBoard,注销SpringBoard

理论部分

1. App所有权

  • /Applications目录存放系统自带的应用,这个目录下存放的应用一般属于root:admin
  • 想要Run an App as root,要把自己的.app文件放到这个目录下

2. 用户标识

  • 文件的所有者和程序的所有者是不一样的,程序的所有者通常被用作用户标识
  • 为了Run an App as root,我们需要更改用户的uid和euid为0

新建RootApp

  • 使用nic.pl进行新建

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    $ nic.pl
    NIC 2.0 - New Instance Creator
    ------------------------------
    [1.] iphone/activator_event
    [2.] iphone/application_modern
    [3.] iphone/application_swift
    [4.] iphone/cydget
    [5.] iphone/flipswitch_switch
    [6.] iphone/framework
    [7.] iphone/ios7_notification_center_widget
    [8.] iphone/library
    [9.] iphone/notification_center_widget
    [10.] iphone/preference_bundle_modern
    [11.] iphone/tool
    [12.] iphone/tool_swift
    [13.] iphone/tweak
    [14.] iphone/xpc_service
    Choose a Template (required): 2
    Project Name (required): RootApp
    Package Name [com.yourcompany.rootapp]: me.rootapp.app
    Author/Maintainer Name [XX]: drag
    [iphone/application_modern] Class name prefix (two or more characters) [XX]: RA
    Instantiating iphone/application_modern in rootapp/...
    Done.
  • RARootViewController.m中填写以下内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #import <spawn.h>

    int spawn(const char* executable, ...) {
    int ret;
    pid_t pid;
    va_list args;
    va_start(args, executable);
    ret = posix_spawn(&pid, executable, NULL, NULL, (char* const *)args, NULL);
    if (ret == 0) waitpid(pid, NULL, 0);
    return ret;
    }

    - (void)addButtonTapped:(id)sender {
    [_objects insertObject:[NSDate date] atIndex:0];
    [self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:0 inSection:0] ] withRowAnimation:UITableViewRowAnimationAutomatic];
    NSLog(@"RootAppTest: %d, %d, %d", getuid(), geteuid(), spawn("/usr/bin/killall","/usr/bin/killall", "-9", "SpringBoard", NULL));
    }
  • 执行make clean && make && make package && make install进行编译安装

    • 看不到App图标,执行uicache刷新就可以了
    • RootApp会安装到/Applications目录下
  • 打开App,点击加号按钮打印uid和euid都为501,注销操作也失败,所以我们需要设置uid和euid。

    1
    RootAppTest: 501, 501, 1

设置uid和euid

  • main.m中设置uid
    1
    2
    3
    4
    5
    6
    7
    #import "RAAppDelegate.h"
    int main(int argc, char *argv[]) {
    @autoreleasepool {
    setuid(0);
    return UIApplicationMain(argc, argv, nil, NSStringFromClass(RAAppDelegate. class));
    }
    }
  • Makefile中添加如下内容设置euid
    1
    2
    after-stage::
    $(ECHO_NOTHING)chmod +s $(THEOS_STAGING_DIR)/Applications/RootApp.app/RootApp$(ECHO_END)
  • 执行make clean && make && make package && make install后,打开App,点击加号按钮,打印uid和euid都为0,注销操作执行失败,还需要为可执行文件签权
    1
    RootAppTest: 0, 0, 1

可执行文件签权

  • 新建RootApp.entitlements文件,填写内容为:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?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>com.apple.private.security.no-container</key>
    <true/>
    <key>com.apple.private.skip-library-validation</key>
    <true/>
    <key>platform-application</key>
    <true/>
    </dict>
    </plist>
  • 把RootApp.entitlements放到和Makefile同级目录,Makefile填入下面内容对可执行文件签权
    1
    RootApp_CODESIGN_FLAGS = -SRootApp.entitlements

最后

  • 最终Makefile内容为
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ARCHS = arm64
    TARGET = iPhone:latest:8.0

    include $(THEOS)/makefiles/common.mk

    APPLICATION_NAME = RootApp
    RootApp_FILES = main.m RAAppDelegate.m RARootViewController.m
    RootApp_FRAMEWORKS = UIKit CoreGraphics
    RootApp_CODESIGN_FLAGS = -SRootApp.entitlements

    include $(THEOS_MAKE_PATH)/application.mk

    after-stage::
    $(ECHO_NOTHING)chmod +s $(THEOS_STAGING_DIR)/Applications/RootApp.app/ RootApp$(ECHO_END)

    after-install::
    install.exec "su mobile -c uicache"
    install.exec "killall \"RootApp\"" || true
  • 执行make clean && make && make package && make install后,点击按钮,注销SpringBoard成功。