Browse Source

added nonce setting support, partially updated teh bootstrap to include latest versions, still need to modify it to respect proper paths (mobilesubstrate dir linked to /usr/lib/TweakInject

Kevin Bradley 5 years ago
parent
commit
b4b86c4283

+ 48 - 0
Meridian/meridianTV/ViewController.m

@@ -253,6 +253,47 @@ bool jailbreak_has_run = false;
     }
 }
 
+
+
+- (IBAction)tappedOnSetNonce:(id)sender {
+    __block NSString *generatorToSet = nil;
+    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:localize(@"Set the system boot nonce on jailbreak") message:localize(@"Enter the generator for the nonce you want the system to generate on boot") preferredStyle:UIAlertControllerStyleAlert];
+    [alertController addAction:[UIAlertAction actionWithTitle:localize(@"Cancel") style:UIAlertActionStyleDefault handler:nil]];
+    UIAlertAction *set = [UIAlertAction actionWithTitle:localize(@"Set") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
+        const char *generatorInput = [alertController.textFields.firstObject.text UTF8String];
+        char compareString[22];
+        uint64_t rawGeneratorValue;
+        sscanf(generatorInput, "0x%16llx",&rawGeneratorValue);
+        sprintf(compareString, "0x%016llx", rawGeneratorValue);
+        if(strcmp(compareString, generatorInput) != 0) {
+            UIAlertController *alertController = [UIAlertController alertControllerWithTitle:localize(@"Error") message:localize(@"Failed to validate generator") preferredStyle:UIAlertControllerStyleAlert];
+            [alertController addAction:[UIAlertAction actionWithTitle:localize(@"OK") style:UIAlertActionStyleDefault handler:nil]];
+            [self presentViewController:alertController animated:YES completion:nil];
+            return;
+        }
+        generatorToSet = [NSString stringWithUTF8String:generatorInput];
+        [userDefaults setObject:generatorToSet forKey:@K_GENERATOR];
+        [userDefaults synchronize];
+        uint32_t flags;
+        csops(getpid(), CS_OPS_STATUS, &flags, 0);
+        UIAlertController *alertController = nil;
+        if ((flags & CS_PLATFORM_BINARY)) {
+            alertController = [UIAlertController alertControllerWithTitle:localize(@"Notice") message:localize(@"The system boot nonce will be set the next time you enable your jailbreak") preferredStyle:UIAlertControllerStyleAlert];
+        } else {
+            alertController = [UIAlertController alertControllerWithTitle:localize(@"Notice") message:localize(@"The system boot nonce will be set once you enable the jailbreak") preferredStyle:UIAlertControllerStyleAlert];
+        }
+        [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+        [self presentViewController:alertController animated:YES completion:nil];
+    }];
+    [alertController addAction:set];
+    [alertController setPreferredAction:set];
+    [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
+        textField.placeholder = [NSString stringWithFormat:@"%s", genToSet()];
+    }];
+    [self presentViewController:alertController animated:YES completion:nil];
+}
+
 - (void)setGoButtonTitle:(NSString *)title {
     
     dispatch_async(dispatch_get_main_queue(), ^{
@@ -368,6 +409,13 @@ bool jailbreak_has_run = false;
             
         }
         
+    } else {
+        
+        playPauseOrMenuDoubleTapRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tappedOnSetNonce:)];
+        playPauseOrMenuDoubleTapRecognizer.numberOfTapsRequired = 2;
+        playPauseOrMenuDoubleTapRecognizer.allowedPressTypes = @[[NSNumber numberWithInteger:UIPressTypePlayPause], [NSNumber numberWithInteger:UIPressTypeMenu]];
+        [self.view addGestureRecognizer:playPauseOrMenuDoubleTapRecognizer];
+        
     }
     
 

BIN
Meridian/meridianTV/bootstrap.tar.gz


+ 30 - 29
Meridian/meridianTV/electra/headers/IOKit.h

@@ -20,39 +20,14 @@ kern_return_t mach_vm_read(
 
 typedef mach_port_t io_service_t;
 typedef mach_port_t io_connect_t;
+typedef mach_port_t    io_object_t;
+typedef io_object_t    io_registry_entry_t;
+typedef char        io_name_t[128];
+typedef char             io_struct_inband_t[4096];
 
 extern const mach_port_t kIOMasterPortDefault;
 #define IO_OBJECT_NULL (0)
 
-kern_return_t
-IOConnectCallAsyncMethod(
-                         mach_port_t     connection,
-                         uint32_t        selector,
-                         mach_port_t     wakePort,
-                         uint64_t*       reference,
-                         uint32_t        referenceCnt,
-                         const uint64_t* input,
-                         uint32_t        inputCnt,
-                         const void*     inputStruct,
-                         size_t          inputStructCnt,
-                         uint64_t*       output,
-                         uint32_t*       outputCnt,
-                         void*           outputStruct,
-                         size_t*         outputStructCntP);
-
-kern_return_t
-IOConnectCallMethod(
-                    mach_port_t     connection,
-                    uint32_t        selector,
-                    const uint64_t* input,
-                    uint32_t        inputCnt,
-                    const void*     inputStruct,
-                    size_t          inputStructCnt,
-                    uint64_t*       output,
-                    uint32_t*       outputCnt,
-                    void*           outputStruct,
-                    size_t*         outputStructCntP);
-
 io_service_t
 IOServiceGetMatchingService(
                             mach_port_t  _masterPort,
@@ -69,9 +44,35 @@ IOServiceOpen(
               uint32_t      type,
               io_connect_t* connect );
 
+io_service_t
+IOServiceGetMatchingService(
+                            mach_port_t  _masterPort,
+                            CFDictionaryRef  matching);
+
+CFMutableDictionaryRef
+IOServiceMatching(
+                  const char* name);
+
+kern_return_t
+IORegistryEntrySetCFProperties(
+                               io_registry_entry_t    entry,
+                               CFTypeRef         properties );
+kern_return_t
+IORegistryEntryGetProperty(
+                           io_registry_entry_t    entry,
+                           const io_name_t        propertyName,
+                           io_struct_inband_t    buffer,
+                           uint32_t          * size );
+io_registry_entry_t IORegistryEntryFromPath(
+                                mach_port_t port,
+                                char *path );
+kern_return_t IOObjectRelease(io_object_t object);
+
 kern_return_t IOConnectTrap6(io_connect_t connect, uint32_t index, uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, uintptr_t p5, uintptr_t p6);
 kern_return_t mach_vm_read_overwrite(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, mach_vm_address_t data, mach_vm_size_t *outsize);
 kern_return_t mach_vm_write(vm_map_t target_task, mach_vm_address_t address, vm_offset_t data, mach_msg_type_number_t dataCnt);
 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);
+kern_return_t mach_vm_remap(vm_map_t dst, mach_vm_address_t *dst_addr, mach_vm_size_t size, mach_vm_offset_t mask, int flags, vm_map_t src, mach_vm_address_t src_addr, boolean_t copy, vm_prot_t *cur_prot, vm_prot_t *max_prot, vm_inherit_t inherit);
 
 #endif /* IOKit_h */

+ 18 - 0
Meridian/meridianTV/electra/the fun part/fun.c

@@ -26,6 +26,7 @@
 #include "unliberios.h"
 #include "removeElectrabeta.h"
 #include "fun_objc.h"
+#include "nonce.h"
 
 mach_port_t tfpzero;
 
@@ -211,6 +212,23 @@ do { \
         writeMessagePlain("remapped tfp0: 0x%x\n", real_tfp0);
     }
 
+    unlocknvram();
+    
+    // Only set a generator if one is not already set or if the user has specified one
+    const char *currentgen = getgen();
+    if (!currentgen || userGenerator()) {
+        const char *gen = genToSet();
+        // Only actually set the generator if it is not already set
+        if (!currentgen || strcasecmp(currentgen, gen) != 0) {
+            printf("Setting generator to %s\n", gen);
+            printf("ret: %d\n", setgen(gen));
+        } else {
+            printf("Requested generator already set: %s\n", gen);
+        }
+    }
+    
+    locknvram();
+    
 	// Remount / as rw - patch by xerub with nosuid patch added by coolstar
 	{
         uint64_t _rootvnode = find_rootvnode();

+ 8 - 0
Meridian/meridianTV/electra/the fun part/fun_objc.h

@@ -9,6 +9,14 @@
 #ifndef fun_objc_h
 #define fun_objc_h
 
+
+#define localize(key) NSLocalizedString(key, @"")
+#define K_GENERATOR "generator"
+#define K_ELECTRA_GENERATOR "0xbd34a880be0b53f3"
+
+const char *userGenerator(void);
+const char *genToSet(void);
+
 const char* progname(const char*);;
 void extractGz(const char *from, const char *to);
 void update_springboard_plist(void);

+ 24 - 0
Meridian/meridianTV/electra/the fun part/fun_objc.m

@@ -20,6 +20,30 @@
 #import "NSData+GZip.h"
 #import "ViewController.h"
 #import "utils.h"
+#import "fun_objc.h"
+
+const char *userGenerator(void) {
+    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+    if ([userDefaults objectForKey:@K_GENERATOR] == nil)
+        return NULL;
+    
+    const char *generator = [[userDefaults objectForKey:@K_GENERATOR] UTF8String];
+    char compareString[22];
+    uint64_t rawGeneratorValue;
+    sscanf(generator, "0x%16llx", &rawGeneratorValue);
+    sprintf(compareString, "0x%016llx", rawGeneratorValue);
+    if(strcmp(compareString, generator) != 0)
+        return NULL;
+    return generator;
+}
+
+const char *genToSet(void) {
+    const char *generator = userGenerator();
+    if (generator == NULL)
+        generator = strdup(K_ELECTRA_GENERATOR);
+    
+    return generator;
+}
 
 const char* progname(const char* prog) {
     char path[4096];

+ 15 - 0
Meridian/meridianTV/electra/the fun part/unlocknvram.c

@@ -46,6 +46,8 @@ uint64_t get_iodtnvram_obj(void) {
     return IODTNVRAMObj;
 }
 
+uint64_t orig_vtable = -1;
+
 void unlocknvram(void) {
     uint64_t obj = get_iodtnvram_obj();
     uint64_t vtable_start = rk64_electra(obj);
@@ -73,3 +75,16 @@ void unlocknvram(void) {
     
     free(buf);
 }
+
+void locknvram(void) {
+    if (orig_vtable == -1) {
+        return;
+    }
+    
+    uint64_t obj = get_iodtnvram_obj();
+    if (obj == 0) { // would never happen but meh
+        return;
+    }
+    
+    wk64_electra(obj, orig_vtable);
+}

+ 1 - 0
Meridian/meridianTV/electra/the fun part/unlocknvram.h

@@ -1 +1,2 @@
 void unlocknvram(void);
+void locknvram(void);

+ 20 - 0
Meridian/meridianTV/electra/the fun part/utilities/debug.h

@@ -0,0 +1,20 @@
+//
+//  debug.h
+//  electra1131
+//
+//  Created by Pwn20wnd on 7/3/18.
+//  Copyright © 2018 Electra Team. All rights reserved.
+//
+
+#ifndef debug_h
+#define debug_h
+
+#include <stdio.h>
+
+#define RAWLOG(fmt, args...) fprintf(stderr, fmt, ##args);
+#define INFO(fmt, args...) RAWLOG("[INF] " fmt, ##args);
+#undef DEBUG
+#define DEBUG(fmt, args...) RAWLOG("[DBG] " fmt, ##args);
+#define ERROR(fmt, args...) RAWLOG("[ERR] " fmt, ##args);
+
+#endif /* debug_h */

+ 120 - 0
Meridian/meridianTV/electra/the fun part/utilities/nonce.c

@@ -0,0 +1,120 @@
+#include "nonce.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <mach/mach.h>
+#include "IOKit.h"
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "debug.h"
+
+#define kIONVRAMDeletePropertyKey   "IONVRAM-DELETE-PROPERTY"
+#define kIONVRAMForceSyncNowPropertyKey "IONVRAM-FORCESYNCNOW-PROPERTY"
+
+#define nonceKey                "com.apple.System.boot-nonce"
+
+// thx PhoenixNonce
+
+CFMutableDictionaryRef makedict(const char *key, const char *val) {
+    CFStringRef cfkey = CFStringCreateWithCStringNoCopy(NULL, key, kCFStringEncodingUTF8, kCFAllocatorNull);
+    CFStringRef cfval = CFStringCreateWithCStringNoCopy(NULL, val, kCFStringEncodingUTF8, kCFAllocatorNull);
+
+    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    if(!cfkey || !dict || !cfval) {
+        ERROR("failed to alloc cf objects {'%s': '%s'}", key, val);
+        return NULL;
+    } else {
+        DEBUG("made dict {'%s': '%s'}", key, val);
+    }
+    CFDictionarySetValue(dict, cfkey, cfval);
+
+    CFRelease(cfkey);
+    CFRelease(cfval);
+    return dict;
+}
+
+int applydict(CFMutableDictionaryRef dict) {
+    int ret = 1;
+
+    io_service_t nvram = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODTNVRAM"));
+    if(!MACH_PORT_VALID(nvram)) {
+        ERROR("Failed to get IODTNVRAM service");
+    } else {
+        kern_return_t kret = IORegistryEntrySetCFProperties(nvram, dict);
+        DEBUG("IORegistryEntrySetCFProperties: 0x%x (%s)\n", kret, mach_error_string(kret));
+        if(kret == KERN_SUCCESS) {
+            ret = 0;
+        }
+    }
+    
+    IOObjectRelease(nvram);
+    
+    return ret;
+}
+
+char* getval(const char *key) {
+    // IORegistryEntryCreateCFProperty seems to fail, btw
+
+    char buf[1024];
+    unsigned int length = sizeof(buf);
+    kern_return_t err;
+
+    io_service_t nvram = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODTNVRAM"));
+    if(!MACH_PORT_VALID(nvram)) {
+        ERROR("Failed to get IODTNVRAM service");
+        return NULL;
+    }
+
+    err = IORegistryEntryGetProperty(nvram, key, (void*)buf, &length);
+    
+    IOObjectRelease(nvram);
+    
+    DEBUG("IORegistryEntryGetProperty(%s) == 0x%x (%s)\n", key, err, mach_error_string(err));
+    if (err != KERN_SUCCESS) {
+        return NULL;
+    }
+    
+    buf[length] = '\0';
+    return strdup(buf);
+}
+
+int makenapply(const char *key, const char *val) {
+    int ret = 1;
+
+    CFMutableDictionaryRef dict = makedict(key, val);
+    if(!dict) {
+        ERROR("failed to make cf dict\n");
+        return ret;
+    }
+
+    ret = applydict(dict);
+
+    if (ret) {
+        ERROR("applydict failed\n");
+    }
+
+    CFRelease(dict);
+    return ret;
+}
+
+int setgen(const char *gen) {
+    int ret = 0;
+
+    ret = makenapply(kIONVRAMDeletePropertyKey, nonceKey);
+
+    // set even if delete failed
+    ret = makenapply(nonceKey, gen);
+    ret = ret || makenapply(kIONVRAMForceSyncNowPropertyKey, nonceKey);
+
+    return ret;
+}
+
+char* getgen(void) {
+    return getval(nonceKey);
+}
+
+int delgen(void) {
+    return makenapply(kIONVRAMDeletePropertyKey, nonceKey);
+}

+ 6 - 0
Meridian/meridianTV/electra/the fun part/utilities/nonce.h

@@ -0,0 +1,6 @@
+#pragma once
+
+int setgen(const char*);
+char* getgen(void);
+int delgen(void);
+

+ 2 - 2
Meridian/meridianTV/electra_extras/sbinject/.theos/_/DEBIAN/control

@@ -8,5 +8,5 @@ Description: A modified version of Coolstars TweakInject to work on tvOS
 Maintainer: Kevin Bradley
 Author: Kevin Bradley
 Section: Utilities
-Version: 0.0.1-28
-Installed-Size: 88
+Version: 0.0.1-26
+Installed-Size: 92

BIN
Meridian/meridianTV/electra_extras/sbinject/.theos/_/usr/lib/TweakInject.dylib


+ 1 - 1
Meridian/meridianTV/electra_extras/sbinject/.theos/last_package

@@ -1 +1 @@
-./debs/com.nito.tweakinject_0.0.1-28_appletvos-arm64.deb
+./debs/com.nito.tweakinject_0.0.1-26_appletvos-arm64.deb

BIN
Meridian/meridianTV/electra_extras/sbinject/.theos/obj/appletv/debug/TweakInject.dylib


BIN
Meridian/meridianTV/electra_extras/sbinject/.theos/obj/appletv/debug/arm64/TweakInject.dylib


+ 1 - 1
Meridian/meridianTV/electra_extras/sbinject/Makefile

@@ -14,7 +14,7 @@ include $(THEOS_MAKE_PATH)/library.mk
 
 after-stage::
 	echo $(FAKEROOT)
-	cd $(FW_STAGING_DIR)/usr/lib/ ; pwd ; ls -al ; ln -s TweakInject.dylib TweakLoader.dylib ; $(FAKEROOT) chown root:wheel TweakLoader.dylib
+	cd $(FW_STAGING_DIR)/usr/lib/ ; pwd ; ls -al ; ln -s TweakInject.dylib TweakLoader.dylib ; cd $(FW_STAGING_DIR) ; sudo chown -R root:wheel usr
 
 	
 	

+ 7 - 4
Meridian/meridianTV/electra_extras/sbinject/SBInject.x

@@ -12,7 +12,7 @@
 #define PROC_PIDPATHINFO_MAXSIZE  (1024)
 int proc_pidpath(pid_t pid, void *buffer, uint32_t buffersize);
 
-#define dylibDir @"/Library/MobileSubstrate/DynamicLibraries/"
+#define dylibDir @"/usr/lib/TweakInject"
 
 NSArray *sbinjectGenerateDylibList() {
 
@@ -74,19 +74,22 @@ NSArray *sbinjectGenerateDylibList() {
             isInjected = YES;
             continue;
         }
-        /*
+
+
+            //this code never worked for me on tvOS
         for (NSString *entry in filter[@"Filter"][@"Bundles"]) {
             // Check to see whether or not this bundle is actually loaded in this application or not
             if (!CFBundleGetBundleWithIdentifier((CFStringRef)entry)) {
                 // If not, skip it
+                //NSLog(@"we not in here?: %@", entry);
                 continue;
             }
             [dylibsToInject addObject:[[plistPath stringByDeletingPathExtension] stringByAppendingString:@".dylib"]];
             isInjected = YES;
-            //NSLog(@"break");
+            //NSLog(@"here?: %@", entry);
             continue;
         }
-        */
+        
         if (!isInjected) {
             // Decide whether or not to load the dylib based on the Executables values
             for (NSString *process in filter[@"Filter"][@"Executables"]) {

+ 0 - 11
Meridian/meridianTV/electra_extras/sbinject/control

@@ -1,11 +0,0 @@
-Package: com.nito.tweakinject
-Priority: required
-Name: TweakInject
-Pre-Depends: cy+model.appletv
-Depends: firmware (>= 10.0)
-Version: 0.0.1
-Architecture: appletvos-arm64
-Description: A modified version of Coolstars TweakInject to work on tvOS
-Maintainer: Kevin Bradley
-Author: Kevin Bradley
-Section: Utilities

BIN
Meridian/meridianTV/meridian-bootstrap.tar