├── .gitignore ├── Makefile ├── README.md ├── SVC_Caller.h ├── app ├── AppDelegate.h ├── AppDelegate.m ├── Makefile ├── Resources │ ├── AppIcon60x60@2x.png │ ├── AppIcon76x76@2x~ipad.png │ └── Info.plist ├── RootViewController.h ├── RootViewController.m ├── appent.xml └── main.m ├── control ├── debian-script ├── Makefile ├── entitlements.plist └── main.m ├── ent.plist ├── include └── NSTask.h ├── kernel.h ├── kernel.m ├── layout └── usr │ └── share │ └── vnodebypass │ └── hidePathList.plist ├── libdimentio.c ├── libdimentio.h ├── main.m ├── vnode.h └── vnode.m /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | .theos/* 3 | debs/* 4 | *.deb 5 | *.dylib 6 | **/.theos/* 7 | */.theos/* 8 | *.psd 9 | _/* 10 | */obj/* 11 | obj/* 12 | *.zip -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GO_EASY_ON_ME = 1 2 | DEBUG = 0 3 | FINALPACKAGE = 1 4 | 5 | THEOS_DEVICE_IP = 0.0.0.0 -p 2222 6 | 7 | TARGET := iphone:clang:latest:12.0 8 | ARCHS = arm64 9 | 10 | include $(THEOS)/makefiles/common.mk 11 | 12 | TOOL_NAME = vnodebypass 13 | 14 | vnodebypass_FILES = main.m vnode.m libdimentio.c kernel.m 15 | vnodebypass_CFLAGS = -fobjc-arc 16 | vnodebypass_CODESIGN_FLAGS = -Sent.plist 17 | vnodebypass_INSTALL_PATH = /usr/bin 18 | vnodebypass_FRAMEWORKS = IOKit 19 | 20 | include $(THEOS_MAKE_PATH)/tool.mk 21 | SUBPROJECTS += app 22 | SUBPROJECTS += debian-script 23 | include $(THEOS_MAKE_PATH)/aggregate.mk 24 | 25 | before-package:: 26 | chmod -R 755 $(THEOS_STAGING_DIR) 27 | chmod 6755 $(THEOS_STAGING_DIR)/usr/bin/vnodebypass 28 | chmod 666 $(THEOS_STAGING_DIR)/DEBIAN/control 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vnodebypass 2 | ===================== 3 | 4 | ### An expermental tool to hide jailbreak files for bypass detection. 5 | -------------------------------------------------------------------------------- /SVC_Caller.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | inline int SVC_Access(const char* detectionPath) { 5 | 6 | #if defined __arm64__ || defined __arm64e__ 7 | int64_t flag = 0; 8 | __asm __volatile("mov x0, %0" :: "r" (detectionPath)); //path 9 | __asm __volatile("mov x1, #0"); //mode 10 | __asm __volatile("mov x16, #0x21"); //access 11 | __asm __volatile("svc #0x80"); //supervisor call 12 | __asm __volatile("mov %0, x0" : "=r" (flag)); 13 | #else 14 | int flag = 0; 15 | __asm __volatile("mov r0, %0" :: "r" (detectionPath)); //path 16 | __asm __volatile("mov r1, #0"); //mode 17 | __asm __volatile("mov r12, #0x21"); //access 18 | __asm __volatile("svc #0x80"); //supervisor call 19 | __asm __volatile("mov %0, r0" : "=r" (flag)); 20 | #endif 21 | return flag; 22 | } -------------------------------------------------------------------------------- /app/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface AppDelegate : UIResponder 4 | 5 | @property(nonatomic, strong) UIWindow *window; 6 | @property(nonatomic, strong) UIViewController *rootViewController; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /app/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "RootViewController.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (void)applicationDidFinishLaunching:(UIApplication *)application { 7 | _window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 8 | _rootViewController = [[RootViewController alloc] init]; 9 | _window.rootViewController = _rootViewController; 10 | [_window makeKeyAndVisible]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /app/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:latest:7.0 2 | INSTALL_TARGET_PROCESSES = vnodebypass 3 | 4 | ARCHS = arm64 5 | 6 | include $(THEOS)/makefiles/common.mk 7 | 8 | APPLICATION_NAME = vnodebypass 9 | 10 | vnodebypass_FILES = main.m AppDelegate.m RootViewController.m 11 | vnodebypass_FRAMEWORKS = UIKit CoreGraphics 12 | vnodebypass_CFLAGS = -fobjc-arc -I../include 13 | vnodebypass_CODESIGN_FLAGS = -Sappent.xml 14 | 15 | include $(THEOS_MAKE_PATH)/application.mk 16 | -------------------------------------------------------------------------------- /app/Resources/AppIcon60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ichitaso/vnodebypass/3fd6076f66a50ff15601002013f258c4edbff746/app/Resources/AppIcon60x60@2x.png -------------------------------------------------------------------------------- /app/Resources/AppIcon76x76@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ichitaso/vnodebypass/3fd6076f66a50ff15601002013f258c4edbff746/app/Resources/AppIcon76x76@2x~ipad.png -------------------------------------------------------------------------------- /app/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 20D91 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | vnodebypass 11 | CFBundleIconFiles 12 | 13 | AppIcon60x60@2x.png 14 | AppIcon76x76@2x~ipad.png 15 | 16 | CFBundleIdentifier 17 | kr.xsf1re.vnodebypass 18 | CFBundleInfoDictionaryVersion 19 | 6.0 20 | CFBundleName 21 | vnodebypass 22 | CFBundlePackageType 23 | APPL 24 | CFBundleShortVersionString 25 | 1.0 26 | CFBundleSupportedPlatforms 27 | 28 | iPhoneOS 29 | 30 | CFBundleVersion 31 | 1 32 | DTCompiler 33 | com.apple.compilers.llvm.clang.1_0 34 | DTPlatformBuild 35 | 18D46 36 | DTPlatformName 37 | iphoneos 38 | DTPlatformVersion 39 | 14.4 40 | DTSDKBuild 41 | 18D46 42 | DTSDKName 43 | iphoneos14.4 44 | DTXcode 45 | 1240 46 | DTXcodeBuild 47 | 12D4e 48 | LSRequiresIPhoneOS 49 | 50 | MinimumOSVersion 51 | 12.0 52 | UIApplicationSupportsIndirectInputEvents 53 | 54 | UIDeviceFamily 55 | 56 | 1 57 | 2 58 | 59 | UILaunchStoryboardName 60 | LaunchScreen 61 | UIRequiredDeviceCapabilities 62 | 63 | arm64 64 | 65 | UISupportedInterfaceOrientations 66 | 67 | UIInterfaceOrientationPortrait 68 | UIInterfaceOrientationLandscapeLeft 69 | UIInterfaceOrientationLandscapeRight 70 | 71 | UISupportedInterfaceOrientations~ipad 72 | 73 | UIInterfaceOrientationPortrait 74 | UIInterfaceOrientationPortraitUpsideDown 75 | UIInterfaceOrientationLandscapeLeft 76 | UIInterfaceOrientationLandscapeRight 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /app/RootViewController.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface RootViewController : UIViewController 5 | @property UILabel *titleLabel; 6 | @property UILabel *subtitleLabel; 7 | @property UIButton *button; 8 | @end 9 | -------------------------------------------------------------------------------- /app/RootViewController.m: -------------------------------------------------------------------------------- 1 | #import "RootViewController.h" 2 | 3 | @interface RootViewController () 4 | @end 5 | 6 | @implementation RootViewController 7 | 8 | - (void)loadView { 9 | [super loadView]; 10 | 11 | self.view.backgroundColor = UIColor.blackColor; 12 | } 13 | 14 | - (void)viewDidLoad { 15 | [super viewDidLoad]; 16 | 17 | _titleLabel = 18 | [[UILabel alloc] initWithFrame:CGRectMake(0, 50, UIScreen.mainScreen.bounds.size.width, 100)]; 19 | _titleLabel.text = @"vnodebypass"; 20 | _titleLabel.textAlignment = NSTextAlignmentCenter; 21 | _titleLabel.textColor = UIColor.whiteColor; 22 | _titleLabel.font = [UIFont systemFontOfSize:40]; 23 | [self.view addSubview:_titleLabel]; 24 | 25 | _subtitleLabel = [[UILabel alloc] 26 | initWithFrame:CGRectMake(0, 100, UIScreen.mainScreen.bounds.size.width, 100)]; 27 | _subtitleLabel.text = @"USE IT AT YOUR OWN RISK!"; 28 | _subtitleLabel.textAlignment = NSTextAlignmentCenter; 29 | _subtitleLabel.textColor = UIColor.whiteColor; 30 | _subtitleLabel.font = [UIFont systemFontOfSize:20]; 31 | [self.view addSubview:_subtitleLabel]; 32 | 33 | _button = [UIButton buttonWithType:UIButtonTypeSystem]; 34 | _button.frame = CGRectMake(UIScreen.mainScreen.bounds.size.width / 2 - 30, 35 | UIScreen.mainScreen.bounds.size.height / 2 - 25, 60, 50); 36 | [_button setTitle:access("/bin/bash", F_OK) == 0 ? @"Enable" : @"Disable" 37 | forState:UIControlStateNormal]; 38 | [_button addTarget:self 39 | action:@selector(buttonPressed:) 40 | forControlEvents:UIControlEventTouchUpInside]; 41 | [self.view addSubview:_button]; 42 | } 43 | 44 | - (void)buttonPressed:(UIButton *)sender { 45 | BOOL disabled = access("/bin/bash", F_OK) == 0; 46 | NSArray *opts; 47 | if (disabled) { 48 | opts = @[ @"-s", @"-h" ]; 49 | } else { 50 | opts = @[ @"-r", @"-R" ]; 51 | } 52 | 53 | NSString *launchPath = 54 | [NSString stringWithFormat:@"/usr/bin/%@", NSProcessInfo.processInfo.processName]; 55 | NSTask *task = [NSTask launchedTaskWithLaunchPath:launchPath arguments:@[ opts[0] ]]; 56 | [task waitUntilExit]; 57 | task = [NSTask launchedTaskWithLaunchPath:launchPath arguments:@[ opts[1] ]]; 58 | [task waitUntilExit]; 59 | NSString *title = access("/bin/bash", F_OK) == 0 ? @"Enable" : @"Disable"; 60 | NSString *successTitle = (access("/bin/bash", F_OK) == 0) == disabled ? @"Failed" : @"Success"; 61 | [_button setTitle:successTitle forState:UIControlStateNormal]; 62 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 63 | sleep(1); 64 | dispatch_async(dispatch_get_main_queue(), ^{ 65 | [_button setTitle:title forState:UIControlStateNormal]; 66 | }); 67 | }); 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /app/appent.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | platform-application 6 | 7 | com.apple.private.security.container-required 8 | 9 | com.apple.springboard.debugapplicationsget-task-allow 10 | 11 | com.apple.private.skip-library-validation 12 | 13 | proc_info-allow 14 | 15 | get-task-allow 16 | 17 | task_for_pid-allow 18 | 19 | run-unsigned-code 20 | 21 | com.apple.private.security.no-container 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/main.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | int main(int argc, char *argv[]) { 4 | @autoreleasepool { 5 | return UIApplicationMain(argc, argv, nil, NSStringFromClass(AppDelegate.class)); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Author: XsF1re 2 | Maintainer: ichitaso 3 | Package: kr.xsf1re.vnodebypass 4 | Name: vnodebypass 5 | Depends: firmware (>= 12.0) 6 | Section: System 7 | Version: 0.2.9 8 | Architecture: iphoneos-arm 9 | Description: An expermental tool to hide jailbreak files for bypass detection. 10 | Depiction: https://cydia.ichitaso.com/depiction/vnodebypass.html 11 | Tag: role::hacker, compatible::ios12, compatible::ios13, compatible::ios14 12 | Icon: https://raw.githubusercontent.com/ichitaso/vnodebypass_theme/main/layout/Library/Themes/vnodebypass.theme/Icon.png 13 | -------------------------------------------------------------------------------- /debian-script/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:latest:12.0 2 | 3 | ARCHS = arm64 4 | 5 | include $(THEOS)/makefiles/common.mk 6 | 7 | TOOL_NAME = postinst prerm 8 | 9 | postinst_FILES = main.m 10 | postinst_CFLAGS = -fobjc-arc -I../include 11 | postinst_CODESIGN_FLAGS = -Sentitlements.plist 12 | postinst_INSTALL_PATH = /DEBIAN 13 | 14 | prerm_FILES = main.m 15 | prerm_CFLAGS = -fobjc-arc -I../include 16 | prerm_CODESIGN_FLAGS = -Sentitlements.plist 17 | prerm_INSTALL_PATH = /DEBIAN 18 | 19 | include $(THEOS_MAKE_PATH)/tool.mk 20 | -------------------------------------------------------------------------------- /debian-script/entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | platform-application 5 | 6 | com.apple.private.security.container-required 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /debian-script/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #include 4 | 5 | int main(int argc, char *argv[], char *envp[]) { 6 | @autoreleasepool { 7 | NSTask *task = [NSTask new]; 8 | task.launchPath = @"/usr/bin/uicache"; 9 | 10 | BOOL isRemoving = [NSProcessInfo.processInfo.processName containsString:@"prerm"]; 11 | BOOL isUpgrading = strstr(argv[1], "upgrade"); 12 | 13 | if (isRemoving || isUpgrading) { 14 | NSArray *fileList = 15 | [[NSString stringWithContentsOfFile:@"/var/lib/dpkg/info/kr.xsf1re.vnodebypass.list" 16 | encoding:NSUTF8StringEncoding 17 | error:nil] componentsSeparatedByString:@"\n"]; 18 | NSInteger appPathIndex = 19 | [fileList indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { 20 | return [obj hasSuffix:@".app"]; 21 | }]; 22 | if (appPathIndex != NSNotFound) { 23 | task.arguments = @[ @"-u", fileList[appPathIndex] ]; 24 | [task launch]; 25 | [task waitUntilExit]; 26 | } else { 27 | printf("Could not find vnodebypass.app, skipping uicache\n"); 28 | } 29 | if (isRemoving) return 0; 30 | } 31 | 32 | NSString *randomName = [[NSUUID UUID].UUIDString componentsSeparatedByString:@"-"].firstObject; 33 | 34 | NSMutableDictionary *appInfo = [NSMutableDictionary 35 | dictionaryWithContentsOfFile:@"/Applications/vnodebypass.app/Info.plist"]; 36 | appInfo[@"CFBundleExecutable"] = randomName; 37 | [appInfo writeToFile:@"/Applications/vnodebypass.app/Info.plist" atomically:YES]; 38 | 39 | NSArray *renames = @[ 40 | @[ @"/usr/bin/vnodebypass", @"/usr/bin/%@" ], 41 | @[ @"/Applications/vnodebypass.app/vnodebypass", @"/Applications/vnodebypass.app/%@" ], 42 | @[ @"/Applications/vnodebypass.app", @"/Applications/%@.app" ], 43 | @[ @"/usr/share/vnodebypass", @"/usr/share/%@" ] 44 | ]; 45 | 46 | for (NSArray *rename in renames) { 47 | NSString *oldPath = rename[0]; 48 | NSString *newPath = [NSString stringWithFormat:rename[1], randomName]; 49 | NSError *error; 50 | [[NSFileManager defaultManager] moveItemAtPath:oldPath toPath:newPath error:&error]; 51 | if (error) { 52 | printf("Failed to rename %s: %s\n", oldPath.UTF8String, 53 | error.localizedDescription.UTF8String); 54 | return 1; 55 | } 56 | } 57 | 58 | NSString *dpkgInfo = 59 | [NSString stringWithContentsOfFile:@"/var/lib/dpkg/info/kr.xsf1re.vnodebypass.list" 60 | encoding:NSUTF8StringEncoding 61 | error:nil]; 62 | dpkgInfo = [dpkgInfo stringByReplacingOccurrencesOfString:@"vnodebypass" withString:randomName]; 63 | [dpkgInfo writeToFile:@"/var/lib/dpkg/info/kr.xsf1re.vnodebypass.list" 64 | atomically:YES 65 | encoding:NSUTF8StringEncoding 66 | error:nil]; 67 | 68 | task.arguments = @[ @"-p", [NSString stringWithFormat:@"/Applications/%@.app", randomName] ]; 69 | [task launch]; 70 | [task waitUntilExit]; 71 | return 0; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ent.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | get-task-allow 6 | 7 | task_for_pid-allow 8 | 9 | platform-application 10 | 11 | com.apple.private.security.no-container 12 | 13 | com.apple.private.kernel.get-kext-info 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /include/NSTask.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSTask.h 3 | // ipacracker 4 | // 5 | // Created by obaby on 14-2-10. 6 | // 7 | // 8 | /* NSTask.h 9 | Copyright (c) 1996-2007, Apple Inc. All rights reserved. 10 | */ 11 | 12 | #import 13 | 14 | @class NSString, NSArray, NSDictionary; 15 | 16 | @interface NSTask : NSObject 17 | 18 | // Create an NSTask which can be run at a later time 19 | // An NSTask can only be run once. Subsequent attempts to 20 | // run an NSTask will raise. 21 | // Upon task death a notification will be sent 22 | // { Name = NSTaskDidTerminateNotification; object = task; } 23 | // 24 | 25 | - (instancetype)init; 26 | 27 | // set parameters 28 | // these methods can only be done before a launch 29 | // if not set, use current 30 | // if not set, use current 31 | 32 | // set standard I/O channels; may be either an NSFileHandle or an NSPipe 33 | - (void)setStandardInput:(id)input; 34 | - (void)setStandardOutput:(id)output; 35 | - (void)setStandardError:(id)error; 36 | 37 | // get parameters 38 | @property (NS_NONATOMIC_IOSONLY, copy) NSString *launchPath; 39 | @property (NS_NONATOMIC_IOSONLY, copy) NSArray *arguments; 40 | @property (NS_NONATOMIC_IOSONLY, copy) NSDictionary *environment; 41 | @property (NS_NONATOMIC_IOSONLY, copy) NSString *currentDirectoryPath; 42 | 43 | // get standard I/O channels; could be either an NSFileHandle or an NSPipe 44 | - (id)standardInput; 45 | - (id)standardOutput; 46 | - (id)standardError; 47 | 48 | // actions 49 | - (void)launch; 50 | 51 | - (void)interrupt; // Not always possible. Sends SIGINT. 52 | - (void)terminate; // Not always possible. Sends SIGTERM. 53 | 54 | @property (NS_NONATOMIC_IOSONLY, readonly) BOOL suspend; 55 | @property (NS_NONATOMIC_IOSONLY, readonly) BOOL resume; 56 | 57 | // status 58 | @property (NS_NONATOMIC_IOSONLY, readonly) int processIdentifier; 59 | @property (NS_NONATOMIC_IOSONLY, getter=isRunning, readonly) BOOL running; 60 | 61 | @property (NS_NONATOMIC_IOSONLY, readonly) int terminationStatus; 62 | 63 | @end 64 | 65 | @interface NSTask (NSTaskConveniences) 66 | 67 | + (NSTask *)launchedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)arguments; 68 | // convenience; create and launch 69 | 70 | - (void)waitUntilExit; 71 | // poll the runLoop in defaultMode until task completes 72 | 73 | @end 74 | 75 | FOUNDATION_EXPORT NSString * const NSTaskDidTerminateNotification; 76 | 77 | -------------------------------------------------------------------------------- /kernel.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #include 4 | #include 5 | #include 6 | #include "libdimentio.h" 7 | 8 | uint32_t off_p_pid; 9 | uint32_t off_p_pfd; 10 | uint32_t off_fd_ofiles; 11 | uint32_t off_fp_fglob; 12 | uint32_t off_fg_data; 13 | uint32_t off_vnode_iocount; 14 | uint32_t off_vnode_usecount; 15 | uint32_t off_vnode_vflags; 16 | 17 | int offset_init(); 18 | 19 | //get vnode 20 | uint64_t get_vnode_with_file_index(int, uint64_t); 21 | 22 | //hide and show file using vnode 23 | void hide_path(uint64_t); 24 | void show_path(uint64_t); 25 | 26 | int init_kernel(); 27 | -------------------------------------------------------------------------------- /kernel.m: -------------------------------------------------------------------------------- 1 | #include "kernel.h" 2 | 3 | //set offset 4 | #define kCFCoreFoundationVersionNumber_iOS_12_0 (1535.12) 5 | #define kCFCoreFoundationVersionNumber_iOS_13_0_b2 (1656) 6 | #define kCFCoreFoundationVersionNumber_iOS_13_0_b1 (1652.20) 7 | #define kCFCoreFoundationVersionNumber_iOS_14_0_b1 (1740) 8 | 9 | uint32_t off_p_pid = 0; 10 | uint32_t off_p_pfd = 0; 11 | uint32_t off_fd_ofiles = 0; 12 | uint32_t off_fp_fglob = 0; 13 | uint32_t off_fg_data = 0; 14 | uint32_t off_vnode_iocount = 0; 15 | uint32_t off_vnode_usecount = 0; 16 | uint32_t off_vnode_vflags = 0; 17 | 18 | int offset_init() { 19 | if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_14_0_b1) { 20 | // ios 14 21 | printf("iOS 14.x offset selected!!!\n"); 22 | off_p_pid = 0x68; 23 | off_p_pfd = 0xf8; 24 | off_fd_ofiles = 0x0; 25 | off_fp_fglob = 0x10; 26 | off_fg_data = 0x38; 27 | off_vnode_iocount = 0x64; 28 | off_vnode_usecount = 0x60; 29 | off_vnode_vflags = 0x54; 30 | return 0; 31 | } 32 | 33 | if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_13_0_b2) { 34 | // ios 13 35 | printf("iOS 13.x offset selected!!!\n"); 36 | off_p_pid = 0x68; 37 | off_p_pfd = 0x108; 38 | off_fd_ofiles = 0x0; 39 | off_fp_fglob = 0x10; 40 | off_fg_data = 0x38; 41 | off_vnode_iocount = 0x64; 42 | off_vnode_usecount = 0x60; 43 | off_vnode_vflags = 0x54; 44 | return 0; 45 | } 46 | 47 | if(kCFCoreFoundationVersionNumber <= kCFCoreFoundationVersionNumber_iOS_13_0_b1 48 | && kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_12_0) { 49 | //ios 12 50 | printf("iOS 12.x offset selected!!!\n"); 51 | off_p_pid = 0x60; 52 | off_p_pfd = 0x100; 53 | off_fd_ofiles = 0x0; 54 | off_fp_fglob = 0x8; 55 | off_fg_data = 0x38; 56 | off_vnode_iocount = 0x64; 57 | off_vnode_usecount = 0x60; 58 | off_vnode_vflags = 0x54; 59 | return 0; 60 | } 61 | 62 | return -1; 63 | } 64 | 65 | //get vnode 66 | uint64_t get_vnode_with_file_index(int file_index, uint64_t proc) { 67 | uint64_t filedesc = kernel_read64(proc + off_p_pfd); 68 | uint64_t fileproc = kernel_read64(filedesc + off_fd_ofiles); 69 | uint64_t openedfile = kernel_read64(fileproc + (sizeof(void*) * file_index)); 70 | uint64_t fileglob = kernel_read64(openedfile + off_fp_fglob); 71 | uint64_t vnode = kernel_read64(fileglob + off_fg_data); 72 | 73 | uint32_t usecount = kernel_read32(vnode + off_vnode_usecount); 74 | uint32_t iocount = kernel_read32(vnode + off_vnode_iocount); 75 | 76 | kernel_write32(vnode + off_vnode_usecount, usecount + 1); 77 | kernel_write32(vnode + off_vnode_iocount, iocount + 1); 78 | 79 | return vnode; 80 | } 81 | 82 | //hide and show file using vnode 83 | #define VISSHADOW 0x008000 84 | void hide_path(uint64_t vnode){ 85 | uint32_t v_flags = kernel_read32(vnode + off_vnode_vflags); 86 | kernel_write32(vnode + off_vnode_vflags, (v_flags | VISSHADOW)); 87 | } 88 | 89 | void show_path(uint64_t vnode){ 90 | uint32_t v_flags = kernel_read32(vnode + off_vnode_vflags); 91 | kernel_write32(vnode + off_vnode_vflags, (v_flags &= ~VISSHADOW)); 92 | } 93 | 94 | int init_kernel() { 95 | 96 | printf("======= init_kernel =======\n"); 97 | 98 | if(dimentio_init(0, NULL, NULL) != KERN_SUCCESS) { 99 | printf("failed dimentio_init!\n"); 100 | return 1; 101 | } 102 | 103 | // if(init_tfp0() != KERN_SUCCESS) { 104 | // printf("failed get_tfp0!\n"); 105 | // return 1; 106 | // } 107 | // 108 | if(kbase == 0) { 109 | printf("failed get_kbase\n"); 110 | return 1; 111 | } 112 | 113 | kern_return_t err = offset_init(); 114 | if (err) { 115 | printf("offset init failed: %d\n", err); 116 | return 1; 117 | } 118 | 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /layout/usr/share/vnodebypass/hidePathList.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | /.bootstrapped_electra 6 | /Applications/Anemone.app 7 | /Applications/Cydia.app 8 | /Applications/SafeMode.app 9 | /Applications/Sileo.app 10 | /Applications/Zebra.app 11 | /bin/bash 12 | /bin/bunzip2 13 | /bin/bzip2 14 | /bin/cat 15 | /bin/chgrp 16 | /bin/chmod 17 | /bin/chown 18 | /bin/cp 19 | /bin/grep 20 | /bin/gzip 21 | /bin/kill 22 | /bin/ln 23 | /bin/ls 24 | /bin/mkdir 25 | /bin/mv 26 | /bin/sed 27 | /bin/sh 28 | /bin/su 29 | /bin/tar 30 | /binpack 31 | /bootstrap 32 | /chimera 33 | /electra 34 | /etc/apt 35 | /etc/profile 36 | /jb 37 | /Library/dpkg/info/com.inoahdev.launchinsafemode.list 38 | /Library/dpkg/info/com.inoahdev.launchinsafemode.md5sums 39 | /Library/Frameworks/CydiaSubstrate.framework 40 | /Library/MobileSubstrate/DynamicLibraries/FlyJB.dylb 41 | /Library/MobileSubstrate/MobileSubstrate.dylib 42 | /Library/PreferenceBundles/LaunchInSafeMode.bundle 43 | /Library/PreferenceLoader/Preferences/LaunchInSafeMode.plist 44 | /Library/Themes 45 | /private/var/binpack 46 | /private/var/checkra1n.dmg 47 | /private/var/lib/apt 48 | /usr/bin/diff 49 | /usr/bin/hostinfo 50 | /usr/bin/killall 51 | /usr/bin/passwd 52 | /usr/bin/recache 53 | /usr/bin/tar 54 | /usr/bin/which 55 | /usr/bin/xargs 56 | /usr/lib/libjailbreak.dylib 57 | /usr/lib/libsubstitute.0.dylib 58 | /usr/lib/libsubstitute.dylib 59 | /usr/lib/libsubstrate.dylib 60 | /usr/lib/substitute-loader.dylib 61 | /usr/lib/SBInject 62 | /usr/lib/SBInject.dylib 63 | /usr/lib/TweakInject 64 | /usr/lib/TweakInject.dylib 65 | /usr/lib/TweakInjectMapsCheck.dylib 66 | /usr/libexec/sftp-server 67 | /usr/sbin/sshd 68 | /usr/share/terminfo 69 | /var/mobile/Library/.sbinjectSafeMode 70 | /var/mobile/fakevar 71 | /var/MobileSoftwareUpdate/mnt1/fakevar 72 | /var/mobile/Library/Preferences/jp.akusio.kernbypass.plist 73 | /var/mobile/Library/Preferences/jp.akusio.kernbypass-unofficial.plist 74 | /var/mobile/Library/Preferences/jp.akusio.kernbypass2.plist 75 | 76 | 77 | -------------------------------------------------------------------------------- /libdimentio.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2020 0x7ff 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #include "libdimentio.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define LZSS_F (18) 26 | #define LZSS_N (4096) 27 | #define LZSS_THRESHOLD (2) 28 | #define IPC_ENTRY_SZ (0x18) 29 | #define OS_STRING_LEN_OFF (0xC) 30 | #define KCOMP_HDR_PAD_SZ (0x16C) 31 | #define OS_STRING_STRING_OFF (0x10) 32 | #define IPC_SPACE_IS_TABLE_OFF (0x20) 33 | #define IPC_ENTRY_IE_OBJECT_OFF (0x0) 34 | #define PROC_P_LIST_LE_PREV_OFF (0x8) 35 | #define OS_DICTIONARY_COUNT_OFF (0x14) 36 | #define IPC_PORT_IP_KOBJECT_OFF (0x68) 37 | #define PROC_P_LIST_LH_FIRST_OFF (0x0) 38 | #define PREBOOT_PATH "/private/preboot/" 39 | #define IPC_SPACE_IS_TABLE_SZ_OFF (0x14) 40 | #define OS_DICTIONARY_DICT_ENTRY_OFF (0x20) 41 | #define OS_STRING_LEN(a) extract32(a, 14, 18) 42 | #define LOADED_KEXT_SUMMARY_HDR_NAME_OFF (0x10) 43 | #define LOADED_KEXT_SUMMARY_HDR_ADDR_OFF (0x60) 44 | #define APPLE_MOBILE_AP_NONCE_CLEAR_NONCE_SEL (0xC9) 45 | #define APPLE_MOBILE_AP_NONCE_GENERATE_NONCE_SEL (0xC8) 46 | #define kCFCoreFoundationVersionNumber_iOS_10_0_b5 (1348) 47 | #define kCFCoreFoundationVersionNumber_iOS_13_0_b2 (1656) 48 | #define kCFCoreFoundationVersionNumber_iOS_14_0_b1 (1740) 49 | #define kCFCoreFoundationVersionNumber_iOS_11_0_b1 (1429.15) 50 | #define kCFCoreFoundationVersionNumber_iOS_12_0_b1 (1535.13) 51 | #define kCFCoreFoundationVersionNumber_iOS_13_0_b1 (1652.20) 52 | #define kCFCoreFoundationVersionNumber_iOS_14_3_b1 (1770.300) 53 | #define BOOT_PATH "/System/Library/Caches/com.apple.kernelcaches/kernelcache" 54 | 55 | #define DER_INT (0x2U) 56 | #define DER_SEQ (0x30U) 57 | #define DER_IA5_STR (0x16U) 58 | #define DER_OCTET_STR (0x4U) 59 | #define RD(a) extract32(a, 0, 5) 60 | #define RN(a) extract32(a, 5, 5) 61 | #define VM_KERN_MEMORY_OSKEXT (5) 62 | #define KCOMP_HDR_MAGIC (0x636F6D70U) 63 | #define ADRP_ADDR(a) ((a) & ~0xFFFULL) 64 | #define ADRP_IMM(a) (ADR_IMM(a) << 12U) 65 | #define IO_OBJECT_NULL ((io_object_t)0) 66 | #define ADD_X_IMM(a) extract32(a, 10, 12) 67 | #define kIODeviceTreePlane "IODeviceTree" 68 | #define KCOMP_HDR_TYPE_LZSS (0x6C7A7373U) 69 | #define LDR_X_IMM(a) (sextract64(a, 5, 19) << 2U) 70 | #define kOSBundleLoadAddressKey "OSBundleLoadAddress" 71 | #define IS_ADR(a) (((a) & 0x9F000000U) == 0x10000000U) 72 | #define IS_ADRP(a) (((a) & 0x9F000000U) == 0x90000000U) 73 | #define IS_LDR_X(a) (((a) & 0xFF000000U) == 0x58000000U) 74 | #define IS_ADD_X(a) (((a) & 0xFFC00000U) == 0x91000000U) 75 | #define LDR_W_UNSIGNED_IMM(a) (extract32(a, 10, 12) << 2U) 76 | #define LDR_X_UNSIGNED_IMM(a) (extract32(a, 10, 12) << 3U) 77 | #define kBootNoncePropertyKey "com.apple.System.boot-nonce" 78 | #define kIONVRAMDeletePropertyKey "IONVRAM-DELETE-PROPERTY" 79 | #define IS_LDR_W_UNSIGNED_IMM(a) (((a) & 0xFFC00000U) == 0xB9400000U) 80 | #define IS_LDR_X_UNSIGNED_IMM(a) (((a) & 0xFFC00000U) == 0xF9400000U) 81 | #define ADR_IMM(a) ((sextract64(a, 5, 19) << 2U) | extract32(a, 29, 2)) 82 | #define kIONVRAMForceSyncNowPropertyKey "IONVRAM-FORCESYNCNOW-PROPERTY" 83 | 84 | #ifndef SECT_CSTRING 85 | # define SECT_CSTRING "__cstring" 86 | #endif 87 | 88 | #ifndef SEG_TEXT_EXEC 89 | # define SEG_TEXT_EXEC "__TEXT_EXEC" 90 | #endif 91 | 92 | typedef char io_string_t[512]; 93 | typedef mach_port_t io_object_t; 94 | typedef uint32_t IOOptionBits, ipc_entry_num_t; 95 | typedef io_object_t io_service_t, io_connect_t, io_registry_entry_t; 96 | typedef kern_return_t (*kernrw_0_kbase_func_t)(kaddr_t *), (*kernrw_0_kread_func_t)(kaddr_t, void *, size_t), (*kernrw_0_kwrite_func_t)(kaddr_t, const void *, size_t); 97 | typedef int (*krw_0_kbase_func_t)(kaddr_t *), (*krw_0_kread_func_t)(kaddr_t, void *, size_t), (*krw_0_kwrite_func_t)(const void *, kaddr_t, size_t), (*kernrw_0_req_kernrw_func_t)(void); 98 | 99 | typedef struct { 100 | struct section_64 s64; 101 | const char *data; 102 | } sec_64_t; 103 | 104 | typedef struct { 105 | struct symtab_command cmd_symtab; 106 | sec_64_t sec_text, sec_cstring; 107 | kaddr_t base, kslide; 108 | const char *kernel; 109 | size_t kernel_sz; 110 | char *data; 111 | } pfinder_t; 112 | 113 | kern_return_t 114 | IOServiceClose(io_connect_t); 115 | 116 | kern_return_t 117 | IOObjectRelease(io_object_t); 118 | 119 | CFMutableDictionaryRef 120 | IOServiceMatching(const char *); 121 | 122 | CFDictionaryRef 123 | OSKextCopyLoadedKextInfo(CFArrayRef, CFArrayRef); 124 | 125 | io_registry_entry_t 126 | IORegistryEntryFromPath(mach_port_t, const io_string_t); 127 | 128 | io_service_t 129 | IOServiceGetMatchingService(mach_port_t, CFDictionaryRef); 130 | 131 | kern_return_t 132 | IOServiceOpen(io_service_t, task_port_t, uint32_t, io_connect_t *); 133 | 134 | kern_return_t 135 | IORegistryEntrySetCFProperty(io_registry_entry_t, CFStringRef, CFTypeRef); 136 | 137 | kern_return_t 138 | mach_vm_write(vm_map_t, mach_vm_address_t, vm_offset_t, mach_msg_type_number_t); 139 | 140 | kern_return_t 141 | IOConnectCallStructMethod(io_connect_t, uint32_t, const void *, size_t, void *, size_t *); 142 | 143 | CFTypeRef 144 | IORegistryEntryCreateCFProperty(io_registry_entry_t, CFStringRef, CFAllocatorRef, IOOptionBits); 145 | 146 | kern_return_t 147 | mach_vm_read_overwrite(vm_map_t, mach_vm_address_t, mach_vm_size_t, mach_vm_address_t, mach_vm_size_t *); 148 | 149 | kern_return_t 150 | mach_vm_machine_attribute(vm_map_t, mach_vm_address_t, mach_vm_size_t, vm_machine_attribute_t, vm_machine_attribute_val_t *); 151 | 152 | kern_return_t 153 | mach_vm_region(vm_map_t, mach_vm_address_t *, mach_vm_size_t *, vm_region_flavor_t, vm_region_info_t, mach_msg_type_number_t *, mach_port_t *); 154 | 155 | extern const mach_port_t kIOMasterPortDefault; 156 | static void *krw_0, *kernrw_0; 157 | 158 | static kread_func_t kread_buf; 159 | task_t tfp0 = TASK_NULL; 160 | static kwrite_func_t kwrite_buf; 161 | kaddr_t kbase, kslide, this_proc, our_task; 162 | static kaddr_t kernproc; 163 | static kernrw_0_kread_func_t kernrw_0_kread; 164 | static kernrw_0_kwrite_func_t kernrw_0_kwrite; 165 | static size_t proc_task_off, proc_p_pid_off, task_itk_space_off, io_dt_nvram_of_dict_off; 166 | 167 | static uint32_t 168 | extract32(uint32_t val, unsigned start, unsigned len) { 169 | return (val >> start) & (~0U >> (32U - len)); 170 | } 171 | 172 | static uint64_t 173 | sextract64(uint64_t val, unsigned start, unsigned len) { 174 | return (uint64_t)((int64_t)(val << (64U - len - start)) >> (64U - len)); 175 | } 176 | 177 | static size_t 178 | decompress_lzss(const uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len) { 179 | const uint8_t *src_end = src + src_len, *dst_start = dst, *dst_end = dst + dst_len; 180 | uint16_t i, r = LZSS_N - LZSS_F, flags = 0; 181 | uint8_t text_buf[LZSS_N + LZSS_F - 1], j; 182 | 183 | memset(text_buf, ' ', r); 184 | while(src != src_end && dst != dst_end) { 185 | if(((flags >>= 1U) & 0x100U) == 0) { 186 | flags = *src++ | 0xFF00U; 187 | if(src == src_end) { 188 | break; 189 | } 190 | } 191 | if((flags & 1U) != 0) { 192 | text_buf[r++] = *dst++ = *src++; 193 | r &= LZSS_N - 1U; 194 | } else { 195 | i = *src++; 196 | if(src == src_end) { 197 | break; 198 | } 199 | j = *src++; 200 | i |= (j & 0xF0U) << 4U; 201 | j = (j & 0xFU) + LZSS_THRESHOLD; 202 | do { 203 | *dst++ = text_buf[r++] = text_buf[i++ & (LZSS_N - 1U)]; 204 | r &= LZSS_N - 1U; 205 | } while(j-- != 0 && dst != dst_end); 206 | } 207 | } 208 | return (size_t)(dst - dst_start); 209 | } 210 | 211 | static const uint8_t * 212 | der_decode(uint8_t tag, const uint8_t *der, const uint8_t *der_end, size_t *out_len) { 213 | size_t der_len; 214 | 215 | if(der_end - der > 2 && tag == *der++) { 216 | if(((der_len = *der++) & 0x80U) != 0) { 217 | *out_len = 0; 218 | if((der_len &= 0x7FU) <= sizeof(*out_len) && (size_t)(der_end - der) >= der_len) { 219 | while(der_len-- != 0) { 220 | *out_len = (*out_len << 8U) | *der++; 221 | } 222 | } 223 | } else { 224 | *out_len = der_len; 225 | } 226 | if(*out_len != 0 && (size_t)(der_end - der) >= *out_len) { 227 | return der; 228 | } 229 | } 230 | return NULL; 231 | } 232 | 233 | static const uint8_t * 234 | der_decode_seq(const uint8_t *der, const uint8_t *der_end, const uint8_t **seq_end) { 235 | size_t der_len; 236 | 237 | if((der = der_decode(DER_SEQ, der, der_end, &der_len)) != NULL) { 238 | *seq_end = der + der_len; 239 | } 240 | return der; 241 | } 242 | 243 | static const uint8_t * 244 | der_decode_uint64(const uint8_t *der, const uint8_t *der_end, uint64_t *r) { 245 | size_t der_len; 246 | 247 | if((der = der_decode(DER_INT, der, der_end, &der_len)) != NULL && (*der & 0x80U) == 0 && (der_len <= sizeof(*r) || (--der_len == sizeof(*r) && *der++ == 0))) { 248 | *r = 0; 249 | while(der_len-- != 0) { 250 | *r = (*r << 8U) | *der++; 251 | } 252 | return der; 253 | } 254 | return NULL; 255 | } 256 | 257 | static void * 258 | kdecompress(const void *src, size_t src_len, size_t *dst_len) { 259 | const uint8_t *der, *octet, *der_end, *src_end = (const uint8_t *)src + src_len; 260 | struct { 261 | uint32_t magic, type, adler32, uncomp_sz, comp_sz; 262 | uint8_t pad[KCOMP_HDR_PAD_SZ]; 263 | } kcomp_hdr; 264 | size_t der_len; 265 | uint64_t r; 266 | void *dst; 267 | 268 | if((der = der_decode_seq(src, src_end, &der_end)) != NULL && (der = der_decode(DER_IA5_STR, der, der_end, &der_len)) != NULL && der_len == 4 && (memcmp(der, "IMG4", der_len) != 0 || ((der = der_decode_seq(der + der_len, src_end, &der_end)) != NULL && (der = der_decode(DER_IA5_STR, der, der_end, &der_len)) != NULL && der_len == 4)) && memcmp(der, "IM4P", der_len) == 0 && (der = der_decode(DER_IA5_STR, der + der_len, der_end, &der_len)) != NULL && der_len == 4 && memcmp(der, "krnl", der_len) == 0 && (der = der_decode(DER_IA5_STR, der + der_len, der_end, &der_len)) != NULL && (der = der_decode(DER_OCTET_STR, der + der_len, der_end, &der_len)) != NULL && der_len > sizeof(kcomp_hdr)) { 269 | octet = der; 270 | memcpy(&kcomp_hdr, octet, sizeof(kcomp_hdr)); 271 | if(kcomp_hdr.magic == __builtin_bswap32(KCOMP_HDR_MAGIC)) { 272 | if(kcomp_hdr.type == __builtin_bswap32(KCOMP_HDR_TYPE_LZSS) && (kcomp_hdr.comp_sz = __builtin_bswap32(kcomp_hdr.comp_sz)) <= der_len - sizeof(kcomp_hdr) && (kcomp_hdr.uncomp_sz = __builtin_bswap32(kcomp_hdr.uncomp_sz)) != 0 && (dst = malloc(kcomp_hdr.uncomp_sz)) != NULL) { 273 | if(decompress_lzss(octet + sizeof(kcomp_hdr), kcomp_hdr.comp_sz, dst, kcomp_hdr.uncomp_sz) == kcomp_hdr.uncomp_sz) { 274 | *dst_len = kcomp_hdr.uncomp_sz; 275 | return dst; 276 | } 277 | free(dst); 278 | } 279 | } else if((der = der_decode_seq(der + der_len, src_end, &der_end)) != NULL && (der = der_decode_uint64(der, der_end, &r)) != NULL && r == 1 && der_decode_uint64(der, der_end, &r) != NULL && r != 0 && (dst = malloc(r)) != NULL) { 280 | if(compression_decode_buffer(dst, r, octet, der_len, NULL, COMPRESSION_LZFSE) == r) { 281 | *dst_len = r; 282 | return dst; 283 | } 284 | free(dst); 285 | } 286 | } 287 | return NULL; 288 | } 289 | 290 | static kern_return_t 291 | kread_buf_krw_0(kaddr_t addr, void *buf, mach_vm_size_t sz) { 292 | static krw_0_kread_func_t krw_0_kread; 293 | 294 | return (krw_0_kread != NULL || (krw_0_kread = (krw_0_kread_func_t)dlsym(krw_0, "kread")) != NULL) && krw_0_kread(addr, buf, sz) == 0 ? KERN_SUCCESS : KERN_FAILURE; 295 | } 296 | 297 | static kern_return_t 298 | kwrite_buf_krw_0(kaddr_t addr, const void *buf, mach_msg_type_number_t sz) { 299 | static krw_0_kwrite_func_t krw_0_kwrite; 300 | 301 | return (krw_0_kwrite != NULL || (krw_0_kwrite = (krw_0_kwrite_func_t)dlsym(krw_0, "kwrite")) != NULL) && krw_0_kwrite(buf, addr, sz) == 0 ? KERN_SUCCESS : KERN_FAILURE; 302 | } 303 | 304 | static kern_return_t 305 | kread_buf_kernrw_0(kaddr_t addr, void *buf, mach_vm_size_t sz) { 306 | return kernrw_0_kread(addr, buf, sz); 307 | } 308 | 309 | static kern_return_t 310 | kwrite_buf_kernrw_0(kaddr_t addr, const void *buf, mach_msg_type_number_t sz) { 311 | return kernrw_0_kwrite(addr, buf, sz); 312 | } 313 | 314 | kern_return_t 315 | init_tfp0(void) { 316 | kern_return_t ret = task_for_pid(mach_task_self(), 0, &tfp0); 317 | mach_port_t host; 318 | 319 | if(ret != KERN_SUCCESS) { 320 | host = mach_host_self(); 321 | if(MACH_PORT_VALID(host)) { 322 | printf("host: 0x%" PRIX32 "\n", host); 323 | ret = host_get_special_port(host, HOST_LOCAL_NODE, 4, &tfp0); 324 | mach_port_deallocate(mach_task_self(), host); 325 | } 326 | } 327 | if(ret == KERN_SUCCESS && MACH_PORT_VALID(tfp0)) { 328 | return ret; 329 | } 330 | return KERN_FAILURE; 331 | } 332 | 333 | kern_return_t 334 | kread_buf_tfp0(kaddr_t addr, void *buf, mach_vm_size_t sz) { 335 | mach_vm_address_t p = (mach_vm_address_t)buf; 336 | mach_vm_size_t read_sz, out_sz = 0; 337 | 338 | while(sz != 0) { 339 | read_sz = MIN(sz, vm_kernel_page_size - (addr & vm_kernel_page_mask)); 340 | if(mach_vm_read_overwrite(tfp0, addr, read_sz, p, &out_sz) != KERN_SUCCESS || out_sz != read_sz) { 341 | return KERN_FAILURE; 342 | } 343 | p += read_sz; 344 | sz -= read_sz; 345 | addr += read_sz; 346 | } 347 | return KERN_SUCCESS; 348 | } 349 | 350 | kern_return_t 351 | kread_addr(kaddr_t addr, kaddr_t *val) { 352 | return kread_buf(addr, val, sizeof(*val)); 353 | } 354 | 355 | kern_return_t 356 | kwrite_buf_tfp0(kaddr_t addr, const void *buf, mach_msg_type_number_t sz) { 357 | vm_machine_attribute_val_t mattr_val = MATTR_VAL_CACHE_FLUSH; 358 | mach_vm_address_t p = (mach_vm_address_t)buf; 359 | mach_msg_type_number_t write_sz; 360 | 361 | while(sz != 0) { 362 | write_sz = (mach_msg_type_number_t)MIN(sz, vm_kernel_page_size - (addr & vm_kernel_page_mask)); 363 | if(mach_vm_write(tfp0, addr, p, write_sz) != KERN_SUCCESS || mach_vm_machine_attribute(tfp0, addr, write_sz, MATTR_CACHE, &mattr_val) != KERN_SUCCESS) { 364 | return KERN_FAILURE; 365 | } 366 | p += write_sz; 367 | sz -= write_sz; 368 | addr += write_sz; 369 | } 370 | return KERN_SUCCESS; 371 | } 372 | 373 | static kern_return_t 374 | find_section(const char *p, struct segment_command_64 sg64, const char *sect_name, struct section_64 *sp) { 375 | for(; sg64.nsects-- != 0; p += sizeof(*sp)) { 376 | memcpy(sp, p, sizeof(*sp)); 377 | if((sp->flags & SECTION_TYPE) != S_ZEROFILL) { 378 | if(sp->offset < sg64.fileoff || sp->size > sg64.filesize || sp->offset - sg64.fileoff > sg64.filesize - sp->size) { 379 | break; 380 | } 381 | if(sp->size != 0 && strncmp(sp->segname, sg64.segname, sizeof(sp->segname)) == 0 && strncmp(sp->sectname, sect_name, sizeof(sp->sectname)) == 0) { 382 | return KERN_SUCCESS; 383 | } 384 | } 385 | } 386 | return KERN_FAILURE; 387 | } 388 | 389 | static void 390 | sec_reset(sec_64_t *sec) { 391 | memset(&sec->s64, '\0', sizeof(sec->s64)); 392 | sec->data = NULL; 393 | } 394 | 395 | static kern_return_t 396 | sec_read_buf(sec_64_t sec, kaddr_t addr, void *buf, size_t sz) { 397 | size_t off; 398 | 399 | if(addr < sec.s64.addr || sz > sec.s64.size || (off = addr - sec.s64.addr) > sec.s64.size - sz) { 400 | return KERN_FAILURE; 401 | } 402 | memcpy(buf, sec.data + off, sz); 403 | return KERN_SUCCESS; 404 | } 405 | 406 | static void 407 | pfinder_reset(pfinder_t *pfinder) { 408 | pfinder->base = 0; 409 | pfinder->kslide = 0; 410 | pfinder->data = NULL; 411 | pfinder->kernel = NULL; 412 | pfinder->kernel_sz = 0; 413 | sec_reset(&pfinder->sec_text); 414 | sec_reset(&pfinder->sec_cstring); 415 | memset(&pfinder->cmd_symtab, '\0', sizeof(pfinder->cmd_symtab)); 416 | } 417 | 418 | static void 419 | pfinder_term(pfinder_t *pfinder) { 420 | free(pfinder->data); 421 | pfinder_reset(pfinder); 422 | } 423 | 424 | static kern_return_t 425 | pfinder_init_file(pfinder_t *pfinder, const char *filename) { 426 | struct symtab_command cmd_symtab; 427 | kern_return_t ret = KERN_FAILURE; 428 | struct segment_command_64 sg64; 429 | struct mach_header_64 mh64; 430 | struct load_command lc; 431 | struct section_64 s64; 432 | struct fat_header fh; 433 | struct stat stat_buf; 434 | struct fat_arch fa; 435 | const char *p, *e; 436 | size_t len; 437 | void *m; 438 | int fd; 439 | 440 | pfinder_reset(pfinder); 441 | if((fd = open(filename, O_RDONLY | O_CLOEXEC)) != -1) { 442 | if(fstat(fd, &stat_buf) != -1 && S_ISREG(stat_buf.st_mode) && stat_buf.st_size > 0) { 443 | len = (size_t)stat_buf.st_size; 444 | if((m = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0)) != MAP_FAILED) { 445 | if((pfinder->data = kdecompress(m, len, &pfinder->kernel_sz)) != NULL && pfinder->kernel_sz > sizeof(fh) + sizeof(mh64)) { 446 | pfinder->kernel = pfinder->data; 447 | memcpy(&fh, pfinder->kernel, sizeof(fh)); 448 | if(fh.magic == __builtin_bswap32(FAT_MAGIC) && (fh.nfat_arch = __builtin_bswap32(fh.nfat_arch)) < (pfinder->kernel_sz - sizeof(fh)) / sizeof(fa)) { 449 | for(p = pfinder->kernel + sizeof(fh); fh.nfat_arch-- != 0; p += sizeof(fa)) { 450 | memcpy(&fa, p, sizeof(fa)); 451 | if(fa.cputype == (cpu_type_t)__builtin_bswap32(CPU_TYPE_ARM64) && (fa.offset = __builtin_bswap32(fa.offset)) < pfinder->kernel_sz && (fa.size = __builtin_bswap32(fa.size)) <= pfinder->kernel_sz - fa.offset && fa.size > sizeof(mh64)) { 452 | pfinder->kernel_sz = fa.size; 453 | pfinder->kernel += fa.offset; 454 | break; 455 | } 456 | } 457 | } 458 | memcpy(&mh64, pfinder->kernel, sizeof(mh64)); 459 | if(mh64.magic == MH_MAGIC_64 && mh64.cputype == CPU_TYPE_ARM64 && mh64.filetype == MH_EXECUTE && mh64.sizeofcmds < pfinder->kernel_sz - sizeof(mh64)) { 460 | for(p = pfinder->kernel + sizeof(mh64), e = p + mh64.sizeofcmds; mh64.ncmds-- != 0 && (size_t)(e - p) >= sizeof(lc); p += lc.cmdsize) { 461 | memcpy(&lc, p, sizeof(lc)); 462 | if(lc.cmdsize < sizeof(lc) || (size_t)(e - p) < lc.cmdsize) { 463 | break; 464 | } 465 | if(lc.cmd == LC_SEGMENT_64) { 466 | if(lc.cmdsize < sizeof(sg64)) { 467 | break; 468 | } 469 | memcpy(&sg64, p, sizeof(sg64)); 470 | if(sg64.vmsize == 0) { 471 | continue; 472 | } 473 | if(sg64.nsects != (lc.cmdsize - sizeof(sg64)) / sizeof(s64) || sg64.fileoff > pfinder->kernel_sz || sg64.filesize > pfinder->kernel_sz - sg64.fileoff) { 474 | break; 475 | } 476 | if(sg64.fileoff == 0 && sg64.filesize != 0) { 477 | if(pfinder->base != 0) { 478 | break; 479 | } 480 | pfinder->base = sg64.vmaddr; 481 | printf("base: " KADDR_FMT "\n", sg64.vmaddr); 482 | } 483 | if(strncmp(sg64.segname, SEG_TEXT_EXEC, sizeof(sg64.segname)) == 0) { 484 | if(find_section(p + sizeof(sg64), sg64, SECT_TEXT, &s64) != KERN_SUCCESS) { 485 | break; 486 | } 487 | pfinder->sec_text.s64 = s64; 488 | pfinder->sec_text.data = pfinder->kernel + s64.offset; 489 | printf("sec_text_addr: " KADDR_FMT ", sec_text_off: 0x%" PRIX32 ", sec_text_sz: 0x%" PRIX64 "\n", s64.addr, s64.offset, s64.size); 490 | } else if(strncmp(sg64.segname, SEG_TEXT, sizeof(sg64.segname)) == 0) { 491 | if(find_section(p + sizeof(sg64), sg64, SECT_CSTRING, &s64) != KERN_SUCCESS || pfinder->kernel[s64.offset + s64.size - 1] != '\0') { 492 | break; 493 | } 494 | pfinder->sec_cstring.s64 = s64; 495 | pfinder->sec_cstring.data = pfinder->kernel + s64.offset; 496 | printf("sec_cstring_addr: " KADDR_FMT ", sec_cstring_off: 0x%" PRIX32 ", sec_cstring_sz: 0x%" PRIX64 "\n", s64.addr, s64.offset, s64.size); 497 | } 498 | } else if(lc.cmd == LC_SYMTAB) { 499 | if(lc.cmdsize != sizeof(cmd_symtab)) { 500 | break; 501 | } 502 | memcpy(&cmd_symtab, p, sizeof(cmd_symtab)); 503 | printf("cmd_symtab_symoff: 0x%" PRIX32 ", cmd_symtab_nsyms: 0x%" PRIX32 ", cmd_symtab_stroff: 0x%" PRIX32 "\n", cmd_symtab.symoff, cmd_symtab.nsyms, cmd_symtab.stroff); 504 | if(cmd_symtab.nsyms != 0 && (cmd_symtab.symoff > pfinder->kernel_sz || cmd_symtab.nsyms > (pfinder->kernel_sz - cmd_symtab.symoff) / sizeof(struct nlist_64) || cmd_symtab.stroff > pfinder->kernel_sz || cmd_symtab.strsize > pfinder->kernel_sz - cmd_symtab.stroff || cmd_symtab.strsize == 0 || pfinder->kernel[cmd_symtab.stroff + cmd_symtab.strsize - 1] != '\0')) { 505 | break; 506 | } 507 | pfinder->cmd_symtab = cmd_symtab; 508 | } 509 | if(pfinder->base != 0 && pfinder->sec_text.s64.size != 0 && pfinder->sec_cstring.s64.size != 0 && pfinder->cmd_symtab.cmdsize != 0) { 510 | ret = KERN_SUCCESS; 511 | break; 512 | } 513 | } 514 | } 515 | } 516 | munmap(m, len); 517 | } 518 | } 519 | close(fd); 520 | } 521 | if(ret != KERN_SUCCESS) { 522 | pfinder_term(pfinder); 523 | } 524 | return ret; 525 | } 526 | 527 | static kaddr_t 528 | pfinder_xref_rd(pfinder_t pfinder, uint32_t rd, kaddr_t start, kaddr_t to) { 529 | kaddr_t x[32] = { 0 }; 530 | uint32_t insn; 531 | 532 | for(; sec_read_buf(pfinder.sec_text, start, &insn, sizeof(insn)) == KERN_SUCCESS; start += sizeof(insn)) { 533 | if(IS_LDR_X(insn)) { 534 | x[RD(insn)] = start + LDR_X_IMM(insn); 535 | } else if(IS_ADR(insn)) { 536 | x[RD(insn)] = start + ADR_IMM(insn); 537 | } else if(IS_ADD_X(insn)) { 538 | x[RD(insn)] = x[RN(insn)] + ADD_X_IMM(insn); 539 | } else if(IS_LDR_W_UNSIGNED_IMM(insn)) { 540 | x[RD(insn)] = x[RN(insn)] + LDR_W_UNSIGNED_IMM(insn); 541 | } else if(IS_LDR_X_UNSIGNED_IMM(insn)) { 542 | x[RD(insn)] = x[RN(insn)] + LDR_X_UNSIGNED_IMM(insn); 543 | } else { 544 | if(IS_ADRP(insn)) { 545 | x[RD(insn)] = ADRP_ADDR(start) + ADRP_IMM(insn); 546 | } 547 | continue; 548 | } 549 | if(RD(insn) == rd) { 550 | if(to == 0) { 551 | if(x[rd] < pfinder.base) { 552 | break; 553 | } 554 | return x[rd]; 555 | } 556 | if(x[rd] == to) { 557 | return start; 558 | } 559 | } 560 | } 561 | return 0; 562 | } 563 | 564 | static kaddr_t 565 | pfinder_xref_str(pfinder_t pfinder, const char *str, uint32_t rd) { 566 | const char *p, *e; 567 | size_t len; 568 | 569 | for(p = pfinder.sec_cstring.data, e = p + pfinder.sec_cstring.s64.size; p != e; p += len) { 570 | len = strlen(p) + 1; 571 | if(strncmp(str, p, len) == 0) { 572 | return pfinder_xref_rd(pfinder, rd, pfinder.sec_text.s64.addr, pfinder.sec_cstring.s64.addr + (kaddr_t)(p - pfinder.sec_cstring.data)); 573 | } 574 | } 575 | return 0; 576 | } 577 | 578 | static kaddr_t 579 | pfinder_sym(pfinder_t pfinder, const char *sym) { 580 | const char *p, *strtab = pfinder.kernel + pfinder.cmd_symtab.stroff; 581 | struct nlist_64 nl64; 582 | 583 | for(p = pfinder.kernel + pfinder.cmd_symtab.symoff; pfinder.cmd_symtab.nsyms-- != 0; p += sizeof(nl64)) { 584 | memcpy(&nl64, p, sizeof(nl64)); 585 | if(nl64.n_un.n_strx != 0 && nl64.n_un.n_strx < pfinder.cmd_symtab.strsize && (nl64.n_type & (N_STAB | N_TYPE)) == N_SECT && nl64.n_value >= pfinder.base && strcmp(strtab + nl64.n_un.n_strx, sym) == 0) { 586 | return nl64.n_value + pfinder.kslide; 587 | } 588 | } 589 | return 0; 590 | } 591 | 592 | static kaddr_t 593 | pfinder_kernproc(pfinder_t pfinder) { 594 | kaddr_t ref = pfinder_sym(pfinder, "_kernproc"); 595 | uint32_t insns[2]; 596 | 597 | if(ref != 0) { 598 | return ref; 599 | } 600 | for(ref = pfinder_xref_str(pfinder, "\"Should never have an EVFILT_READ except for reg or fifo.\"", 0); sec_read_buf(pfinder.sec_text, ref, insns, sizeof(insns)) == KERN_SUCCESS; ref -= sizeof(*insns)) { 601 | if(IS_ADRP(insns[0]) && IS_LDR_X_UNSIGNED_IMM(insns[1]) && RD(insns[1]) == 3) { 602 | return pfinder_xref_rd(pfinder, RD(insns[1]), ref, 0); 603 | } 604 | } 605 | return 0; 606 | } 607 | 608 | static kaddr_t 609 | pfinder_init_kbase(pfinder_t *pfinder) { 610 | mach_msg_type_number_t cnt = TASK_DYLD_INFO_COUNT; 611 | kaddr_t kext_addr, kext_addr_slid; 612 | CFDictionaryRef kexts_info, kext_info; 613 | task_dyld_info_data_t dyld_info; 614 | char kext_name[KMOD_MAX_NAME]; 615 | struct mach_header_64 mh64; 616 | CFStringRef kext_name_cf; 617 | CFNumberRef kext_addr_cf; 618 | CFArrayRef kext_names; 619 | 620 | struct { 621 | uint32_t pri_prot, pri_max_prot, pri_inheritance, pri_flags; 622 | uint64_t pri_offset; 623 | uint32_t pri_behavior, pri_user_wired_cnt, pri_user_tag, pri_pages_resident, pri_pages_shared_now_private, pri_pages_swapped_out, pri_pages_dirtied, pri_ref_cnt, pri_shadow_depth, pri_share_mode, pri_private_pages_resident, pri_shared_pages_resident, pri_obj_id, pri_depth; 624 | kaddr_t pri_addr; 625 | uint64_t pri_sz; 626 | } pri; 627 | 628 | if(pfinder->kslide == 0) { 629 | if(task_info(tfp0, TASK_DYLD_INFO, (task_info_t)&dyld_info, &cnt) == KERN_SUCCESS) { 630 | pfinder->kslide = dyld_info.all_image_info_size; 631 | } 632 | if(pfinder->kslide == 0) { 633 | cnt = VM_REGION_EXTENDED_INFO_COUNT; 634 | for(pri.pri_addr = 0; proc_pidinfo(0, PROC_PIDREGIONINFO, pri.pri_addr, &pri, sizeof(pri)) == sizeof(pri); pri.pri_addr += pri.pri_sz) { 635 | if(pri.pri_prot == VM_PROT_READ && pri.pri_user_tag == VM_KERN_MEMORY_OSKEXT) { 636 | if(kread_buf(pri.pri_addr + LOADED_KEXT_SUMMARY_HDR_NAME_OFF, kext_name, sizeof(kext_name)) == KERN_SUCCESS) { 637 | printf("kext_name: %s\n", kext_name); 638 | if(kread_addr(pri.pri_addr + LOADED_KEXT_SUMMARY_HDR_ADDR_OFF, &kext_addr_slid) == KERN_SUCCESS) { 639 | printf("kext_addr_slid: " KADDR_FMT "\n", kext_addr_slid); 640 | if((kext_name_cf = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, kext_name, kCFStringEncodingUTF8, kCFAllocatorNull)) != NULL) { 641 | if((kext_names = CFArrayCreate(kCFAllocatorDefault, (const void **)&kext_name_cf, 1, &kCFTypeArrayCallBacks)) != NULL) { 642 | if((kexts_info = OSKextCopyLoadedKextInfo(kext_names, NULL)) != NULL) { 643 | if(CFGetTypeID(kexts_info) == CFDictionaryGetTypeID() && CFDictionaryGetCount(kexts_info) == 1 && (kext_info = CFDictionaryGetValue(kexts_info, kext_name_cf)) != NULL && CFGetTypeID(kext_info) == CFDictionaryGetTypeID() && (kext_addr_cf = CFDictionaryGetValue(kext_info, CFSTR(kOSBundleLoadAddressKey))) != NULL && CFGetTypeID(kext_addr_cf) == CFNumberGetTypeID() && CFNumberGetValue(kext_addr_cf, kCFNumberSInt64Type, &kext_addr) && kext_addr_slid > kext_addr) { 644 | pfinder->kslide = kext_addr_slid - kext_addr; 645 | } 646 | CFRelease(kexts_info); 647 | } 648 | CFRelease(kext_names); 649 | } 650 | CFRelease(kext_name_cf); 651 | } 652 | } 653 | } 654 | break; 655 | } 656 | } 657 | } 658 | } 659 | if(pfinder->base + pfinder->kslide > pfinder->base && kread_buf(pfinder->base + pfinder->kslide, &mh64, sizeof(mh64)) == KERN_SUCCESS && mh64.magic == MH_MAGIC_64 && mh64.cputype == CPU_TYPE_ARM64 && mh64.filetype == MH_EXECUTE) { 660 | pfinder->sec_text.s64.addr += pfinder->kslide; 661 | pfinder->sec_cstring.s64.addr += pfinder->kslide; 662 | printf("kbase: " KADDR_FMT ", kslide: " KADDR_FMT "\n", pfinder->base + pfinder->kslide, pfinder->kslide); 663 | kbase = pfinder->base + pfinder->kslide; 664 | kslide = pfinder->kslide; 665 | return KERN_SUCCESS; 666 | } 667 | return KERN_FAILURE; 668 | } 669 | 670 | static char * 671 | get_boot_path(void) { 672 | size_t hash_len, path_len = sizeof(BOOT_PATH); 673 | io_registry_entry_t chosen; 674 | struct stat stat_buf; 675 | const uint8_t *hash; 676 | CFDataRef hash_cf; 677 | char *path = NULL; 678 | 679 | if(stat(PREBOOT_PATH, &stat_buf) != -1 && S_ISDIR(stat_buf.st_mode) && (chosen = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/chosen")) != IO_OBJECT_NULL) { 680 | if((hash_cf = IORegistryEntryCreateCFProperty(chosen, CFSTR("boot-manifest-hash"), kCFAllocatorDefault, kNilOptions)) != NULL) { 681 | if(CFGetTypeID(hash_cf) == CFDataGetTypeID() && (hash_len = (size_t)CFDataGetLength(hash_cf) << 1U) != 0) { 682 | path_len += strlen(PREBOOT_PATH) + hash_len; 683 | if((path = malloc(path_len)) != NULL) { 684 | memcpy(path, PREBOOT_PATH, strlen(PREBOOT_PATH)); 685 | for(hash = CFDataGetBytePtr(hash_cf); hash_len-- != 0; ) { 686 | path[strlen(PREBOOT_PATH) + hash_len] = "0123456789ABCDEF"[(hash[hash_len >> 1U] >> ((~hash_len & 1U) << 2U)) & 0xFU]; 687 | } 688 | } 689 | } 690 | CFRelease(hash_cf); 691 | } 692 | IOObjectRelease(chosen); 693 | } 694 | if(path == NULL) { 695 | path_len = sizeof(BOOT_PATH); 696 | path = malloc(path_len); 697 | } 698 | if(path != NULL) { 699 | memcpy(path + (path_len - sizeof(BOOT_PATH)), BOOT_PATH, sizeof(BOOT_PATH)); 700 | } 701 | return path; 702 | } 703 | 704 | kern_return_t 705 | pfinder_init_offsets(void) { 706 | kern_return_t ret = KERN_FAILURE; 707 | pfinder_t pfinder; 708 | char *boot_path; 709 | 710 | proc_task_off = 0x18; 711 | proc_p_pid_off = 0x10; 712 | task_itk_space_off = 0x290; 713 | io_dt_nvram_of_dict_off = 0xC0; 714 | if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_10_0_b5) { 715 | task_itk_space_off = 0x300; 716 | if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_11_0_b1) { 717 | task_itk_space_off = 0x308; 718 | if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_12_0_b1) { 719 | proc_task_off = 0x10; 720 | proc_p_pid_off = 0x60; 721 | task_itk_space_off = 0x300; 722 | if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_13_0_b1) { 723 | task_itk_space_off = 0x320; 724 | if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_13_0_b2) { 725 | proc_p_pid_off = 0x68; 726 | if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_14_0_b1) { 727 | task_itk_space_off = 0x330; 728 | io_dt_nvram_of_dict_off = 0xB8; 729 | if(kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_14_3_b1) { 730 | io_dt_nvram_of_dict_off = 0xC0; 731 | } 732 | } 733 | } 734 | } 735 | } 736 | } 737 | } 738 | if((boot_path = get_boot_path()) != NULL) { 739 | printf("boot_path: %s\n", boot_path); 740 | if(pfinder_init_file(&pfinder, boot_path) == KERN_SUCCESS) { 741 | pfinder.kslide = kslide; 742 | if(pfinder_init_kbase(&pfinder) == KERN_SUCCESS && (kernproc = pfinder_kernproc(pfinder)) != 0) { 743 | printf("kernproc: " KADDR_FMT "\n", kernproc); 744 | ret = KERN_SUCCESS; 745 | } 746 | pfinder_term(&pfinder); 747 | } 748 | free(boot_path); 749 | } 750 | return ret; 751 | } 752 | 753 | kern_return_t 754 | find_task(pid_t pid, kaddr_t *task) { 755 | pid_t cur_pid; 756 | kaddr_t proc; 757 | 758 | if(kread_addr(kernproc + PROC_P_LIST_LH_FIRST_OFF, &proc) == KERN_SUCCESS) { 759 | while(proc != 0 && kread_buf(proc + proc_p_pid_off, &cur_pid, sizeof(cur_pid)) == KERN_SUCCESS) { 760 | if(cur_pid == pid) { 761 | this_proc = proc; 762 | return kread_addr(proc + proc_task_off, task); 763 | } 764 | if(pid == 0 || kread_addr(proc + PROC_P_LIST_LE_PREV_OFF, &proc) != KERN_SUCCESS) { 765 | break; 766 | } 767 | } 768 | } 769 | return KERN_FAILURE; 770 | } 771 | 772 | static kern_return_t 773 | lookup_ipc_port(mach_port_name_t port_name, kaddr_t *ipc_port) { 774 | ipc_entry_num_t port_idx, is_table_sz; 775 | kaddr_t itk_space, is_table; 776 | 777 | if(MACH_PORT_VALID(port_name) && kread_addr(our_task + task_itk_space_off, &itk_space) == KERN_SUCCESS) { 778 | printf("itk_space: " KADDR_FMT "\n", itk_space); 779 | if(kread_buf(itk_space + IPC_SPACE_IS_TABLE_SZ_OFF, &is_table_sz, sizeof(is_table_sz)) == KERN_SUCCESS) { 780 | printf("is_table_sz: 0x%" PRIX32 "\n", is_table_sz); 781 | if((port_idx = MACH_PORT_INDEX(port_name)) < is_table_sz && kread_addr(itk_space + IPC_SPACE_IS_TABLE_OFF, &is_table) == KERN_SUCCESS) { 782 | printf("is_table: " KADDR_FMT "\n", is_table); 783 | return kread_addr(is_table + port_idx * IPC_ENTRY_SZ + IPC_ENTRY_IE_OBJECT_OFF, ipc_port); 784 | } 785 | } 786 | } 787 | return KERN_FAILURE; 788 | } 789 | 790 | static kern_return_t 791 | lookup_io_object(io_object_t object, kaddr_t *ip_kobject) { 792 | kaddr_t ipc_port; 793 | 794 | if(lookup_ipc_port(object, &ipc_port) == KERN_SUCCESS) { 795 | printf("ipc_port: " KADDR_FMT "\n", ipc_port); 796 | return kread_addr(ipc_port + IPC_PORT_IP_KOBJECT_OFF, ip_kobject); 797 | } 798 | return KERN_FAILURE; 799 | } 800 | 801 | static kern_return_t 802 | nonce_generate(io_service_t nonce_serv) { 803 | uint8_t nonce_d[CC_SHA384_DIGEST_LENGTH]; 804 | kern_return_t ret = KERN_FAILURE; 805 | io_connect_t nonce_conn; 806 | size_t nonce_d_sz; 807 | 808 | if(IOServiceOpen(nonce_serv, mach_task_self(), 0, &nonce_conn) == KERN_SUCCESS) { 809 | printf("nonce_conn: 0x%" PRIX32 "\n", nonce_conn); 810 | if(IOConnectCallStructMethod(nonce_conn, APPLE_MOBILE_AP_NONCE_CLEAR_NONCE_SEL, NULL, 0, NULL, NULL) == KERN_SUCCESS) { 811 | nonce_d_sz = sizeof(nonce_d); 812 | ret = IOConnectCallStructMethod(nonce_conn, APPLE_MOBILE_AP_NONCE_GENERATE_NONCE_SEL, NULL, 0, nonce_d, &nonce_d_sz); 813 | } 814 | IOServiceClose(nonce_conn); 815 | } 816 | return ret; 817 | } 818 | 819 | static kern_return_t 820 | get_of_dict(io_service_t nvram_serv, kaddr_t *of_dict) { 821 | kaddr_t nvram_object; 822 | 823 | if(lookup_io_object(nvram_serv, &nvram_object) == KERN_SUCCESS) { 824 | printf("nvram_object: " KADDR_FMT "\n", nvram_object); 825 | return kread_addr(nvram_object + io_dt_nvram_of_dict_off, of_dict); 826 | } 827 | return KERN_FAILURE; 828 | } 829 | 830 | static kaddr_t 831 | lookup_key_in_os_dict(kaddr_t os_dict, const char *key) { 832 | kaddr_t os_dict_entry_ptr, string_ptr, val = 0; 833 | uint32_t os_dict_cnt, cur_key_len; 834 | size_t key_len = strlen(key) + 1; 835 | struct { 836 | kaddr_t key, val; 837 | } os_dict_entry; 838 | char *cur_key; 839 | 840 | if((cur_key = malloc(key_len)) != NULL) { 841 | if(kread_addr(os_dict + OS_DICTIONARY_DICT_ENTRY_OFF, &os_dict_entry_ptr) == KERN_SUCCESS && os_dict_entry_ptr != 0) { 842 | printf("os_dict_entry_ptr: " KADDR_FMT "\n", os_dict_entry_ptr); 843 | if(kread_buf(os_dict + OS_DICTIONARY_COUNT_OFF, &os_dict_cnt, sizeof(os_dict_cnt)) == KERN_SUCCESS) { 844 | printf("os_dict_cnt: 0x%" PRIX32 "\n", os_dict_cnt); 845 | while(os_dict_cnt-- != 0 && kread_buf(os_dict_entry_ptr + os_dict_cnt * sizeof(os_dict_entry), &os_dict_entry, sizeof(os_dict_entry)) == KERN_SUCCESS) { 846 | printf("key: " KADDR_FMT ", val: " KADDR_FMT "\n", os_dict_entry.key, os_dict_entry.val); 847 | if(kread_buf(os_dict_entry.key + OS_STRING_LEN_OFF, &cur_key_len, sizeof(cur_key_len)) != KERN_SUCCESS) { 848 | break; 849 | } 850 | cur_key_len = OS_STRING_LEN(cur_key_len); 851 | printf("cur_key_len: 0x%" PRIX32 "\n", cur_key_len); 852 | if(cur_key_len == key_len) { 853 | if(kread_addr(os_dict_entry.key + OS_STRING_STRING_OFF, &string_ptr) != KERN_SUCCESS || string_ptr == 0) { 854 | break; 855 | } 856 | printf("string_ptr: " KADDR_FMT "\n", string_ptr); 857 | if(kread_buf(string_ptr, cur_key, key_len) != KERN_SUCCESS) { 858 | break; 859 | } 860 | if(memcmp(cur_key, key, key_len) == 0) { 861 | val = os_dict_entry.val; 862 | break; 863 | } 864 | } 865 | } 866 | } 867 | } 868 | free(cur_key); 869 | } 870 | return val; 871 | } 872 | 873 | static kern_return_t 874 | set_nvram_prop(io_service_t nvram_serv, const char *key, const char *val) { 875 | CFStringRef cf_key = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, key, kCFStringEncodingUTF8, kCFAllocatorNull), cf_val; 876 | kern_return_t ret = KERN_FAILURE; 877 | 878 | if(cf_key != NULL) { 879 | if((cf_val = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, val, kCFStringEncodingUTF8, kCFAllocatorNull)) != NULL) { 880 | ret = IORegistryEntrySetCFProperty(nvram_serv, cf_key, cf_val); 881 | CFRelease(cf_val); 882 | } 883 | CFRelease(cf_key); 884 | } 885 | return ret; 886 | } 887 | 888 | static kern_return_t 889 | sync_nonce(io_service_t nvram_serv) { 890 | if(set_nvram_prop(nvram_serv, "temp_key", "temp_val") == KERN_SUCCESS && set_nvram_prop(nvram_serv, kIONVRAMDeletePropertyKey, "temp_key") == KERN_SUCCESS) { 891 | return set_nvram_prop(nvram_serv, kIONVRAMForceSyncNowPropertyKey, kBootNoncePropertyKey); 892 | } 893 | return KERN_FAILURE; 894 | } 895 | 896 | static bool 897 | entangle_nonce(uint64_t nonce, uint8_t entangled_nonce[CC_SHA384_DIGEST_LENGTH]) { 898 | bool ret = false; 899 | #ifdef __arm64e__ 900 | # define IO_AES_ACCELERATOR_SPECIAL_KEYS_OFF (0xD0) 901 | # define IO_AES_ACCELERATOR_SPECIAL_KEY_CNT_OFF (0xD8) 902 | io_service_t aes_serv = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOAESAccelerator")); 903 | struct { 904 | uint32_t generated, key_id, key_sz, val[4], key[4], zero, pad; 905 | } key; 906 | uint64_t buf[] = { 0, nonce }; 907 | kaddr_t aes_object, keys_ptr; 908 | uint32_t key_cnt; 909 | size_t out_sz; 910 | 911 | if(aes_serv != IO_OBJECT_NULL) { 912 | printf("aes_serv: 0x%" PRIX32 "\n", aes_serv); 913 | if(lookup_io_object(aes_serv, &aes_object) == KERN_SUCCESS) { 914 | printf("aes_object: " KADDR_FMT "\n", aes_object); 915 | if(kread_addr(aes_object + IO_AES_ACCELERATOR_SPECIAL_KEYS_OFF, &keys_ptr) == KERN_SUCCESS) { 916 | printf("keys_ptr: " KADDR_FMT "\n", keys_ptr); 917 | if(kread_buf(aes_object + IO_AES_ACCELERATOR_SPECIAL_KEY_CNT_OFF, &key_cnt, sizeof(key_cnt)) == KERN_SUCCESS) { 918 | printf("key_cnt: 0x%" PRIX32 "\n", key_cnt); 919 | for(; key_cnt-- != 0 && kread_buf(keys_ptr, &key, sizeof(key)) == KERN_SUCCESS; keys_ptr += sizeof(key)) { 920 | printf("generated: 0x%" PRIX32 ", key_id: 0x%" PRIX32 ", key_sz: 0x%" PRIX32 "\n", key.generated, key.key_id, key.key_sz); 921 | if(key.generated == 1 && key.key_id == 0x8A3 && key.key_sz == 8 * kCCKeySizeAES128) { 922 | if(CCCrypt(kCCEncrypt, kCCAlgorithmAES128, 0, key.val, kCCKeySizeAES128, NULL, buf, sizeof(buf), buf, sizeof(buf), &out_sz) == kCCSuccess && out_sz == sizeof(buf)) { 923 | CC_SHA384(buf, sizeof(buf), entangled_nonce); 924 | ret = true; 925 | } 926 | break; 927 | } 928 | } 929 | } 930 | } 931 | } 932 | IOObjectRelease(aes_serv); 933 | } 934 | #else 935 | (void)nonce; 936 | (void)entangled_nonce; 937 | #endif 938 | return ret; 939 | } 940 | 941 | void 942 | dimentio_term(void) { 943 | if(tfp0 != TASK_NULL) { 944 | mach_port_deallocate(mach_task_self(), tfp0); 945 | } else if(krw_0 != NULL) { 946 | dlclose(krw_0); 947 | } 948 | setpriority(PRIO_PROCESS, 0, 0); 949 | } 950 | 951 | kern_return_t 952 | dimentio_init(kaddr_t _kslide, kread_func_t _kread_buf, kwrite_func_t _kwrite_buf) { 953 | kernrw_0_req_kernrw_func_t kernrw_0_req; 954 | kslide = _kslide; 955 | if(_kread_buf != NULL && _kwrite_buf != NULL) { 956 | kread_buf = _kread_buf; 957 | kwrite_buf = _kwrite_buf; 958 | } else if(init_tfp0() == KERN_SUCCESS) { 959 | printf("tfp0: 0x%" PRIX32 "\n", tfp0); 960 | kread_buf = _kread_buf != NULL ? _kread_buf : kread_buf_tfp0; 961 | kwrite_buf = _kwrite_buf != NULL ? _kwrite_buf : kwrite_buf_tfp0; 962 | } else if((krw_0 = dlopen("/usr/lib/libkrw.0.dylib", RTLD_LAZY)) != NULL) { 963 | printf("libkrw!\n"); 964 | kread_buf = kread_buf_krw_0; 965 | kwrite_buf = kwrite_buf_krw_0; 966 | } else if((kernrw_0 = dlopen("/usr/lib/libkernrw.0.dylib", RTLD_LAZY)) != NULL && (kernrw_0_req = (kernrw_0_req_kernrw_func_t)dlsym(kernrw_0, "requestKernRw")) != NULL && kernrw_0_req() == 0 && (kernrw_0_kread = (kernrw_0_kread_func_t)dlsym(kernrw_0, "kernRW_readbuf")) != NULL && (kernrw_0_kwrite = (kernrw_0_kwrite_func_t)dlsym(kernrw_0, "kernRW_writebuf")) != NULL) { 967 | printf("libkernrw!\n"); 968 | kread_buf = kread_buf_kernrw_0; 969 | kwrite_buf = kwrite_buf_kernrw_0; 970 | } 971 | if(setpriority(PRIO_PROCESS, 0, PRIO_MIN) != -1 && pfinder_init_offsets() == KERN_SUCCESS) { 972 | return KERN_SUCCESS; 973 | } 974 | dimentio_term(); 975 | return KERN_FAILURE; 976 | } 977 | 978 | kern_return_t 979 | dementia(uint64_t *nonce, uint8_t entangled_nonce[CC_SHA384_DIGEST_LENGTH], bool *entangled) { 980 | io_service_t nvram_serv = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/options"); 981 | char nonce_hex[sizeof("0x") + 2 * sizeof(*nonce)]; 982 | kaddr_t of_dict, os_string, string_ptr; 983 | kern_return_t ret = KERN_FAILURE; 984 | 985 | if(nvram_serv != IO_OBJECT_NULL) { 986 | printf("nvram_serv: 0x%" PRIX32 "\n", nvram_serv); 987 | if(find_task(getpid(), &our_task) == KERN_SUCCESS) { 988 | printf("our_task: " KADDR_FMT "\n", our_task); 989 | if(get_of_dict(nvram_serv, &of_dict) == KERN_SUCCESS && of_dict != 0) { 990 | printf("of_dict: " KADDR_FMT "\n", of_dict); 991 | if((os_string = lookup_key_in_os_dict(of_dict, kBootNoncePropertyKey)) != 0) { 992 | printf("os_string: " KADDR_FMT "\n", os_string); 993 | if(kread_addr(os_string + OS_STRING_STRING_OFF, &string_ptr) == KERN_SUCCESS && string_ptr != 0) { 994 | printf("string_ptr: " KADDR_FMT "\n", string_ptr); 995 | if(kread_buf(string_ptr, nonce_hex, sizeof(nonce_hex)) == KERN_SUCCESS && sscanf(nonce_hex, "0x%016" PRIx64, nonce) == 1) { 996 | ret = KERN_SUCCESS; 997 | *entangled = entangle_nonce(*nonce, entangled_nonce); 998 | } 999 | } 1000 | } 1001 | } 1002 | } 1003 | IOObjectRelease(nvram_serv); 1004 | } 1005 | return ret; 1006 | } 1007 | 1008 | kern_return_t 1009 | dimentio(uint64_t nonce, uint8_t entangled_nonce[CC_SHA384_DIGEST_LENGTH], bool *entangled) { 1010 | io_service_t nonce_serv, nvram_serv = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/options"); 1011 | char nonce_hex[sizeof("0x") + 2 * sizeof(nonce)]; 1012 | kaddr_t of_dict, os_string, string_ptr; 1013 | kern_return_t ret = KERN_FAILURE; 1014 | 1015 | if(nvram_serv != IO_OBJECT_NULL) { 1016 | printf("nvram_serv: 0x%" PRIX32 "\n", nvram_serv); 1017 | if(find_task(getpid(), &our_task) == KERN_SUCCESS) { 1018 | printf("our_task: " KADDR_FMT "\n", our_task); 1019 | if((nonce_serv = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleMobileApNonce"))) != IO_OBJECT_NULL) { 1020 | printf("nonce_serv: 0x%" PRIX32 "\n", nonce_serv); 1021 | if(nonce_generate(nonce_serv) == KERN_SUCCESS && get_of_dict(nvram_serv, &of_dict) == KERN_SUCCESS && of_dict != 0) { 1022 | printf("of_dict: " KADDR_FMT "\n", of_dict); 1023 | if((os_string = lookup_key_in_os_dict(of_dict, kBootNoncePropertyKey)) != 0) { 1024 | printf("os_string: " KADDR_FMT "\n", os_string); 1025 | if(kread_addr(os_string + OS_STRING_STRING_OFF, &string_ptr) == KERN_SUCCESS && string_ptr != 0) { 1026 | printf("string_ptr: " KADDR_FMT "\n", string_ptr); 1027 | snprintf(nonce_hex, sizeof(nonce_hex), "0x%016" PRIx64, nonce); 1028 | if(kwrite_buf(string_ptr, nonce_hex, sizeof(nonce_hex)) == KERN_SUCCESS && sync_nonce(nvram_serv) == KERN_SUCCESS) { 1029 | ret = KERN_SUCCESS; 1030 | *entangled = entangle_nonce(nonce, entangled_nonce); 1031 | } 1032 | } 1033 | } 1034 | } 1035 | IOObjectRelease(nonce_serv); 1036 | } 1037 | } 1038 | IOObjectRelease(nvram_serv); 1039 | } 1040 | return ret; 1041 | } 1042 | 1043 | //read kernel 1044 | uint32_t kernel_read32(uint64_t where) { 1045 | uint32_t out; 1046 | kread_buf(where, &out, sizeof(uint32_t)); 1047 | return out; 1048 | } 1049 | 1050 | uint64_t kernel_read64(uint64_t where) { 1051 | uint64_t out; 1052 | kread_buf(where, &out, sizeof(uint64_t)); 1053 | return out; 1054 | } 1055 | 1056 | //write kernel 1057 | void kernel_write32(uint64_t where, uint32_t what) { 1058 | uint32_t _what = what; 1059 | kwrite_buf(where, &_what, sizeof(uint32_t)); 1060 | } 1061 | 1062 | void kernel_write64(uint64_t where, uint64_t what) { 1063 | uint64_t _what = what; 1064 | kwrite_buf(where, &_what, sizeof(uint64_t)); 1065 | } 1066 | -------------------------------------------------------------------------------- /libdimentio.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2020 0x7ff 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #ifndef LIBDIMENTIO_H 16 | # define LIBDIMENTIO_H 17 | # include 18 | # include 19 | # include 20 | # define KADDR_FMT "0x%" PRIX64 21 | typedef uint64_t kaddr_t; 22 | typedef kern_return_t (*kread_func_t)(kaddr_t, void *, mach_vm_size_t), (*kwrite_func_t)(kaddr_t, const void *, mach_msg_type_number_t); 23 | static kread_func_t kread_buf; 24 | static kwrite_func_t kwrite_buf; 25 | static size_t proc_p_pid_off; 26 | static size_t proc_task_off; 27 | task_t tfp0; 28 | kaddr_t kbase, kslide, this_proc, our_task; 29 | 30 | void 31 | dimentio_term(void); 32 | 33 | kern_return_t 34 | dimentio_init(kaddr_t, kread_func_t, kwrite_func_t); 35 | 36 | kern_return_t 37 | dimentio(uint64_t, uint8_t[CC_SHA384_DIGEST_LENGTH], bool *); 38 | 39 | kern_return_t 40 | dementia(uint64_t *, uint8_t[CC_SHA384_DIGEST_LENGTH], bool *); 41 | 42 | kern_return_t 43 | init_tfp0(void); 44 | 45 | kern_return_t 46 | kread_addr(kaddr_t, kaddr_t *); 47 | 48 | kern_return_t 49 | find_task(pid_t, kaddr_t *); 50 | 51 | kern_return_t 52 | pfinder_init_offsets(void); 53 | 54 | //read kernel 55 | uint32_t kernel_read32(uint64_t); 56 | uint64_t kernel_read64(uint64_t); 57 | 58 | //write kernel 59 | void kernel_write32(uint64_t, uint32_t); 60 | void kernel_write64(uint64_t, uint64_t); 61 | #endif 62 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | #include 2 | #import 3 | #include 4 | #include "vnode.h" 5 | 6 | void showUsage() { 7 | printf("Usage: vnodebypass [OPTION]...\n"); 8 | printf("Hide jailbreak files using VNODE that provides an internal representation of a file or directory or defines an interface to a file.\n\n"); 9 | printf("Option:\n"); 10 | printf("-s, --save Get vnode with file index and save path to /tmp/vnodeMem.txt\n"); 11 | printf("-h, --hide Hide jailbreak files\n"); 12 | printf("-r, --revert Revert jailbreak files\n"); 13 | printf("-R, --recovery To prevent kernel panic, vnode_usecount and vnode_iocount will be substracted 1 and remove /tmp/vnodeMem.txt\n"); 14 | printf("-c, --check Check if jailbreak file exists using SVC #0x80 SYS_access.\n"); 15 | } 16 | 17 | int main(int argc, char *argv[], char *envp[]) { 18 | setuid(0); 19 | setgid(0); 20 | 21 | if(getuid() != 0 && getgid() != 0) { 22 | printf("Require vnodebypass to be run as root!\n"); 23 | return -1; 24 | } 25 | 26 | if (argc != 2) { 27 | showUsage(); 28 | return -1; 29 | } 30 | 31 | if((strcmp(argv[1], "-s") == 0 || strcmp(argv[1], "--save") == 0)) 32 | saveVnode(); 33 | else if((strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--hide") == 0)) 34 | hideVnode(); 35 | else if((strcmp(argv[1], "-r") == 0 || strcmp(argv[1], "--revert") == 0)) 36 | revertVnode(); 37 | else if((strcmp(argv[1], "-R") == 0 || strcmp(argv[1], "--recovery") == 0)) 38 | recoveryVnode(); 39 | else if((strcmp(argv[1], "-c") == 0 || strcmp(argv[1], "--check") == 0)) 40 | checkFile(); 41 | else 42 | showUsage(); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /vnode.h: -------------------------------------------------------------------------------- 1 | void saveVnode(); 2 | void hideVnode(); 3 | void revertVnode(); 4 | void recoveryVnode(); 5 | void checkFile(); 6 | -------------------------------------------------------------------------------- /vnode.m: -------------------------------------------------------------------------------- 1 | #include "vnode.h" 2 | #import 3 | #import 4 | #include "SVC_Caller.h" 5 | #include "kernel.h" 6 | #include "libdimentio.h" 7 | 8 | const char *vnodeMemPath; 9 | NSArray *hidePathList = nil; 10 | 11 | __attribute__((constructor)) void initVnodeMemPath() { 12 | vnodeMemPath = 13 | [NSString stringWithFormat:@"/tmp/%@.txt", NSProcessInfo.processInfo.processName].UTF8String; 14 | } 15 | 16 | void initPath() { 17 | hidePathList = [NSArray 18 | arrayWithContentsOfFile:[NSString stringWithFormat:@"/usr/share/%@/hidePathList.plist", 19 | NSProcessInfo.processInfo.processName]]; 20 | if (hidePathList == nil) goto exit; 21 | for (id path in hidePathList) { 22 | if (![path isKindOfClass:[NSString class]]) goto exit; 23 | } 24 | return; 25 | exit: 26 | printf("hidePathList.plist is broken, please reinstall vnodebypass!\n"); 27 | exit(1); 28 | } 29 | 30 | void saveVnode() { 31 | if (access(vnodeMemPath, F_OK) == 0) { 32 | printf("Already exist /tmp/vnodeMem.txt, Please vnode recovery first!\n"); 33 | return; 34 | } 35 | 36 | initPath(); 37 | if (init_kernel() == 1) { 38 | printf("Failed init_kernel\n"); 39 | return; 40 | } 41 | find_task(getpid(), &our_task); 42 | if (!this_proc) return; 43 | printf("this_proc: " KADDR_FMT "\n", this_proc); 44 | 45 | FILE *fp = fopen(vnodeMemPath, "w"); 46 | 47 | int hideCount = (int)[hidePathList count]; 48 | uint64_t vnodeArray[hideCount]; 49 | 50 | for (int i = 0; i < hideCount; i++) { 51 | const char *hidePath = [[hidePathList objectAtIndex:i] UTF8String]; 52 | int file_index = open(hidePath, O_RDONLY); 53 | 54 | if (file_index == -1) continue; 55 | 56 | vnodeArray[i] = get_vnode_with_file_index(file_index, this_proc); 57 | printf("hidePath: %s, vnode[%d]: 0x%" PRIX64 "\n", hidePath, i, vnodeArray[i]); 58 | printf("vnode_usecount: 0x%" PRIX32 ", vnode_iocount: 0x%" PRIX32 "\n", 59 | kernel_read32(vnodeArray[i] + off_vnode_usecount), 60 | kernel_read32(vnodeArray[i] + off_vnode_iocount)); 61 | fprintf(fp, "0x%" PRIX64 "\n", vnodeArray[i]); 62 | close(file_index); 63 | } 64 | fclose(fp); 65 | if (tfp0) mach_port_deallocate(mach_task_self(), tfp0); 66 | printf("Saved vnode to /tmp/vnodeMem.txt\nMake sure vnode recovery to prevent kernel panic!\n"); 67 | } 68 | 69 | void hideVnode() { 70 | if (init_kernel() == 1) { 71 | printf("Failed init_kernel\n"); 72 | return; 73 | } 74 | if (access(vnodeMemPath, F_OK) == 0) { 75 | FILE *fp = fopen(vnodeMemPath, "r"); 76 | uint64_t savedVnode; 77 | int i = 0; 78 | while (!feof(fp)) { 79 | if (fscanf(fp, "0x%" PRIX64 "\n", &savedVnode) == 1) { 80 | printf("Saved vnode[%d] = 0x%" PRIX64 "\n", i, savedVnode); 81 | hide_path(savedVnode); 82 | } 83 | i++; 84 | } 85 | } 86 | if (tfp0) mach_port_deallocate(mach_task_self(), tfp0); 87 | printf("Hide file!\n"); 88 | } 89 | 90 | void revertVnode() { 91 | if (init_kernel() == 1) { 92 | printf("Failed init_kernel\n"); 93 | return; 94 | } 95 | if (access(vnodeMemPath, F_OK) == 0) { 96 | FILE *fp = fopen(vnodeMemPath, "r"); 97 | uint64_t savedVnode; 98 | int i = 0; 99 | while (!feof(fp)) { 100 | if (fscanf(fp, "0x%" PRIX64 "\n", &savedVnode) == 1) { 101 | printf("Saved vnode[%d] = 0x%" PRIX64 "\n", i, savedVnode); 102 | show_path(savedVnode); 103 | } 104 | i++; 105 | } 106 | } 107 | if (tfp0) mach_port_deallocate(mach_task_self(), tfp0); 108 | printf("Show file!\n"); 109 | } 110 | 111 | void recoveryVnode() { 112 | if (init_kernel() == 1) { 113 | printf("Failed init_kernel\n"); 114 | return; 115 | } 116 | if (access(vnodeMemPath, F_OK) == 0) { 117 | FILE *fp = fopen(vnodeMemPath, "r"); 118 | uint64_t savedVnode; 119 | int i = 0; 120 | while (!feof(fp)) { 121 | if (fscanf(fp, "0x%" PRIX64 "\n", &savedVnode) == 1) { 122 | kernel_write32(savedVnode + off_vnode_iocount, 123 | kernel_read32(savedVnode + off_vnode_iocount) - 1); 124 | kernel_write32(savedVnode + off_vnode_usecount, 125 | kernel_read32(savedVnode + off_vnode_usecount) - 1); 126 | printf("Saved vnode[%d] = 0x%" PRIX64 "\n", i, savedVnode); 127 | printf("vnode_usecount: 0x%" PRIX32 ", vnode_iocount: 0x%" PRIX32 "\n", 128 | kernel_read32(savedVnode + off_vnode_usecount), 129 | kernel_read32(savedVnode + off_vnode_iocount)); 130 | } 131 | i++; 132 | } 133 | remove(vnodeMemPath); 134 | } 135 | if (tfp0) mach_port_deallocate(mach_task_self(), tfp0); 136 | printf("Recovered vnode! No more kernel panic when you shutdown.\n"); 137 | } 138 | 139 | void checkFile() { 140 | initPath(); 141 | int hideCount = (int)[hidePathList count]; 142 | for (int i = 0; i < hideCount; i++) { 143 | const char *hidePath = [[hidePathList objectAtIndex:i] UTF8String]; 144 | int ret = 0; 145 | ret = SVC_Access(hidePath); 146 | printf("hidePath: %s, errno: %d\n", hidePath, ret); 147 | } 148 | printf("Done check file!\n"); 149 | } 150 | --------------------------------------------------------------------------------