Home

Awesome

kfund (Post-Exploitation)

kfund, short for my fun with kfd exploit.

Supported Device

Experimental dynamic patchfinder is now working (patchfinder only works with landa/physpuppet exploit), <br> so...<br><br> Supposed to be work: <br> iOS/iPadOS 16.0-16.6.1

What you can do with this?

utils.m

int ResSet16(NSInteger height, NSInteger width);
int setSuperviseMode(BOOL enable);
int removeKeyboardCache(void);
int removeSMSCache(void);
int regionChanger(NSString *country_value, NSString *region_value);
bool sandbox_escape_can_i_access_file(char* path, int mode);
void HexDump(uint64_t addr, size_t size);

vnode.c

uint64_t getVnodeAtPath(char* filename);
uint64_t getVnodeAtPathByChdir(char *path);
uint64_t findRootVnode(void);
uint64_t funVnodeHide(char* filename);
uint64_t funVnodeHide(char* filename);
uint64_t funVnodeChown(char* filename, uid_t uid, gid_t gid);
uint64_t funVnodeChmod(char* filename, mode_t mode);
uint64_t funVnodeRedirectFolder(char* to, char* from);
uint64_t funVnodeOverwriteFile(char* to, char* from);
uint64_t funVnodeIterateByPath(char* dirname);
uint64_t funVnodeIterateByVnode(uint64_t vnode);
uint64_t funVnodeRedirectFolderFromVnode(char* to, uint64_t from_vnode);
uint64_t funVnodeUnRedirectFolder(char* to, uint64_t orig_to_v_data);
uint64_t findChildVnodeByVnode(uint64_t vnode, char* childname);
uint64_t funVnodeOverwriteFileUnlimitSize(char* to, char* from);
uint64_t funVnodeRedirectFile(char* to, char* from, uint64_t* orig_to_vnode, uint64_t* orig_nc_vp);
uint64_t funVnodeUnRedirectFile(uint64_t orig_to_vnode, uint64_t orig_nc_vp);

cs_blobs.c

uint64_t fun_proc_dump_entitlements(uint64_t proc);
uint64_t fun_vnode_dump_entitlements(const char* path);

proc.c

uint64_t getProc(pid_t pid);
uint64_t getProcByName(char* nm);
int getPidByName(char* nm)

fun.m

int funUcred(uint64_t proc);
int funTask(char* process);
uint64_t fun_nvram_dump(void);
int do_fun(void);

kfd

kfd, short for kernel file descriptor, is a project to read and write kernel memory on Apple devices. It leverages various vulnerabilities that can be exploited to obtain dangling PTEs, which will be referred to as a PUAF primitive, short for "physical use-after-free". Then, it reallocates certain kernel objects inside those physical pages and manipulates them directly from user space through the dangling PTEs in order to achieve a KRKW primitive, short for "kernel read/write". The exploit code is fully contained in a library, libkfd, but the project also contains simple executable wrappers for iOS and macOS. The public API of libkfd is quite small and intuitive:

enum puaf_method {
    puaf_physpuppet,
    puaf_smith,
};

enum kread_method {
    kread_kqueue_workloop_ctl,
    kread_sem_open,
};

enum kwrite_method {
    kwrite_dup,
    kwrite_sem_open,
};

u64 kopen(u64 puaf_pages, u64 puaf_method, u64 kread_method, u64 kwrite_method);
void kread(u64 kfd, u64 kaddr, void* uaddr, u64 size);
void kwrite(u64 kfd, void* uaddr, u64 kaddr, u64 size);
void kclose(u64 kfd);

kopen() conceptually opens a "kernel file descriptor". It takes the following 4 arguments:

If the exploit is successful, kopen() returns a 64-bit opaque file descriptor. In practice, this is just a user space pointer to a structure needed by libkfd. However, since that structure should not be accessed outside of the library, it is returned as an opaque integer. If the exploit is unsuccessful, the library will print an error message, sleep for 30 seconds, then exit with a status code of 1. It sleeps for 30 seconds because the kernel might panic on exit for certain PUAF methods that require some cleanup post-KRKW (e.g. puaf_smith).

kread() and kwrite() are the user space equivalent of copyout() and copyin(), respectively. Please note that the options for kread_method and kwrite_method are described in a separate write-up. In addition, the initial primitives granted by those methods can be used to bootstrap a better KRKW primitive. Finally, kclose() simply closes the kernel file descriptor. They all take the opaque integer returned by kopen() as their first argument.


What are the supported OS versions and devices?

The later stage of the exploit makes use of various offsets. For the structures that have identical offsets across all versions that I tested, I simply included their definitions under the static_types folder. For the structures that have different offsets, I built offset tables for them under the dynamic_types folder. Then, I map the "kern.osversion" of the device to the appropriate index for those offset tables. Please check the function info_init(), located in info.h, for the list of currently supported iOS and macOS versions. However, please note that I only tested the exploits on an iPhone 14 Pro Max and a MacBook Air (M2 2022). Therefore, it is possible that the offsets are actually different on other devices, even for the same OS version. Keep this in mind if you get a "Kernel data abort" panic on a "supported" version. Fortunately, those offsets should all be easily retrievable from the XNU source code.

On the other hand, in order to bootstrap the better KRKW primitive, the exploit makes use of certain static addresses which must be retrieved from the kernelcache. This is a tedious process, which I only carried out for the kernelcaches of certain iOS versions on the iPhone 14 Pro Max. Please check the function perf_init(), located in perf.h, for the list of currently supported versions. Note that none of the exploits require the better KRKW primitive in order to succeed. However, if you plan on doing research based on this project, then it is probably worthwhile to add support for the better KRKW primitive for your own device!


How to build and run kfd on an iPhone?

In Xcode, open the root folder of the project and connect your iOS device.


How to build and run kfd on a Mac?

In a terminal, navigate to the root folder of the project.

Optionally, to increase the global and per-process file descriptor limits, which will improve the success rate especially on multiple consecutive runs, enter the command make s and type in the sudo password.


Where to find detailed write-ups for the exploits?

This README presented a high-level overview of the kfd project. Once a PUAF primitive has been achieved, the rest of the exploit is generic. Therefore, I have hoisted the common part of the exploits in a dedicated write-up:

In addition, I have split the vulnerability-specific part of the exploits used to achieve the PUAF primitive into distinct write-ups, listed below in chronological order of discovery:

However, please note that these write-ups have been written for an audience that is already familiar with the XNU virtual memory system.