KEXT patching in ios 8

Questions and Answers about all things *OS (macOS, iOS, tvOS, watchOS)

KEXT patching in ios 8

Postby Boba » Wed Aug 02, 2017 9:51 am

Hello everyone:)
I want to know more about ios internals, so there is no better way than practical experiments. I know, that with each new version of ios the amount of features growns. So I decided to take my old iphone 4s with old ios 8 on it for experements (used taig for jailbreak). I took decrypted kernelcache and started to explore it in IDA. Then I found some interesting places for me (for example AplleKeyStore kext), and wanted to try patching it. AFAIK, I am not able to boot patched kernelcache in ios 8, because there are no suitable exploits for this. So the second way is to patch directly in RAM, when kernelcache has already booted. Function vm_write can help with it. Prototype:
kern_return_t vm_write(vm_map_t target_task, vm_address_t address, vm_offset_t data, mach_msg_type_number_t dataCnt);
I use utilities from siguza's git (https://github.com/Siguza/ios-kern-utils). One of them is kpatch, that uses function vm_write under the hood to patch kernel. When I try to patch code of kernel itself (not KEXTs, that linked within kernelcache), everything goes fine. But when I try to patch code of some KEXT (which is inside kernelcache), I get kernel panic and ios reboots.
So now I try understand, what is the difference between patching kernel itself and patching kernelcache's KEXT? These prelinked KEXT start with kernel, so they "belong" to kernel task, right?

I also tryed to anylize panic logs and found, that panic can happen due to 2 different reasons. One of them I have not explored yet. The second reason is that when the os tryes to get physical address of page (which I want to patch), it gets zero address and panic happens. Also I cannot understand this fact. Because before call kpatch utility I always read the patching memory with kmem utility, and it reads fine.

Thanx for your time.
Boba
 
Posts: 5
Joined: Wed Aug 02, 2017 8:15 am

Re: KEXT patching in ios 8

Postby Siguza » Thu Aug 03, 2017 1:49 am

1. You could actually boot a custom kernel by means of kloader and kDFU.
2. If I had to guess I'd say the memory region you're trying to patch is readonly (as would the kernel __TEXT be, if it weren't for the jailbreak).
User avatar
Siguza
Unicorn
 
Posts: 159
Joined: Thu Jan 28, 2016 10:38 am

Re: KEXT patching in ios 8

Postby Boba » Fri Aug 04, 2017 1:18 pm

Thank you for answer. But I still cannot get the victory :)
1. You could actually boot a custom kernel by means of kloader and kDFU.

As I googled, I am only able to downgrade to ios 6.1.3 (or to 8.4.1, but don't need it) using OdysseusOTA with OTA blob. But what can I do then? Term custom kernel does not mean, that I am able to patch decrypted kernelcache file and then boot it. Am I right? I googled much before make such a conclusion..

2. If I had to guess I'd say the memory region you're trying to patch is readonly (as would the kernel __TEXT be, if it weren't for the jailbreak).

I also think so. That's why I tried to change rwx attributes of memory using vm_protect function, but it doesn't return success (KERN_SUCCESS). But I am still digging in this destination. May be there some another kernel APIs exist. Or may be I missed something in my code.

Code: Select all
#include <mach/vm_map.h>
#include <mach/mach_traps.h>
#include <mach/mach_init.h>
#include <cstdio>
#include <cstdlib>

int printUsage()
{
    printf("Usage: setvmprot PID ADDRESS SIZE\n");
    return 0;
}

int main(int argc, char **argv)
{
    if (argc < 4) {
        printUsage();
        return -1;
    }
    uint32_t pid = (uint32_t)strtoll(argv[1], 0, 0);
    vm_address_t address = (vm_address_t)strtoll(argv[2], 0, 0);
    vm_size_t size = (vm_size_t)strtoll(argv[3], 0, 0);
    printf("pid=%u, address=0x%08X, size=0x%X\n", pid, address, size);

    kern_return_t ret;
    mach_port_name_t target_task;
    ret = task_for_pid(mach_task_self(), pid, &target_task);
    if (ret == KERN_SUCCESS) {
        printf("Successfully got task, target_task=0x%08X\n", (uint32_t)target_task);
    } else {
        printf("Failed to get task, ret=%d\n", ret);
        return ret;
    }

    vm_prot_t attrs = VM_PROT_READ | VM_PROT_WRITE /*| VM_PROT_EXECUTE*/;
    printf("vm_protect rw returned %d\n", vm_protect(target_task , address, size, false, attrs));

    attrs = VM_PROT_READ /*| VM_PROT_WRITE*/ | VM_PROT_EXECUTE;
    printf("vm_protect rx returned %d\n", vm_protect(target_task , address, size, false, attrs));
    return 0;
}
Boba
 
Posts: 5
Joined: Wed Aug 02, 2017 8:15 am

Re: KEXT patching in ios 8

Postby Siguza » Fri Aug 04, 2017 11:54 pm

1. In a KPP-free world, you actually can boot whatever binary you like, including a patched kernel file. One such way would be dual-booting. You can do that without blobs, so your kernel isn't signed anyway. A tethered boot is also possible this way: first you use kloader to bootstrap a pwned iBSS, then you plug your device into your computer and use futurerestore with the "--use-pwndfu --just-boot" arguments. You'd have to create an IPSW with your patched kernel though, and I'm not sure how you'd go about that...
2. The page table entries of the memory region containing the kernel binary aren't accurately reflected in the VM system (most likely by design). So you can't use the vm_* functions to do more than read or writes, you'd have to patch the page tables "by hand". The way I'd go about this would be to first locate the level 0 translation table (this gist has a great explanation on how to get that pointer) and then traverse the page tables and patch the protection bits to RWX (note that in order to access page tables of level >= 1, you might need to actively map them into virtual memory (which you might wanna undo later) in order to patch them, since they're not in the VM system and you only get their physical address from the level 0 page table).
User avatar
Siguza
Unicorn
 
Posts: 159
Joined: Thu Jan 28, 2016 10:38 am

Re: KEXT patching in ios 8

Postby Boba » Sat Aug 05, 2017 9:40 pm

Wow, thanx. I'll try theese as soon as get to my device again (now not at home)
Boba
 
Posts: 5
Joined: Wed Aug 02, 2017 8:15 am

Re: KEXT patching in ios 8

Postby Boba » Tue Aug 08, 2017 8:19 am

Yay! Got the patch:)
I decided to try the way of "shadow mapping" (which is related to translation tables). I took code from here (if somebody will get the same question like me):
https://github.com/dinosec/iphone-dataprotection-xcode5/blob/master/ramdisk_tools/ttbthingy.c
There I only had to change do_kernel_patchs() function.
Thank you Siguza for your answers :)
Boba
 
Posts: 5
Joined: Wed Aug 02, 2017 8:15 am

Re: KEXT patching in ios 8

Postby Siguza » Tue Aug 08, 2017 5:03 pm

Oh right, remapping would certainly work too - good thinking. :)
User avatar
Siguza
Unicorn
 
Posts: 159
Joined: Thu Jan 28, 2016 10:38 am


Return to Questions and Answers

Who is online

Users browsing this forum: No registered users and 1 guest

cron