161 lines
4.3 KiB
Objective-C
161 lines
4.3 KiB
Objective-C
|
|
#import "kernel_utils.h"
|
|
#import "patchfinder64.h"
|
|
|
|
static mach_port_t tfpzero;
|
|
static uint64_t kernel_base;
|
|
static uint64_t KASLR_Slide;
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#define LOG(str, args...) do { NSLog(@"[*] " str "\n", ##args); } while(0)
|
|
|
|
void init_kernel_utils(mach_port_t tfp0, uint64_t kbase) {
|
|
tfpzero = tfp0;
|
|
kernel_base = kbase;
|
|
KASLR_Slide = (uint32_t)(kernel_base - 0xFFFFFFF007004000); // slid kernel base - kernel base = kaslr slide
|
|
}
|
|
|
|
uint64_t get_kernel_slide() {
|
|
return KASLR_Slide;
|
|
}
|
|
|
|
uint64_t Kernel_alloc(vm_size_t size) {
|
|
mach_vm_address_t address = 0;
|
|
mach_vm_allocate(tfpzero, (mach_vm_address_t *)&address, size, VM_FLAGS_ANYWHERE);
|
|
return address;
|
|
}
|
|
|
|
void Kernel_free(mach_vm_address_t address, vm_size_t size) {
|
|
mach_vm_deallocate(tfpzero, address, size);
|
|
}
|
|
|
|
int Kernel_strcmp(uint64_t kstr, const char* str) {
|
|
// XXX be safer, dont just assume you wont cause any
|
|
// page faults by this
|
|
size_t len = strlen(str) + 1;
|
|
char *local = malloc(len + 1);
|
|
local[len] = '\0';
|
|
|
|
int ret = 1;
|
|
|
|
if (KernelRead(kstr, local, len) == len) {
|
|
ret = strcmp(local, str);
|
|
}
|
|
|
|
free(local);
|
|
|
|
return ret;
|
|
}
|
|
|
|
size_t KernelRead(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(tfpzero, where + offset, chunk, (mach_vm_address_t)p + offset, &sz);
|
|
if (rv || sz == 0) {
|
|
printf("[-] error on KernelRead(0x%016llx)\n", where);
|
|
break;
|
|
}
|
|
offset += sz;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
uint32_t KernelRead_32bits(uint64_t where) {
|
|
uint32_t out;
|
|
KernelRead(where, &out, sizeof(uint32_t));
|
|
return out;
|
|
}
|
|
|
|
uint64_t KernelRead_64bits(uint64_t where) {
|
|
uint64_t out;
|
|
KernelRead(where, &out, sizeof(uint64_t));
|
|
return out;
|
|
}
|
|
|
|
size_t KernelWrite(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(tfpzero, where + offset, (mach_vm_offset_t)p + offset, chunk);
|
|
if (rv) {
|
|
printf("[-] error on KernelWrite(0x%016llx)\n", where);
|
|
break;
|
|
}
|
|
offset += chunk;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
void KernelWrite_32bits(uint64_t where, uint32_t what) {
|
|
uint32_t _what = what;
|
|
KernelWrite(where, &_what, sizeof(uint32_t));
|
|
}
|
|
|
|
|
|
void KernelWrite_64bits(uint64_t where, uint64_t what) {
|
|
uint64_t _what = what;
|
|
KernelWrite(where, &_what, sizeof(uint64_t));
|
|
}
|
|
|
|
const uint64_t kernel_address_space_base = 0xffff000000000000;
|
|
void Kernel_memcpy(uint64_t dest, uint64_t src, uint32_t length) {
|
|
if (dest >= kernel_address_space_base) {
|
|
// copy to kernel:
|
|
KernelWrite(dest, (void*) src, length);
|
|
} else {
|
|
// copy from kernel
|
|
KernelRead(src, (void*)dest, length);
|
|
}
|
|
}
|
|
|
|
uint64_t proc_of_pid(pid_t pid) {
|
|
uint64_t allproc = Find_allproc();
|
|
uint64_t proc = KernelRead_64bits(allproc), pd;
|
|
|
|
while (proc) { //iterate over all processes till we find the one we're looking for
|
|
pd = KernelRead_32bits(proc + 0x10);
|
|
if (pd == pid) return proc;
|
|
proc = KernelRead_64bits(proc);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint64_t ZmFixAddr(uint64_t addr) {
|
|
static kmap_hdr_t zm_hdr = {0, 0, 0, 0};
|
|
|
|
if (zm_hdr.start == 0) {
|
|
// xxx rk64(0) ?!
|
|
uint64_t zone_map = KernelRead_64bits(Find_zone_map_ref());
|
|
// hdr is at offset 0x10, mutexes at start
|
|
size_t r = KernelRead(zone_map + 0x10, &zm_hdr, sizeof(zm_hdr));
|
|
//printf("zm_range: 0x%llx - 0x%llx (read 0x%zx, exp 0x%zx)\n", zm_hdr.start, zm_hdr.end, r, sizeof(zm_hdr));
|
|
|
|
if (r != sizeof(zm_hdr) || zm_hdr.start == 0 || zm_hdr.end == 0) {
|
|
printf("[-] KernelRead of zone_map failed!\n");
|
|
return 1;
|
|
}
|
|
|
|
if (zm_hdr.end - zm_hdr.start > 0x100000000) {
|
|
printf("[-] zone_map is too big, sorry.\n");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
uint64_t zm_tmp = (zm_hdr.start & 0xffffffff00000000) | ((addr) & 0xffffffff);
|
|
|
|
return zm_tmp < zm_hdr.start ? zm_tmp + 0x100000000 : zm_tmp;
|
|
}
|
|
|
|
|
|
|