iOS 获取root权限
2022-09-09 本文已影响0人
第x个等于4乘x的阶乘
首先感谢 https://www.diffit.cn/2019/10/09/RunAppAsRootForXcode/ 作者 帮助我解决了困扰我很久的root权限问题 就有一点entitlements签名有点困惑 文件位置不是很清晰 本篇文章只是注明entitlements的文件位置
同时拓展了在root权限下获取UDID之类的api
注意事项
- 测试环境
- macOS: 10.14.6
- iPhoneOS: iOS11.0、iOS12.0、
- iPhone机型:两个iPhone6
- 越狱工具:unc0ver3.6.2
- 没有测试:iOS13和iOS10,也许可以。
- 关于链接
- 阅读本文前,请首先阅读 RunAppAsRootForTheos理论部分
- 此文使用Xcode新建的App,如果使用Theos新建的App,请转入RunAppAsRootForTheos
- 实现目标:点击按钮执行killall -9 SpringBoard,注销SpringBoard
App代码
- 本案例中使用Xcode新建的项目名称叫RootApp
- 在Xcode中找到main.m,添加setuid(0),设置uid
#import "RARootViewController.h"
#import <spawn.h>
#import <sys/utsname.h>
extern CFTypeRef MGCopyAnswer(CFStringRef);
@interface RARootViewController ()<UIAlertViewDelegate>
@end
@implementation RARootViewController {
NSMutableArray *_objects;
}
- (void)loadView {
[super loadView];
_objects = [NSMutableArray array];
self.title = @"Root View Controller";
self.navigationItem.leftBarButtonItem = self.editButtonItem;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonTapped:)];
}
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];
NSDictionary *dic = [self getDeviceInfo];
NSLog(@"HardwareID %@",dic);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Info" message:dic.description delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
[alert show];
// NSLog(@"RootAppTest: %d, %d, %d", getuid(), geteuid(), spawn("/usr/bin/killall","/usr/bin/killall", "-9", "SpringBoard", NULL));
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
id alertbutton = [alertView buttonTitleAtIndex:buttonIndex];
if (buttonIndex == 1) {
NSLog(@"RootAppTest: %d, %d, %d", getuid(), geteuid(), spawn("/usr/bin/killall","/usr/bin/killall", "-9", "SpringBoard", NULL));
}
}
#pragma mark - Table View Data Source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _objects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDate *date = _objects[indexPath.row];
cell.textLabel.text = date.description;
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[ indexPath ] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - Table View Delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
//获取udid
/**
*
*/
- (NSDictionary*)getDeviceInfo{
NSString *strUDID = [self getUDID];
NSString *strSN = [self getSerialNumber];
NSString *strWifiAddress = [self getWifiAddress];
NSString *strBlueAddress = [self getBluetoothAddress];
if (strUDID == nil) {
strUDID = @" ";
}
if (strSN == nil) {
strSN = @" ";
}
if (strWifiAddress == nil) {
strWifiAddress = @" ";
}
if (strBlueAddress == nil) {
strBlueAddress = @" ";
}
NSLog(@"RootAppTest: getuid——%d, geteuid——%d", getuid(), geteuid());
NSMutableDictionary *dictDeviceInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
strUDID,@"UDID",
strSN,@"SerialNumber",
strWifiAddress,@"WifiAddress",
strBlueAddress,@"BlueAddress",
[NSString stringWithFormat:@"%d",getuid()],@"getuid()",
[NSString stringWithFormat:@"%d",geteuid()],@"geteuid()",
nil];
return dictDeviceInfo;
}
-(NSString*)getUDID{
NSString *str = @"UniqueDeviceID";
CFStringRef result = MGCopyAnswer((__bridge CFStringRef)str);
return (__bridge NSString *)(result);
}
-(NSString*)getSerialNumber{
NSString *str = @"SerialNumber";
CFStringRef result = MGCopyAnswer((__bridge CFStringRef)str);
return (__bridge NSString *)(result);
}
-(NSString*) getIMEI{
NSString *str = @"InternationalMobileEquipmentIdentity";
CFStringRef result = MGCopyAnswer((__bridge CFStringRef)str);
return (__bridge NSString *)(result);
}
-(NSString*) getWifiAddress{
NSString *str = @"WifiAddress";
CFStringRef result = MGCopyAnswer((__bridge CFStringRef)str);
return (__bridge NSString *)(result);
}
-(NSString*) getBluetoothAddress{
NSString *str = @"BluetoothAddress";
CFStringRef result = MGCopyAnswer((__bridge CFStringRef)str);
return (__bridge NSString *)(result);
}
@end
- 代码写完后,进行编译,编译完成后把RootApp.app放入iPhone上的/Applications里面
运行App
- SSH登录iPhone,执行以下命令,要不然看不到App图标
~ root# uicache
- 更改二进制文件权限,要不然App不能启动
~ root# chmod 755 /Applications/RootApp.app/RootApp
- 至此App可以成功打开
设置euid
~ root# chmod u+s /Applications/RootApp.app/RootApp
- 执行killall -9 SpringBoard,然后重新打开App,点击按钮,这个时候打印出来uid和euid为0
- 虽然uid和euid为0但是不能注销SpringBoard,因为需要可执行文件签权
可执行文件签权
- 新建RootApp.entitlements文件,内容为
<?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放到app文件内
ldid -SRootApp.entitlements RootApp
-
如下图
image.png