Pangu 9.1 Kernel Dump

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

Pangu 9.1 Kernel Dump

Postby bob969 » Tue Mar 22, 2016 1:52 pm

Hi Jonathan,

I was in your class last week and you mentioned that in the Pangu 9.1 jailbreak they add in a Mach host special port 4 for reading the kernel memory. I am trying to use this to get a kernel dump on an iPhone 6S. My first attempts resulted in instant reboots when I tried to read from kernel addresses that were not currently mapped due to ASLR. I then found the vm_region_64() function in the header and am currently using this to try and find the pages that are mapped and contain the kernel. After finding what I think are the right pages, I read them using mach_vm_read() and save them to disk. However, no matter what pages I read from the kernel the result is a file of the expected size where all the bytes are set to zero with the exception of the first 3 or 4 bytes. However, the phone no longer reboots immediately. Do I need to do anything special to actually read the kernel memory? To me it seems like I am at the right address but the kernel is refusing to actually provide its memory. I have attached the output of my program and the program itself below.

Got port e03
vm_region returned 0
kernel start
address = 0xffffff8002014000, size = 0xe0000, info_count = 9
protection = 3,max protect =7,inheritance=1,shared=0,reserved=0,offset=ffffff8002014000,behavior=0,wired=0
vm_region returned 0
kernel end
address = 0xffffff801a28c000, size = 0x3d78000, info_count = 9
protection = 3,max protect =7,inheritance=1,shared=0,reserved=1,offset=ffffff801a28c000,behavior=0,wired=0
Kernel size is about 0x18278000
read 0xe0000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x8000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x94000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x4000 bytes from the kernel mem
read 0x8000 bytes from the kernel mem
read 0x8000 bytes from the kernel mem


Code: Select all
#include <stdio.h>
#include <mach/mach.h>
#include <mach/vm_map.h>
#include <mach/vm_region.h>

#include <stdlib.h>

//From header
kern_return_t mach_vm_read(vm_map_t target_task, mach_vm_address_t address, mach_vm_size_t size, vm_offset_t *data, mach_msg_type_number_t *dataCnt);

int main(int argc, char** argv)
{
    mach_port_t kernMemPort;
    host_get_special_port(mach_host_self(),HOST_LOCAL_NODE,4,&kernMemPort); //host special port 4 was been added to get kernel memory?
    printf("Got port %x\n",kernMemPort);
   
    //try and find kernel start and end addresses
    vm_address_t address;
    vm_size_t size;
    kern_return_t kr;
    struct vm_region_basic_info_64 info;
    mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
    mach_port_t notUsed;
   
    for (address= VM_MIN_ADDRESS; ; address += size) {

        kr = vm_region_64(kernMemPort,&address,&size,VM_REGION_BASIC_INFO_64,(vm_region_info_t)&info,&info_count,&notUsed);
        if(info.protection == 3 && info.offset !=0){
            printf("vm_region returned %d\n",kr);
            printf("kernel start\n");
            printf("\taddress = 0x%lx, size = 0x%lx, info_count = %d\n",address,size,info_count);
            printf("\tprotection = %d,max protect =%d,inheritance=%d,shared=%d,reserved=%d,offset=%llx,behavior=%d,wired=%x\n",info.protection,info.max_protection,info.inheritance,info.shared,info.reserved,info.offset,info.behavior,info.user_wired_count);
            fflush(stdout);
            break;
        }
    }
   
    vm_address_t startAddress = address;
    vm_size_t startSize = size;
    vm_address_t endAddress = address;
    for (address = startAddress; ;address += size) {
       
        kr = vm_region_64(kernMemPort,&address,&size,VM_REGION_BASIC_INFO_64,(vm_region_info_t)&info,&info_count,&notUsed);
        if(info.protection == 0){
            break;
        }
        endAddress = address; //want the page before the first unmmaped page
    }

    //get info from the last mapped page
    kr = vm_region_64(kernMemPort,&endAddress,&size,VM_REGION_BASIC_INFO_64,(vm_region_info_t)&info,&info_count,&notUsed);
    printf("vm_region returned %d\n",kr);
    printf("kernel end\n");
    printf("\taddress = 0x%lx, size = 0x%lx, info_count = %d\n",endAddress,size,info_count);
    printf("\tprotection = %d,max protect =%d,inheritance=%d,shared=%d,reserved=%d,offset=%llx,behavior=%d,wired=%x\n",info.protection,info.max_protection,info.inheritance,info.shared,info.reserved,info.offset,info.behavior,info.user_wired_count);
    fflush(stdout);
    printf("Kernel size is about 0x%lx\n",endAddress-startAddress);
   
   
    //Save to disk and hope for the best?
    FILE* outFile;
    outFile = fopen("/var/root/kerndump.dump","w");

    for (address= startAddress; address < endAddress; address += size) {
       
        kr = vm_region_64(kernMemPort,&address,&size,VM_REGION_BASIC_INFO_64,(vm_region_info_t)&info,&info_count,&notUsed);
       
        vm_offset_t *kernData = malloc(size);
        mach_msg_type_number_t dataRead;
       
        kr = mach_vm_read(kernMemPort,address,size,kernData,&dataRead);
        //printf("vm_read returned %d\n",kr);
        printf("read 0x%x bytes from the kernel mem\n",dataRead);
        fwrite(kernData,size,1,outFile);
    }
    fclose(outFile);

}
bob969
 
Posts: 8
Joined: Tue Mar 22, 2016 1:44 pm

Re: Pangu 9.1 Kernel Dump

Postby Siguza » Tue Mar 22, 2016 8:05 pm

Are you sure you're reading from the correct region?
I only know my way around iOS 8, but there seem to be too many differences.
From forking and tampering with saelo's kern-utils I learned that on iOS 8, the kernel maps over 1 GB of ram where it stores itself, that region has protection and max_protection both set to 0, and the reconstructed binary is about 20 MB.
Unless all of those things have changed, I suspect that you're reading from the wrong region.
Running kmap and grepping for 'M]' (region sizes in the megabytes) on iOS 8.4, I get:

Code: Select all
iPhone:~ mobile$ sudo kmap | fgrep 'M]'
ffffff8015800000-ffffff8097000000 [ 2072M] ---/---
ffffff8097000000-ffffff80adf7c000 [  367M] rw-/rwx

The kernel is in the 2072M region and I believe you're reading from the 367M one.
User avatar
Siguza
Unicorn
 
Posts: 158
Joined: Thu Jan 28, 2016 10:38 am

Re: Pangu 9.1 Kernel Dump

Postby Siguza » Tue Mar 22, 2016 8:51 pm

I added an experimental ios9 branch to my kern-utils fork.
I cannot test it though, because I have no device on 9.x.
Feel like testing kdump there? :P (if you do, make sure you clone the ios9-test branch and not master)
User avatar
Siguza
Unicorn
 
Posts: 158
Joined: Thu Jan 28, 2016 10:38 am

Re: Pangu 9.1 Kernel Dump

Postby bob969 » Wed Mar 23, 2016 2:03 pm

Thanks for the tips! Turns out I was reading from the wrong section of the kernel memory as you suspected. After playing with your experimental branch for a bit I was able to get it to dump a 9.1 kernel that works with joker. The image offset for the Mach-O header was changed and the buffer for storing the kernel had to be increased.
bob969
 
Posts: 8
Joined: Tue Mar 22, 2016 1:44 pm

Re: Pangu 9.1 Kernel Dump

Postby morpheus » Wed Mar 23, 2016 4:35 pm

Thanks for handling this one, Siguza. Bob - glad you got this working!
morpheus
Site Admin
 
Posts: 530
Joined: Thu Apr 11, 2013 6:24 pm

Re: Pangu 9.1 Kernel Dump

Postby Siguza » Wed Mar 23, 2016 6:25 pm

Happy I was able to help. :)
User avatar
Siguza
Unicorn
 
Posts: 158
Joined: Thu Jan 28, 2016 10:38 am

Re: Pangu 9.1 Kernel Dump

Postby backendbilly » Fri Mar 25, 2016 5:16 pm

I tried Siguza's latest test of ios-kern-utils on 9.1 but keep getting:

Code: Select all
iPhone:~ root# ./kdump3
[*] found kernel base at address 0xffffff8016002000
[*] reading kernel header...
[!] header has wrong magic, expected: 0xfeedfacf, found: 0x3af28282



I also tested it on 9.0.2. Getting different error:

Code: Select all
[!] could not find kernel base address
backendbilly
Site Admin
 
Posts: 132
Joined: Fri May 29, 2015 5:58 pm

Re: Pangu 9.1 Kernel Dump

Postby Siguza » Fri Mar 25, 2016 7:17 pm

Could you give me the output of kmap on 9.0.2?

And could you run the following program on 9.1 and give me its output too?:
Code: Select all
// dump this into ios-kern-utils repo as test.c, then run:
// xcrun -sdk iphoneos gcc -arch armv7 -arch arm64 -Ilib/kernel lib/kernel/*.c -o test test.c
// codesign -s - --entitlements misc/ent.xml test
#include <stdio.h>
#include <mach-o/loader.h>
#include "libkern.h"

#if __LP64__
#define MACH_HEADER_MAGIC MH_MAGIC_64
#else
#define MACH_HEADER_MAGIC MH_MAGIC
#endif

int main()
{
    int magic = MACH_HEADER_MAGIC;
    vm_address_t base = get_kernel_base();
    printf("base: " ADDR "\n", base);
    if(base == 0)
    {
        return 1;
    }
    for(vm_address_t off = base - IMAGE_OFFSET; off < base + 0x10000; ++off)
    {
        off = find_bytes_kern(off, base + 0x10000, (unsigned char*)&magic, sizeof(int));
        if(off == 0)
            break;
        else
            printf(ADDR "\n", off);
    }
    return 0;
}
User avatar
Siguza
Unicorn
 
Posts: 158
Joined: Thu Jan 28, 2016 10:38 am

Re: Pangu 9.1 Kernel Dump

Postby backendbilly » Fri Mar 25, 2016 7:43 pm

I ran kmap on 9.0.2. Nothing comes back

Code: Select all
iPhone:~ root# ./kmap
iPhone:~ root#


Here is the output of test on 9.1:

Code: Select all
iPhone:~ root# ./test
base: ffffff8016002000
iPhone:~ root#
backendbilly
Site Admin
 
Posts: 132
Joined: Fri May 29, 2015 5:58 pm

Re: Pangu 9.1 Kernel Dump

Postby Siguza » Fri Mar 25, 2016 8:12 pm

Ok, could you add two zeroes to both occurrences of 0x10000 in test.c and try again?

And it seems that vm_region_recurse_64 fails on 9.0.2... could you run this there?:
Code: Select all
#include <stdio.h>
#include <mach/vm_map.h>
#include "libkern.h"

int main()
{
    kern_return_t ret;
    task_t kernel_task;
    vm_region_submap_info_data_64_t info;
    vm_size_t size;
    mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
    unsigned int depth = 0;
    ret = get_kernel_task(&kernel_task);
    if(ret != KERN_SUCCESS)
    {
        printf("Failed to get kernel task\n");
        return 1;
    }
    for(vm_address_t addr = 0; 1; addr += size)
    {
        ret = vm_region_recurse_64(kernel_task, &addr, &size, &depth, (vm_region_info_t)&info, &info_count);
        if(ret != KERN_SUCCESS)
        {
            printf("return value: %u\n", ret);
            break;
        }
        printf(ADDR "-" ADDR "\n", addr, addr + size);
    }
    return 0;
}
User avatar
Siguza
Unicorn
 
Posts: 158
Joined: Thu Jan 28, 2016 10:38 am

Next

Return to Questions and Answers

Who is online

Users browsing this forum: No registered users and 1 guest