mirror of https://github.com/opa334/TrollStore.git
439 lines
11 KiB
Objective-C
439 lines
11 KiB
Objective-C
//
|
|
// KernelManager.m
|
|
// NonceSet15
|
|
//
|
|
// Created by Lars Fröder on 02.06.22.
|
|
//
|
|
|
|
#import "KernelManager.h"
|
|
|
|
@implementation KernelManager
|
|
|
|
+ (instancetype)sharedInstance
|
|
{
|
|
static KernelManager *sharedInstance = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
sharedInstance = [[KernelManager alloc] init];
|
|
});
|
|
return sharedInstance;
|
|
}
|
|
|
|
- (void)loadOffsets
|
|
{
|
|
struct StaticOffsets staticOffsets;
|
|
// iPhone 13 Pro, 15.1.1
|
|
staticOffsets.kernel_base = 0xFFFFFFF007004000;
|
|
staticOffsets.sandbox_secret = 0xFFFFFFF009DF2140;
|
|
staticOffsets.allproc = 0xFFFFFFF009D86AA0;
|
|
staticOffsets.kauth_cred_table_anchor = 0xFFFFFFF009DE0988;
|
|
staticOffsets.cs_debug = 0xFFFFFFF009D86990;
|
|
|
|
self.static_offsets = staticOffsets;
|
|
|
|
struct ProcOffsets proc;
|
|
proc.task_offset = 0x10;
|
|
proc.pid_offset = 0x68;
|
|
proc.comm_offset = 0x2C8;
|
|
proc.name_offset = 0x2D9;
|
|
proc.ucred_offset = 0xD8;
|
|
proc.textvp_offset = 0x2A8;
|
|
proc.textoff_offset = 0x2B0;
|
|
proc.csflags_offset = 0x300;
|
|
proc.fd_offset = 0xE0;
|
|
|
|
struct UCredOffsets ucred;
|
|
ucred.posix_offset = 0x18;
|
|
ucred.label_offset = 0x78;
|
|
ucred.audit_offset = 0x80;
|
|
|
|
struct TaskOffsets task;
|
|
task.map_offset = 0x28;
|
|
task.threads_offset = 0x58;
|
|
task.itk_space_offset = 0x330;
|
|
task.rop_pid_offset = 0x360;
|
|
task.jop_pid_offset = 0x368;
|
|
task.disable_user_jop_offset = 0x370;
|
|
task.t_flags_offset = 0x41C;
|
|
|
|
struct ThreadOffsets thread;
|
|
thread.task_threads_offset = 0x400;
|
|
thread.disable_user_jop_offset = 0x167;
|
|
thread.rop_pid_offset = 0x168;
|
|
thread.jop_pid_offset = 0x170;
|
|
|
|
struct ItkSpaceOffsets itk_space;
|
|
itk_space.is_table_offset = 0x20;
|
|
|
|
struct IpcEntryOffsets ipc_entry;
|
|
ipc_entry.size = 0x18;
|
|
|
|
struct FileDescriptorOffsets fd;
|
|
fd.ofiles_offset = 0x20; // proc + 256
|
|
// numfiles: 0xC, proc + 244
|
|
// fd_ofileflags: proc + 264
|
|
|
|
struct FileProcOffsets fproc;
|
|
fproc.glob_offset = 0x10;
|
|
|
|
struct FileGlobOffsets fglob;
|
|
fglob.data_offset = 0x38;
|
|
|
|
struct VnodeOffsets vnode;
|
|
vnode.un_offset.ubcinfo = 0x78;
|
|
vnode.type_offset = 0x70;
|
|
vnode.flag_offset = 0x54;
|
|
|
|
struct UbcInfoOffsets ubc_info;
|
|
ubc_info.csblobs_offset = 0x50;
|
|
|
|
struct CsBlobOffsets csblob;
|
|
csblob.team_id_offset = 0x80;
|
|
csblob.platform_binary_offset = 0xB8;
|
|
csblob.pmap_cs_entry_offset = 0xC0;
|
|
|
|
struct VmMapOffsets vmmap;
|
|
vmmap.header_offset = 0x10;
|
|
vmmap.pmap_offset = 0x48;
|
|
vmmap.flag_offset = 0x11C;
|
|
|
|
struct VmHeaderOffsets vmheader;
|
|
vmheader.links_offset = 0x0;
|
|
vmheader.numentry_offset = 0x20;
|
|
|
|
struct VmMapLinkOffsets vmlink;
|
|
vmlink.prev_offset = 0x0;
|
|
vmlink.next_offset = 0x8;
|
|
|
|
struct VmMapEntryOffsets vmentry;
|
|
vmentry.links_offset = 0x0;
|
|
vmentry.flag_bits_offset = 0x48;
|
|
|
|
|
|
// vm header:
|
|
// links: 0x00
|
|
// nentries: 0x20
|
|
// ..
|
|
|
|
struct CsDirEntryOffsets csdirentry;
|
|
csdirentry.trust_level_offset = 0x9C;
|
|
|
|
struct StructOffsets structOffsets;
|
|
structOffsets.proc = proc;
|
|
structOffsets.ucred = ucred;
|
|
structOffsets.task = task;
|
|
structOffsets.thread = thread;
|
|
structOffsets.itk_space = itk_space;
|
|
structOffsets.ipc_entry = ipc_entry;
|
|
structOffsets.fd = fd;
|
|
structOffsets.fproc = fproc;
|
|
structOffsets.fglob = fglob;
|
|
structOffsets.vnode = vnode;
|
|
structOffsets.ubc_info = ubc_info;
|
|
structOffsets.csblob = csblob;
|
|
structOffsets.vmmap = vmmap;
|
|
structOffsets.csdirentry = csdirentry;
|
|
structOffsets.vmheader = vmheader;
|
|
structOffsets.vmlink = vmlink;
|
|
structOffsets.vmentry = vmentry;
|
|
|
|
self.struct_offsets = structOffsets;
|
|
}
|
|
|
|
- (void)_loadSlidOffsets
|
|
{
|
|
struct SlidOffsets slidOffsets;
|
|
slidOffsets.sandbox_secret = _static_offsets.sandbox_secret + self.kernel_slide;
|
|
slidOffsets.allproc = _static_offsets.allproc + self.kernel_slide;
|
|
slidOffsets.kauth_cred_table_anchor = _static_offsets.kauth_cred_table_anchor + self.kernel_slide;
|
|
slidOffsets.cs_debug = _static_offsets.cs_debug + self.kernel_slide;
|
|
self.slid_offsets = slidOffsets;
|
|
}
|
|
|
|
- (void)loadSlidOffsetsWithKernelSlide:(uint64_t)kernel_slide
|
|
{
|
|
self.kernel_base = self.static_offsets.kernel_base + kernel_slide;
|
|
self.kernel_slide = kernel_slide;
|
|
[self _loadSlidOffsets];
|
|
}
|
|
|
|
- (void)loadSlidOffsetsWithKernelBase:(uint64_t)kernel_base
|
|
{
|
|
self.kernel_base = kernel_base;
|
|
self.kernel_slide = kernel_base - self.static_offsets.kernel_base;
|
|
[self _loadSlidOffsets];
|
|
}
|
|
|
|
- (uint64_t)read64BitValueAtAddress:(uint64_t)addr
|
|
{
|
|
if(_kread_64_d)
|
|
{
|
|
return _kread_64_d(addr);
|
|
}
|
|
else
|
|
{
|
|
uint64_t outInt = 0;
|
|
int suc = 0;
|
|
|
|
if(_kread_64_id)
|
|
{
|
|
_kread_64_id(addr, &outInt);
|
|
}
|
|
else if(_kread_64_id_ret)
|
|
{
|
|
suc = _kread_64_id_ret(addr, &outInt);
|
|
}
|
|
else if(_kread64_block)
|
|
{
|
|
suc = _kread64_block(addr, &outInt);
|
|
}
|
|
else
|
|
{
|
|
uint8_t* b = (uint8_t*)&outInt;
|
|
*(uint32_t *)b = [self read32BitValueAtAddress:addr];
|
|
*(uint32_t *)(b + 4) = [self read32BitValueAtAddress:addr + 4];
|
|
}
|
|
|
|
if(suc != 0)
|
|
{
|
|
NSLog(@"ERROR reading kernel memory (%llX): %d", addr, suc);
|
|
}
|
|
|
|
return outInt;
|
|
}
|
|
|
|
}
|
|
|
|
- (uint32_t)read32BitValueAtAddress:(uint64_t)addr
|
|
{
|
|
if(_kread_32_d)
|
|
{
|
|
return _kread_32_d(addr);
|
|
}
|
|
else
|
|
{
|
|
uint32_t outInt = 0;
|
|
int suc = 0;
|
|
if(_kread_32_id)
|
|
{
|
|
_kread_32_id(addr, &outInt);
|
|
}
|
|
else if(_kread_32_id_ret)
|
|
{
|
|
suc = _kread_32_id_ret(addr, &outInt);
|
|
}
|
|
else if(_kread32_block)
|
|
{
|
|
suc = _kread32_block(addr, &outInt);
|
|
}
|
|
if(suc != 0)
|
|
{
|
|
NSLog(@"ERROR read kernel memory (%llX): %d", addr, suc);
|
|
}
|
|
return outInt;
|
|
}
|
|
}
|
|
|
|
- (int)readBufferAtAddress:(uint64_t)addr intoBuffer:(void*)outBuf withLength:(size_t)len
|
|
{
|
|
//printf("read at %llX - %lX\n", addr, len);
|
|
//usleep(50);
|
|
|
|
if(_kread_buf)
|
|
{
|
|
return _kread_buf(addr, outBuf, len);
|
|
}
|
|
else
|
|
{
|
|
uint64_t endAddr = addr + len;
|
|
uint32_t outputOffset = 0;
|
|
unsigned char* outputBytes = (unsigned char*)outBuf;
|
|
|
|
for(uint64_t curAddr = addr; curAddr < endAddr; curAddr += 4)
|
|
{
|
|
//printf("read %llX\n", curAddr);
|
|
//usleep(1000);
|
|
uint32_t k = [self read32BitValueAtAddress:curAddr];
|
|
|
|
unsigned char* kb = (unsigned char*)&k;
|
|
for(int i = 0; i < 4; i++)
|
|
{
|
|
if(outputOffset == len) break;
|
|
outputBytes[outputOffset] = kb[i];
|
|
outputOffset++;
|
|
}
|
|
if(outputOffset == len) break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
- (int)copyStringAtAddress:(uint64_t)addr intoBuffer:(void*)outBuf withBufferSize:(size_t)bufSize
|
|
{
|
|
bzero(outBuf, bufSize);
|
|
char* outBufStr = (char*)outBuf;
|
|
|
|
uint64_t maxEndAddr = addr + bufSize;
|
|
int ci = 0;
|
|
|
|
for(uint64_t curAddr = addr; curAddr < maxEndAddr; curAddr += 4)
|
|
{
|
|
uint32_t k = [self read32BitValueAtAddress:curAddr];
|
|
char* kb = (char*)&k;
|
|
for(int i = 0; i < 4; i++)
|
|
{
|
|
char c = kb[i];
|
|
if(c == '\0') return 0;
|
|
outBufStr[ci] = c;
|
|
ci++;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void DumpHex(const void* data, size_t size) {
|
|
char ascii[17];
|
|
size_t i, j;
|
|
ascii[16] = '\0';
|
|
for (i = 0; i < size; ++i) {
|
|
if(i % 16 == 0)
|
|
{
|
|
printf("0x%zX | ", i);
|
|
}
|
|
printf("%02X ", ((unsigned char*)data)[i]);
|
|
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
|
|
ascii[i % 16] = ((unsigned char*)data)[i];
|
|
} else {
|
|
ascii[i % 16] = '.';
|
|
}
|
|
if ((i+1) % 8 == 0 || i+1 == size) {
|
|
printf(" ");
|
|
if ((i+1) % 16 == 0) {
|
|
printf("| %s \n", ascii);
|
|
} else if (i+1 == size) {
|
|
ascii[(i+1) % 16] = '\0';
|
|
if ((i+1) % 16 <= 8) {
|
|
printf(" ");
|
|
}
|
|
for (j = (i+1) % 16; j < 16; ++j) {
|
|
printf(" ");
|
|
}
|
|
printf("| %s \n", ascii);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (int)dumpHexAtAddress:(uint64_t)addr withLength:(size_t)len
|
|
{
|
|
void* buffer = malloc(len);
|
|
int ret = [self readBufferAtAddress:addr intoBuffer:buffer withLength:len];
|
|
if(ret == 0)
|
|
{
|
|
DumpHex(buffer, len);
|
|
}
|
|
free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
- (int)write64BitValue:(uint64_t)value toAddress:(uint64_t)addr
|
|
{
|
|
if(_kwrite_64)
|
|
{
|
|
_kwrite_64(addr, value);
|
|
}
|
|
else if(_kwrite_64_ret)
|
|
{
|
|
return _kwrite_64_ret(addr, value);
|
|
}
|
|
else if(_kwrite64_block)
|
|
{
|
|
return _kwrite64_block(addr, value);
|
|
}
|
|
else
|
|
{
|
|
int r1 = [self write32BitValue:(uint32_t)value toAddress:addr];
|
|
int r2 = [self write32BitValue:(uint32_t)(value >> 32) toAddress:addr + 4];
|
|
return r1 || r2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
- (int)write32BitValue:(uint32_t)value toAddress:(uint64_t)addr
|
|
{
|
|
if(_kwrite_32)
|
|
{
|
|
_kwrite_32(addr, value);
|
|
}
|
|
else if(_kwrite_32_ret)
|
|
{
|
|
return _kwrite_32_ret(addr, value);
|
|
}
|
|
else if(_kwrite32_block)
|
|
{
|
|
return _kwrite32_block(addr, value);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
- (int)writeBuffer:(void*)inBuf withLength:(size_t)len toAddress:(uint64_t)addr
|
|
{
|
|
//printf("write to %llX - %lX\n", addr, len);
|
|
//usleep(50);
|
|
|
|
if(_kwrite_buf)
|
|
{
|
|
return _kwrite_buf(addr, inBuf, len);
|
|
}
|
|
else
|
|
{
|
|
uint64_t endAddr = addr + len;
|
|
uint32_t inputOffset = 0;
|
|
unsigned char* inputBytes = (unsigned char*)inBuf;
|
|
|
|
for(uint64_t curAddr = addr; curAddr < endAddr; curAddr += 4)
|
|
{
|
|
uint32_t toWrite = 0;
|
|
int bc = 4;
|
|
|
|
uint64_t remainingBytes = endAddr - curAddr;
|
|
if(remainingBytes < 4)
|
|
{
|
|
toWrite = [self read32BitValueAtAddress:curAddr];
|
|
bc = (int)remainingBytes;
|
|
}
|
|
|
|
unsigned char* wb = (unsigned char*)&toWrite;
|
|
for(int i = 0; i < bc; i++)
|
|
{
|
|
wb[i] = inputBytes[inputOffset];
|
|
inputOffset++;
|
|
}
|
|
|
|
//printf("write %X to %llX\n", toWrite, curAddr);
|
|
//usleep(1000);
|
|
|
|
[self write32BitValue:toWrite toAddress:curAddr];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
- (void)finishAndCleanupIfNeeded
|
|
{
|
|
if(_kcleanup)
|
|
{
|
|
_kcleanup();
|
|
}
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[self finishAndCleanupIfNeeded];
|
|
}
|
|
|
|
@end
|