mirror of
https://github.com/EchoStretch/kstuff.git
synced 2026-10-22 03:32:25 -05:00
ps5-kstuff: add "run in foreign process" kekcall
Also adds support for arbitrary mprotect & mdbg_call without creds.
This commit is contained in:
1 parent
2dc99448fb
commit
d0cdc83e8a
11 files changed
+151
-46
No files matched your search
@@ -696,6 +696,7 @@ void* mmap20(void* addr, size_t sz, int prot, int flags, int fd, off_t offset)
|
||||
|
||||
static uint64_t sys_write;
|
||||
static uint64_t sys_sigaction;
|
||||
static uint64_t sys_mdbg_call;
|
||||
|
||||
static void fix_sigaction_17_9(uint64_t* regs)
|
||||
{
|
||||
@@ -763,6 +764,30 @@ int get_self_auth_info_20(const char* path, void* buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fix_mdbg_call(uint64_t* regs)
|
||||
{
|
||||
SKIP_SCHEDULER
|
||||
if(regs[0] == sys_write)
|
||||
regs[0] = sys_mdbg_call;
|
||||
else if(regs[0] == kdata_base - 0x631ea9)
|
||||
regs[5] = 1;
|
||||
}
|
||||
|
||||
int mdbg_call_20(void* a, void* b, void* c)
|
||||
{
|
||||
r0gdb_instrument(0);
|
||||
int(*p_write)(void*, void*, void*) = dlsym((void*)0x2001, "_write");
|
||||
trace_prog = fix_mdbg_call;
|
||||
if(!sys_write)
|
||||
kmemcpy(&sys_write, (void*)(kdata_base + 0x1709c0 + 48*SYS_write + 8), 8);
|
||||
if(!sys_mdbg_call)
|
||||
kmemcpy(&sys_mdbg_call, (void*)(kdata_base + 0x1709c0 + 48*573 + 8), 8);
|
||||
set_trace();
|
||||
int ans = p_write(a, b, c);
|
||||
trace_prog = 0;
|
||||
return ans;
|
||||
}
|
||||
|
||||
static uint64_t fncall_fn = 0;
|
||||
static uint64_t fncall_args[6];
|
||||
static uint64_t fncall_ans = 0;
|
||||
|
||||
@@ -70,6 +70,9 @@ int sigaction20(int sig, const struct sigaction* neww, struct sigaction* oldd);
|
||||
//get_self_auth_info that works
|
||||
int get_self_auth_info_20(const char* path, void* buf);
|
||||
|
||||
//mdbg_call that works
|
||||
int mdbg_call_20(void* a, void* b, void* c);
|
||||
|
||||
//kernel function call
|
||||
uint64_t r0gdb_kfncall(uint64_t kfn, ...);
|
||||
|
||||
|
||||
+1
-1
@@ -33,4 +33,4 @@ uelf/crt.o: uelf/crt.asm
|
||||
yasm uelf/crt.asm -f elf64 -o uelf/crt.o
|
||||
|
||||
uelf/uelf: uelf/*.c uelf/*.h structs.h uelf/crt.o
|
||||
gcc -Wl,-Bsymbolic -O0 -g -isystem ../freebsd-headers -nostdinc -nostdlib -mgeneral-regs-only -fno-stack-protector -fPIE -fPIC -shared -ffreestanding -fno-builtin uelf/crt.o uelf/*.c -o uelf/uelf
|
||||
gcc -Wl,-Bsymbolic -Wl,-gc-sections -ffunction-sections -fdata-sections -O0 -g -isystem ../freebsd-headers -nostdinc -nostdlib -mgeneral-regs-only -fno-stack-protector -fPIE -fPIC -shared -ffreestanding -fno-builtin uelf/crt.o uelf/*.c -o uelf/uelf
|
||||
@@ -19,7 +19,7 @@ uelf/crt.o: uelf/crt.asm
|
||||
yasm uelf/crt.asm -f elf64 -o uelf/crt.o
|
||||
|
||||
uelf/uelf: uelf/*.c uelf/*.h structs.h uelf/crt.o
|
||||
gcc -Wl,-zmax-page-size=4096 -Wl,-Bsymbolic -O0 -g -DFREEBSD -std=gnu11 -nostdlib -fno-stack-protector -fPIE -fPIC -shared -ffreestanding -fno-builtin uelf/crt.o uelf/*.c -o uelf/uelf
|
||||
gcc -Wl,-zmax-page-size=4096 -Wl,-Bsymbolic -Wl,-gc-sections -ffunction-sections -fdata-sections -O0 -g -DFREEBSD -std=gnu11 -nostdlib -fno-stack-protector -fPIE -fPIC -shared -ffreestanding -fno-builtin uelf/crt.o uelf/*.c -o uelf/uelf
|
||||
|
||||
freebsd-loader: uelf/uelf kelf freebsd-loader.c
|
||||
gcc -O0 -g -std=gnu11 freebsd-loader.c -mno-red-zone -o freebsd-loader
|
||||
@@ -7,3 +7,4 @@ Calls:
|
||||
* rax = 0x100000027, rdi = X -> copy dr0-dr3 and dr6-dr7 to user address X
|
||||
* rax = 0x200000027, rdi = X -> copy dr0-dr3 and dr6-dr7 from user address X
|
||||
* rax = 0x300000027, rdi = X -> returns rdmsr(X)
|
||||
* rax = 0x500000027, rdi = pid, rsi = syscno, rdx = X -> call syscall in foreign process, with args read from user address X
|
||||
@@ -322,9 +322,12 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
"loadSelfSegment_epilogue"+zero,
|
||||
"loadSelfSegment_watchpoint"+zero,
|
||||
"loadSelfSegment_watchpoint_lr"+zero,
|
||||
"mdbg_call_fix"+zero,
|
||||
"mini_syscore_header"+zero,
|
||||
"mov_cr3_rax"+zero,
|
||||
"mov_rdi_cr3"+zero,
|
||||
"mprotect_fix_start"+zero,
|
||||
"mprotect_fix_end"+zero,
|
||||
"nop_ret"+zero,
|
||||
".pcpu"+zero,
|
||||
"pop_all_except_rdi_iret"+zero,
|
||||
@@ -375,9 +378,12 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
kdata_base - 0x8a54cd, // loadSelfSegment_epilogue
|
||||
kdata_base - 0x2cc918, // loadSelfSegment_watchpoint
|
||||
kdata_base - 0x8a5727, // loadSelfSegment_watchpoint_lr
|
||||
kdata_base - 0x631ea9, // mdbg_call_fix
|
||||
kdata_base + 0xdc16e8, // mini_syscore_header
|
||||
kdata_base - 0x396f9e, // mov_cr3_rax
|
||||
kdata_base - 0x39700e, // mov_rdi_cr3
|
||||
kdata_base - 0x90ac61, // mprotect_fix_start
|
||||
kdata_base - 0x90ac5b, // mprotect_fix_end
|
||||
kdata_base - 0x28a3a0, // nop_ret
|
||||
0x1234, // .pcpu
|
||||
kdata_base - 0x9cf8a7, // pop_all_except_rdi_iret
|
||||
@@ -455,6 +461,7 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
kelf_bases[cpu] = (uint64_t)kelf;
|
||||
kelf_entries[cpu] = (uint64_t)entry;
|
||||
}
|
||||
r0gdb_wrmsr(0xc0000084, r0gdb_rdmsr(0xc0000084) | 0x100);
|
||||
gdb_remote_syscall("write", 3, 0, (uintptr_t)1, (uintptr_t)"done loading\npatching idt... ", (uintptr_t)29);
|
||||
uint64_t cr3 = r0gdb_read_cr3();
|
||||
for(int cpu = 0; cpu < NCPUS; cpu++)
|
||||
@@ -482,6 +489,7 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
struct sigaction sa;
|
||||
sigaction(SIGBUS, 0, &sa);
|
||||
sigaction(SIGTRAP, &sa, 0);
|
||||
copyin(IDT+16*179+5, "\x89", 1);
|
||||
asm volatile("ud2");
|
||||
return 0;
|
||||
}
|
||||
@@ -19,9 +19,12 @@
|
||||
%define iret_rsp (iret_rip+24)
|
||||
%define iret_ss (iret_rip+32)
|
||||
|
||||
%define td_proc 8
|
||||
%define td_pcb 0x3f8
|
||||
%define td_retval 0x408
|
||||
|
||||
%define p_pid 0xbc
|
||||
|
||||
%define pcb_gsbase 0x48
|
||||
%define pcb_flags 0x100
|
||||
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
#include <errno.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <string.h>
|
||||
#include "kekcall.h"
|
||||
#include "traps.h"
|
||||
#include "utils.h"
|
||||
|
||||
extern char syscall_after[];
|
||||
extern char doreti_iret[];
|
||||
extern char nop_ret[];
|
||||
extern char copyout[];
|
||||
extern char copyin[];
|
||||
extern struct sysent sysents[];
|
||||
|
||||
int handle_kekcall(uint64_t* regs, uint64_t* args, uint32_t nr)
|
||||
{
|
||||
if(nr == 1)
|
||||
{
|
||||
uint64_t stack_frame[13] = {
|
||||
uint64_t stack_frame[12] = {
|
||||
(uint64_t)doreti_iret,
|
||||
(uint64_t)syscall_after, regs[CS], regs[EFLAGS], regs[RSP], regs[SS],
|
||||
(uint64_t)nop_ret, regs[CS], regs[EFLAGS], regs[RSP], regs[SS],
|
||||
};
|
||||
read_dbgregs(stack_frame+6);
|
||||
if(!get_pcb_dbregs())
|
||||
@@ -28,24 +32,33 @@ int handle_kekcall(uint64_t* regs, uint64_t* args, uint32_t nr)
|
||||
regs[RSI] = args[RDI];
|
||||
regs[RDX] = 48;
|
||||
regs[RIP] = (uint64_t)copyout;
|
||||
return ENOSYS;
|
||||
}
|
||||
else if(nr == 2)
|
||||
{
|
||||
uint64_t stack_frame[13] = {(uint64_t)doreti_iret, MKTRAP(TRAP_KEKCALL, 1), [12] = regs[RDI]};
|
||||
uint64_t stack_frame[14] = {(uint64_t)doreti_iret, MKTRAP(TRAP_KEKCALL, 1), [12] = regs[RDI]};
|
||||
push_stack(regs, stack_frame, sizeof(stack_frame));
|
||||
regs[RDI] = args[RDI];
|
||||
regs[RSI] = regs[RSP] + 48;
|
||||
regs[RDX] = 48;
|
||||
regs[RIP] = (uint64_t)copyin;
|
||||
return ENOSYS;
|
||||
}
|
||||
else if(nr == 3)
|
||||
{
|
||||
return rdmsr(args[RDI], &args[RAX]) ? 0 : EFAULT;
|
||||
}
|
||||
else if(nr == 0x42)
|
||||
regs[CS] |= 1;
|
||||
//nr 4 reserved for wrmsr
|
||||
else if(nr == 5)
|
||||
{
|
||||
uint64_t stack_frame[16] = {(uint64_t)doreti_iret, MKTRAP(TRAP_KEKCALL, 2)};
|
||||
stack_frame[6] = args[RDI];
|
||||
stack_frame[7] = args[RSI];
|
||||
stack_frame[14] = regs[RDI];
|
||||
push_stack(regs, stack_frame, sizeof(stack_frame));
|
||||
regs[RDI] = args[RDX];
|
||||
regs[RSI] = regs[RSP] + 64;
|
||||
regs[RDX] = 48;
|
||||
regs[RIP] = (uint64_t)copyin;
|
||||
}
|
||||
else if(nr == 0xffffffff)
|
||||
{
|
||||
args[RAX] = 0;
|
||||
@@ -58,13 +71,52 @@ void handle_kekcall_trap(uint64_t* regs, uint32_t trap)
|
||||
{
|
||||
if(trap == 1)
|
||||
{
|
||||
uint64_t stack_frame[12];
|
||||
uint64_t stack_frame[14];
|
||||
pop_stack(regs, stack_frame, sizeof(stack_frame));
|
||||
regs[RIP] = (uint64_t)syscall_after;
|
||||
regs[RIP] = stack_frame[13];
|
||||
if((uint32_t)regs[RAX])
|
||||
return;
|
||||
kpoke64(stack_frame[11]+td_retval, 0);
|
||||
set_pcb_dbregs();
|
||||
write_dbgregs(stack_frame+5);
|
||||
}
|
||||
else if(trap == 2)
|
||||
{
|
||||
uint64_t stack_frame[15];
|
||||
pop_stack(regs, stack_frame, sizeof(stack_frame));
|
||||
if((uint32_t)regs[RAX])
|
||||
{
|
||||
pop_stack(regs, regs+RIP, 8);
|
||||
return;
|
||||
}
|
||||
uint32_t pid = stack_frame[5];
|
||||
uint32_t sysc_no = stack_frame[6];
|
||||
int64_t proc = kpeek64(stack_frame[13]+td_proc);
|
||||
while(proc < -0x100000000)
|
||||
proc = kpeek64(proc+8);
|
||||
while(proc && (uint32_t)kpeek64(proc+p_pid) != pid)
|
||||
proc = kpeek64(proc);
|
||||
if(!proc)
|
||||
{
|
||||
regs[RAX] = ESRCH;
|
||||
pop_stack(regs, regs+RIP, 8);
|
||||
return;
|
||||
}
|
||||
regs[RDI] = kpeek64(proc+16);
|
||||
uint64_t stack_frame_2[14] = {(uint64_t)doreti_iret, MKTRAP(TRAP_KEKCALL, 3), [6] = stack_frame[13], regs[RDI]};
|
||||
memcpy(stack_frame_2+8, stack_frame+7, 48);
|
||||
push_stack(regs, stack_frame_2, sizeof(stack_frame_2));
|
||||
regs[RAX] = (uint64_t)&sysents[sysc_no];
|
||||
regs[RIP] = kpeek64((uint64_t)&sysents[sysc_no].sy_call);
|
||||
regs[RSI] = regs[RSP] + 64;
|
||||
handle_syscall(regs, 0);
|
||||
}
|
||||
else if(trap == 3)
|
||||
{
|
||||
uint64_t stack_frame[14];
|
||||
pop_stack(regs, stack_frame, sizeof(stack_frame));
|
||||
if(!(uint32_t)regs[RAX])
|
||||
kpoke64(stack_frame[5]+td_retval, kpeek64(stack_frame[6]+td_retval));
|
||||
regs[RIP] = stack_frame[13];
|
||||
}
|
||||
}
|
||||
+45
-31
@@ -11,6 +11,7 @@
|
||||
#include "traps.h"
|
||||
#include "kekcall.h"
|
||||
#include "fself.h"
|
||||
#include "syscall_fixes.h"
|
||||
|
||||
int have_error_code;
|
||||
|
||||
@@ -25,6 +26,44 @@ extern char int1_handler[];
|
||||
extern char int13_handler[];
|
||||
extern uint64_t wrmsr_args;
|
||||
|
||||
void handle_syscall(uint64_t* regs, int allow_kekcall)
|
||||
{
|
||||
#define IS_PPR(which) (regs[RAX] == (uint64_t)&sysents[SYS_##which])
|
||||
#ifdef FREEBSD
|
||||
#define IS_PS4(which) 0
|
||||
#else
|
||||
#define IS_PS4(which) (regs[RAX] == (uint64_t)&sysents2[SYS_##which])
|
||||
#endif
|
||||
#define IS(which) (IS_PPR(which) || IS_PS4(which))
|
||||
if(IS_PPR(getppid) && allow_kekcall)
|
||||
{
|
||||
uint64_t args[NREGS] = {0};
|
||||
copy_from_kernel(args, regs[RSP]+syscall_rsp_to_regs_stash+8, sizeof(args));
|
||||
int err = handle_kekcall(regs, args, args[RAX]>>32);
|
||||
if(err != ENOSYS)
|
||||
{
|
||||
if(!err)
|
||||
kpoke64(regs[RDI]+td_retval, args[RAX]);
|
||||
regs[RAX] = err;
|
||||
pop_stack(regs, regs+RIP, 8);
|
||||
}
|
||||
}
|
||||
#ifndef FREEBSD
|
||||
else if(IS(execve)
|
||||
|| IS(dynlib_load_prx)
|
||||
|| IS(get_self_auth_info)
|
||||
|| IS(get_sdk_compiled_version)
|
||||
|| IS_PPR(get_ppr_sdk_compiled_version))
|
||||
handle_fself_syscall(regs);
|
||||
else if(IS(mprotect)
|
||||
|| IS_PPR(mdbg_call))
|
||||
handle_syscall_fix(regs);
|
||||
#endif
|
||||
#undef IS
|
||||
#undef IS_PS4
|
||||
#undef IS_PPR
|
||||
}
|
||||
|
||||
void handle(uint64_t* regs)
|
||||
{
|
||||
if(!(regs[CS] & 3))
|
||||
@@ -76,37 +115,10 @@ from_userspace:
|
||||
else if(regs[RIP] == (uint64_t)syscall_before)
|
||||
{
|
||||
regs[RAX] |= 0xffffull << 48;
|
||||
#define IS_PPR(which) (regs[RAX] == (uint64_t)&sysents[SYS_##which])
|
||||
#ifdef FREEBSD
|
||||
#define IS_PS4(which) 0
|
||||
#else
|
||||
#define IS_PS4(which) (regs[RAX] == (uint64_t)&sysents2[SYS_##which])
|
||||
#endif
|
||||
#define IS(which) (IS_PPR(which) || IS_PS4(which))
|
||||
if(IS_PPR(getppid))
|
||||
{
|
||||
uint64_t args[NREGS] = {0};
|
||||
copy_from_kernel(args, regs[RSP]+syscall_rsp_to_regs_stash, sizeof(args));
|
||||
int err = handle_kekcall(regs, args, args[RAX]>>32);
|
||||
if(err != ENOSYS)
|
||||
{
|
||||
if(!err)
|
||||
kpoke64(regs[RDI]+td_retval, args[RAX]);
|
||||
regs[RAX] = err;
|
||||
regs[RIP] = (uint64_t)syscall_after;
|
||||
}
|
||||
}
|
||||
#ifndef FREEBSD
|
||||
else if(IS(execve)
|
||||
|| IS(dynlib_load_prx)
|
||||
|| IS(get_self_auth_info)
|
||||
|| IS(get_sdk_compiled_version)
|
||||
|| IS_PPR(get_ppr_sdk_compiled_version))
|
||||
handle_fself_syscall(regs);
|
||||
#endif
|
||||
#undef IS
|
||||
#undef IS_PS4
|
||||
#undef IS_PPR
|
||||
regs[RSI] = regs[RSP] + syscall_rsp_to_rsi;
|
||||
push_stack(regs, (const uint64_t[1]){(uint64_t)syscall_after}, 8);
|
||||
regs[RIP] = kpeek64(regs[RAX]+8);
|
||||
handle_syscall(regs, 1);
|
||||
}
|
||||
else if(regs[RIP] == (uint64_t)doreti_iret)
|
||||
{
|
||||
@@ -134,6 +146,8 @@ from_userspace:
|
||||
return;
|
||||
else if(handle_fself_parasites(regs))
|
||||
return;
|
||||
else if(try_handle_syscall_fix_trap(regs))
|
||||
return;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
|
||||
@@ -151,8 +151,7 @@ int wrmsr(uint32_t which, uint64_t value)
|
||||
|
||||
void start_syscall_with_dbgregs(uint64_t* regs, const uint64_t* dbgregs)
|
||||
{
|
||||
regs[RSI] = regs[RSP] + syscall_rsp_to_rsi;
|
||||
uint64_t stack_frame[13] = {
|
||||
uint64_t stack_frame[12] = {
|
||||
(uint64_t)doreti_iret,
|
||||
MKTRAP(TRAP_UTILS, 1), 0, 0, 0, 0,
|
||||
};
|
||||
@@ -160,7 +159,6 @@ void start_syscall_with_dbgregs(uint64_t* regs, const uint64_t* dbgregs)
|
||||
push_stack(regs, stack_frame, sizeof(stack_frame));
|
||||
set_pcb_dbregs();
|
||||
write_dbgregs(dbgregs);
|
||||
regs[RIP] = kpeek64(regs[RAX] + 8);
|
||||
}
|
||||
|
||||
void handle_utils_trap(uint64_t* regs, uint32_t trapno)
|
||||
@@ -170,6 +168,6 @@ void handle_utils_trap(uint64_t* regs, uint32_t trapno)
|
||||
uint64_t stack_frame[12];
|
||||
pop_stack(regs, stack_frame, sizeof(stack_frame));
|
||||
write_dbgregs(stack_frame+5);
|
||||
regs[RIP] = (uint64_t)syscall_after;
|
||||
regs[RIP] = stack_frame[11];
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ void read_dbgregs(uint64_t* dr);
|
||||
void write_dbgregs(const uint64_t* dr);
|
||||
void start_syscall_with_dbgregs(uint64_t* regs, const uint64_t* dbgregs);
|
||||
void handle_utils_trap(uint64_t* regs, uint32_t trapno);
|
||||
void handle_syscall(uint64_t* regs, int allow_kekcall);
|
||||
int rdmsr(uint32_t which, uint64_t* ans);
|
||||
int wrmsr(uint32_t which, uint64_t value);
|
||||
|
||||
|
||||
Reference in new issue
Block a user