mirror of
https://github.com/EchoStretch/kstuff-lite.git
synced 2026-10-19 02:09:50 -05:00
ps5-kstuff: add nmount & sceSblServiceCrypt hooks
This can be used to decrypt the inner PFS using custom-derived keys. Key derivation using the "ypkg" key is also implemented. External libraries used: BearSSL for RSA & SHA256HMAC, libtomcrypt for AES/XTS.
This commit is contained in:
1 parent
74f7752b61
commit
04fa6028eb
21 files changed
+813
-18
No files matched your search
@@ -16,3 +16,9 @@
|
||||
[submodule "linux/ps4-kexec-900"]
|
||||
path = linux/ps4-kexec-900
|
||||
url = https://github.com/sleirsgoevy/ps4-kexec
|
||||
[submodule "ps5-kstuff/BearSSL"]
|
||||
path = ps5-kstuff/BearSSL
|
||||
url = https://www.bearssl.org/git/BearSSL
|
||||
[submodule "ps5-kstuff/libtomcrypt"]
|
||||
path = ps5-kstuff/libtomcrypt
|
||||
url = https://github.com/libtom/libtomcrypt
|
||||
Submodule
+1
Submodule ps5-kstuff/BearSSL added at 79c060eea3.
+8
-2
@@ -32,5 +32,11 @@ structs.h: structs.inc
|
||||
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 -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
|
||||
uelf/uelf: uelf/*.c uelf/*.h structs.h uelf/crt.o BearSSL/build/libbearssl.a libtomcrypt/libtomcrypt.a
|
||||
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 -fvisibility=hidden -ffreestanding uelf/crt.o uelf/*.c -L BearSSL/build -lbearssl -L libtomcrypt -ltomcrypt -o uelf/uelf
|
||||
|
||||
BearSSL/build/libbearssl.a: build_bearssl.sh overrides.h
|
||||
bash build_bearssl.sh
|
||||
|
||||
libtomcrypt/libtomcrypt.a: build_libtomcrypt.sh overrides.h
|
||||
bash build_libtomcrypt.sh
|
||||
@@ -0,0 +1,2 @@
|
||||
cd BearSSL
|
||||
for i in clean "lib -j$(nproc)"; do make CC='gcc -nostdlib -nostdinc -isystem /proc/'$$'/cwd/../../freebsd-headers -isystem /nix/store/b7hvml0m3qmqraz1022fwvyyg6fc1vdy-gcc-12.2.0/lib/gcc/x86_64-unknown-linux-gnu/12.2.0/include -O0 -g -ffreestanding -mgeneral-regs-only -ffunction-sections -fdata-sections -fvisibility=hidden -include /proc/'$$'/cwd/../overrides.h' $i; done
|
||||
@@ -0,0 +1,2 @@
|
||||
cd libtomcrypt
|
||||
for i in clean -j$(nproc); do make CC='gcc -nostdlib -nostdinc -isystem /proc/'$$'/cwd/../../freebsd-headers -isystem /nix/store/b7hvml0m3qmqraz1022fwvyyg6fc1vdy-gcc-12.2.0/lib/gcc/x86_64-unknown-linux-gnu/12.2.0/include -O0 -g -ffreestanding -mgeneral-regs-only -ffunction-sections -fdata-sections -fPIE -fPIC -fvisibility=hidden -include /proc/'$$'/cwd/../overrides.h' $i; done
|
||||
Submodule
+1
Submodule ps5-kstuff/libtomcrypt added at b96e96cf8b.
+351
-9
@@ -202,11 +202,14 @@ extern char uek_end[];
|
||||
|
||||
asm(".section .text\nkekcall:\nmov 8(%rsp), %rax\njmp *p_kekcall(%rip)");
|
||||
|
||||
int kekcall(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t nr);
|
||||
uint64_t kekcall(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f, uint64_t nr);
|
||||
|
||||
#define KEKCALL_GETPPID 0x000000027
|
||||
#define KEKCALL_READ_DR 0x100000027
|
||||
#define KEKCALL_WRITE_DR 0x200000027
|
||||
#define KEKCALL_GETPPID 0x000000027
|
||||
#define KEKCALL_READ_DR 0x100000027
|
||||
#define KEKCALL_WRITE_DR 0x200000027
|
||||
#define KEKCALL_RDMSR 0x300000027
|
||||
#define KEKCALL_REMOTE_SYSCALL 0x500000027
|
||||
#define KEKCALL_CHECK 0xffffffff00000027
|
||||
|
||||
void* p_kekcall;
|
||||
void* dlsym(void*, const char*);
|
||||
@@ -276,7 +279,6 @@ void build_uelf_cr3(uint64_t uelf_cr3, void* uelf_base[2])
|
||||
int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
{
|
||||
r0gdb_init(ds, a, b, c, d);
|
||||
dbg_enter();
|
||||
uint64_t percpu_ist4[NCPUS];
|
||||
for(int cpu = 0; cpu < NCPUS; cpu++)
|
||||
copyout(&percpu_ist4[cpu], TSS(cpu)+28+4*8, 8);
|
||||
@@ -286,6 +288,7 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
uint64_t int13_handler;
|
||||
copyout(&int13_handler, IDT+16*13, 2);
|
||||
copyout((char*)&int13_handler + 2, IDT+16*13+6, 6);
|
||||
dbg_enter();
|
||||
gdb_remote_syscall("write", 3, 0, (uintptr_t)1, (uintptr_t)"allocating kernel memory... ", (uintptr_t)28);
|
||||
for(int i = 0; i < 0x300; i += 2)
|
||||
r0gdb_kmalloc(0x100);
|
||||
@@ -296,11 +299,16 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
mem_blocks[i+1] = (mem_blocks[i] ? mem_blocks[i] + (1<<23) : 0);
|
||||
}
|
||||
gdb_remote_syscall("write", 3, 0, (uintptr_t)1, (uintptr_t)"done\n", (uintptr_t)5);
|
||||
uint64_t shared_area = (uint64_t)kmalloc(8192);
|
||||
shared_area = ((shared_area - 1) | 4095) + 1;
|
||||
kmemzero((void*)shared_area, 4096);
|
||||
shared_area = virt2phys(shared_area) + (1ull << 39);
|
||||
volatile int zero = 0; //hack to force runtime calculation of string pointers
|
||||
const char* symbols[] = {
|
||||
"add_rsp_iret"+zero,
|
||||
"copyin"+zero,
|
||||
"copyout"+zero,
|
||||
"crypt_message_resolve"+zero,
|
||||
"decryptSelfBlock_epilogue"+zero,
|
||||
"decryptSelfBlock_watchpoint"+zero,
|
||||
"decryptSelfBlock_watchpoint_lr"+zero,
|
||||
@@ -336,11 +344,13 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
"rdmsr_end"+zero,
|
||||
"rdmsr_start"+zero,
|
||||
"rep_movsb_pop_rbp_ret"+zero,
|
||||
"sceSblServiceCryptAsync_deref_singleton"+zero,
|
||||
"sceSblServiceIsLoadable2"+zero,
|
||||
"sceSblServiceMailbox"+zero,
|
||||
"sceSblServiceMailbox_lr_decryptSelfBlock"+zero,
|
||||
"sceSblServiceMailbox_lr_loadSelfSegment"+zero,
|
||||
"sceSblServiceMailbox_lr_verifyHeader"+zero,
|
||||
"shared_area"+zero,
|
||||
"soo_ioctl"+zero,
|
||||
"syscall_after"+zero,
|
||||
"syscall_before"+zero,
|
||||
@@ -357,6 +367,7 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
kdata_base - 0x9cf853, // add_rsp_iret
|
||||
kdata_base - 0x9908e0, // copyin
|
||||
kdata_base - 0x990990, // copyout
|
||||
kdata_base - 0x479d60, // crypt_message_resolve
|
||||
kdata_base - 0x8a52c3, // decryptSelfBlock_epilogue
|
||||
kdata_base - 0x2cc88e, // decryptSelfBlock_watchpoint
|
||||
kdata_base - 0x8a538a, // decryptSelfBlock_watchpoint_lr
|
||||
@@ -392,11 +403,13 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
kdata_base - 0x9d6cf9, // rdmsr_end
|
||||
kdata_base - 0x9d6d02, // rdmsr_start
|
||||
kdata_base - 0x990a55, // rep_movsb_pop_rbp_ret
|
||||
kdata_base - 0x8ed902, // sceSblServiceCryptAsync_deref_singleton
|
||||
kdata_base - 0x8a5c40, // sceSblServiceIsLoadable2
|
||||
kdata_base - 0x6824c0, // sceSblServiceMailbox
|
||||
kdata_base - 0x8a5014, // sceSblServiceMailbox_lr_decryptSelfBlock
|
||||
kdata_base - 0x8a5541, // sceSblServiceMailbox_lr_loadSelfSegment
|
||||
kdata_base - 0x8a58bc, // sceSblServiceMailbox_lr_verifyHeader
|
||||
shared_area, // shared_area
|
||||
kdata_base - 0x96eb98, // soo_ioctl
|
||||
kdata_base - 0x8022ee, // syscall_after
|
||||
kdata_base - 0x802311, // syscall_before
|
||||
@@ -424,6 +437,7 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
uint64_t uelf_bases[NCPUS];
|
||||
uint64_t kelf_bases[NCPUS];
|
||||
uint64_t kelf_entries[NCPUS];
|
||||
uint64_t uelf_cr3s[NCPUS];
|
||||
for(int cpu = 0; cpu < NCPUS; cpu++)
|
||||
{
|
||||
char buf[] = "loading on cpu ..\n";
|
||||
@@ -451,6 +465,7 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
char* uelf = load_kelf(uek, symbols, values, uelf_base, &uelf_entry, 0x400000);
|
||||
uintptr_t uelf_cr3 = (uintptr_t)kmalloc(24576);
|
||||
uelf_cr3 = ((uelf_cr3 + 4095) | 4095) - 4095;
|
||||
uelf_cr3s[cpu] = uelf_cr3;
|
||||
values[uelf_cr3_idx] = virt2phys(uelf_cr3);
|
||||
values[uelf_entry_idx] = (uintptr_t)uelf_entry - (uintptr_t)uelf_base[0] + 0x400000;
|
||||
void* entry = 0;
|
||||
@@ -480,16 +495,343 @@ int main(void* ds, int a, int b, uintptr_t c, uintptr_t d)
|
||||
kmemcpy((char*)(IDT+16*2), (char*)&iret, 2);
|
||||
kmemcpy((char*)(IDT+16*2+6), (char*)&iret+2, 6);
|
||||
//kmemzero((char*)(IDT+16*1), 16);
|
||||
gdb_remote_syscall("write", 3, 0, (uintptr_t)1, (uintptr_t)"done\npatching sysentvec... ", (uintptr_t)27);
|
||||
copyin(kdata_base + 0xd11bb8 + 14, &(const uint16_t[1]){0xdeb7}, 2);
|
||||
copyin(kdata_base + 0xd11d30 + 14, &(const uint16_t[1]){0xdeb7}, 2);
|
||||
gdb_remote_syscall("write", 3, 0, (uintptr_t)1, (uintptr_t)"done\napplying kdata patches... ", (uintptr_t)31);
|
||||
copyin(kdata_base + 0xd11bb8 + 14, &(const uint16_t[1]){0xdeb7}, 2); //native sysentvec
|
||||
copyin(kdata_base + 0xd11d30 + 14, &(const uint16_t[1]){0xdeb7}, 2); //ps4 sysentvec
|
||||
copyin(kdata_base + 0x2e31830 + 11*8 + 2*8 + 6, &(const uint16_t[1]){0xdeb7}, 2); //crypt xts
|
||||
copyin(kdata_base + 0x2e31830 + 11*8 + 9*8 + 6, &(const uint16_t[1]){0xdeb7}, 2); //crypt xts
|
||||
gdb_remote_syscall("write", 3, 0, (uintptr_t)1, (uintptr_t)"done\n", (uintptr_t)5);
|
||||
p_kekcall = (char*)dlsym((void*)0x2001, "getpid") + 7;
|
||||
//restore the gdb_stub's SIGTRAP handler
|
||||
struct sigaction sa;
|
||||
sigaction(SIGBUS, 0, &sa);
|
||||
sigaction(SIGTRAP, &sa, 0);
|
||||
copyin(IDT+16*179+5, "\x89", 1);
|
||||
sigaction(SIGPIPE, &sa, 0);
|
||||
copyin(IDT+16*9+5, "\x8e", 1);
|
||||
copyin(IDT+16*179+5, "\x8e", 1);
|
||||
asm volatile("ud2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
TEMPORARY CODE
|
||||
|
||||
This should either go to some separate place ("utils.c" in r0gdb perhaps), or be removed completely.
|
||||
*/
|
||||
|
||||
#define sysctl __sysctl
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/thr.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define SYS_mdbg_call 573
|
||||
#define SYS_dynlib_dlsym 591
|
||||
#define SYS_dynlib_get_info_ex 608
|
||||
|
||||
void inject_payload(int pid)
|
||||
{
|
||||
if(kekcall(0, 0, 0, 0, 0, 0, KEKCALL_CHECK))
|
||||
return;
|
||||
static int sock = -1;
|
||||
if(sock < 0)
|
||||
{
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
struct sockaddr_in sin = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr = {.s_addr = 0},
|
||||
.sin_port = __builtin_bswap16(9020),
|
||||
};
|
||||
bind(sock, (void*)&sin, sizeof(sin));
|
||||
listen(sock, 1);
|
||||
}
|
||||
int sock2 = accept(sock, 0, 0);
|
||||
char* buf = mmap(0, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
|
||||
size_t sz = 0;
|
||||
size_t cap = 16384;
|
||||
for(;;)
|
||||
{
|
||||
if(sz == cap)
|
||||
{
|
||||
cap *= 2;
|
||||
char* buf2 = mmap(0, cap, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
|
||||
for(size_t i = 0; i < sz; i++)
|
||||
buf2[i] = buf[i];
|
||||
munmap(buf, sz);
|
||||
buf = buf2;
|
||||
}
|
||||
ssize_t chk = read(sock2, buf+sz, cap-sz);
|
||||
if(chk <= 0)
|
||||
break;
|
||||
sz += chk;
|
||||
}
|
||||
static const char shellcode[] = {
|
||||
0x55, //push rbp
|
||||
0x48, 0x8b, 0xfc, //mov rdi, rsp
|
||||
0x31, 0xf6, //xor esi, esi
|
||||
0x48, 0xba, 0, 0, 0, 0, 0, 0, 0, 0, //movabs rdx, ...
|
||||
0x48, 0xb9, 0, 0, 0, 0, 0, 0, 0, 0, //movabs rcx, ...
|
||||
0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, //movabs rax, ...
|
||||
0xff, 0xd0, //call rax
|
||||
0x31, 0xff, //xor edi, edi
|
||||
0xb8, SYS_thr_exit&255, SYS_thr_exit>>8, 0, 0,
|
||||
0xff, 0x25, 0, 0, 0, 0, //jmp qword [rip]
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
if(cap - sz < sizeof(shellcode))
|
||||
{
|
||||
cap *= 2;
|
||||
char* buf2 = mmap(0, cap, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
|
||||
for(size_t i = 0; i < sz; i++)
|
||||
buf2[i] = buf[i];
|
||||
munmap(buf, sz);
|
||||
buf = buf2;
|
||||
}
|
||||
size_t shellcode_offset = sz;
|
||||
for(size_t i = 0; i < sizeof(shellcode); i++)
|
||||
buf[sz++] = shellcode[i];
|
||||
uint64_t target_pointer = kekcall(pid, SYS_mmap, (uint64_t)(const uint64_t[6]){0, sz, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0}, 0, 0, 0, KEKCALL_REMOTE_SYSCALL);
|
||||
if(target_pointer + 1 <= 4096)
|
||||
asm volatile("ud2");
|
||||
uint64_t target_stack = kekcall(pid, SYS_mmap, (uint64_t)(const uint64_t[6]){0, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0}, 0, 0, 0, KEKCALL_REMOTE_SYSCALL);
|
||||
if(target_stack + 1 <= 4096)
|
||||
asm volatile("ud2");
|
||||
if(kekcall(pid, SYS_mprotect, (uint64_t)(const uint64_t[6]){target_pointer, sz, PROT_READ|PROT_WRITE|PROT_EXEC}, 0, 0, 0, KEKCALL_REMOTE_SYSCALL))
|
||||
asm volatile("ud2");
|
||||
*(uint64_t*)(buf+shellcode_offset+8) = target_pointer;
|
||||
kekcall(pid, SYS_dynlib_dlsym, (uint64_t)(const uint64_t[6]){0x2001, (uint64_t)"sceKernelDlsym", (uint64_t)(buf+shellcode_offset+18)}, 0, 0, 0, KEKCALL_REMOTE_SYSCALL);
|
||||
if(!*(uint64_t*)(buf+shellcode_offset+18))
|
||||
asm volatile("ud2");
|
||||
kekcall(pid, SYS_dynlib_dlsym, (uint64_t)(const uint64_t[6]){0x2001, (uint64_t)"pthread_create", (uint64_t)(buf+shellcode_offset+28)}, 0, 0, 0, KEKCALL_REMOTE_SYSCALL);
|
||||
if(!*(uint64_t*)(buf+shellcode_offset+28))
|
||||
asm volatile("ud2");
|
||||
kekcall(pid, SYS_dynlib_dlsym, (uint64_t)(const uint64_t[6]){0x2001, (uint64_t)"getpid", (uint64_t)(buf+shellcode_offset+51)}, 0, 0, 0, KEKCALL_REMOTE_SYSCALL);
|
||||
if(!*(uint64_t*)(buf+shellcode_offset+51))
|
||||
asm volatile("ud2");
|
||||
*(uint64_t*)(buf+shellcode_offset+51) += 7;
|
||||
{
|
||||
uint64_t arg1[4] = {1, 0x13};
|
||||
uint64_t arg2[8] = {pid, target_pointer, (uint64_t)buf, sz};
|
||||
uint64_t arg3[4] = {0};
|
||||
if(kekcall((uint64_t)arg1, (uint64_t)arg2, (uint64_t)arg3, 0, 0, 0, SYS_mdbg_call))
|
||||
asm volatile("ud2");
|
||||
}
|
||||
{
|
||||
uint64_t arg1[4] = {1, 0x13};
|
||||
uint64_t arg2[8] = {pid, target_stack+16, (uint64_t)&target_stack, 8};
|
||||
uint64_t arg3[4] = {0};
|
||||
if(kekcall((uint64_t)arg1, (uint64_t)arg2, (uint64_t)arg3, 0, 0, 0, SYS_mdbg_call))
|
||||
asm volatile("ud2");
|
||||
}
|
||||
{
|
||||
uint64_t arg1[4] = {1, 0x13};
|
||||
uint64_t arg2[8] = {pid, target_stack+0x1a8, (uint64_t)&target_stack, 8};
|
||||
uint64_t arg3[4] = {0};
|
||||
if(kekcall((uint64_t)arg1, (uint64_t)arg2, (uint64_t)arg3, 0, 0, 0, SYS_mdbg_call))
|
||||
asm volatile("ud2");
|
||||
}
|
||||
munmap(buf, sz);
|
||||
{
|
||||
struct thr_param param = {0};
|
||||
long x, y;
|
||||
param.start_func = (void*)(target_pointer+shellcode_offset);
|
||||
param.stack_base = (void*)target_stack;
|
||||
param.stack_size = 65536;
|
||||
param.tls_size = 1;
|
||||
param.arg = 0;
|
||||
if(kekcall(pid, SYS_sysarch, (uint64_t)(const uint64_t[6]){AMD64_GET_FSBASE, (uint64_t)¶m.tls_base}, 0, 0, 0, KEKCALL_REMOTE_SYSCALL))
|
||||
asm volatile("ud2");
|
||||
if(kekcall(pid, SYS_thr_new, (uint64_t)(const uint64_t[6]){(uint64_t)¶m, sizeof(param)}, 0, 0, 0, KEKCALL_REMOTE_SYSCALL))
|
||||
asm volatile("ud2");
|
||||
}
|
||||
}
|
||||
|
||||
void* klog_server(void* arg)
|
||||
{
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
struct sockaddr_in sin = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr = { .s_addr = 0 },
|
||||
.sin_port = 0x0e27, //9998
|
||||
};
|
||||
bind(sock, (void*)&sin, sizeof(sin));
|
||||
listen(sock, 1);
|
||||
new_conn:
|
||||
int sock2 = accept(sock, NULL, NULL);
|
||||
char buf[512];
|
||||
int fd1 = open("/dev/klog", O_RDONLY);
|
||||
for(;;)
|
||||
{
|
||||
ssize_t chk = read(fd1, buf, sizeof(buf));
|
||||
if(chk < 0)
|
||||
break;
|
||||
char* p = buf;
|
||||
while(chk > 0)
|
||||
{
|
||||
ssize_t chk1 = write(sock2, p, chk);
|
||||
if(chk1 <= 0)
|
||||
{
|
||||
close(sock2);
|
||||
goto new_conn;
|
||||
}
|
||||
chk -= chk1;
|
||||
p += chk1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int find_proc(const char* name)
|
||||
{
|
||||
char buf[1097] = {0};
|
||||
for(int pid = 1; pid < 1024; pid++)
|
||||
{
|
||||
size_t sz = 1096;
|
||||
int key[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
|
||||
sysctl(key, 4, buf, &sz, 0, 0);
|
||||
const char* a = buf + 447;
|
||||
const char* b = name;
|
||||
while(*a && *a++ == *b++);
|
||||
if(!*a && !*b)
|
||||
return pid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int64_t do_remote_syscall(int pid, int sysc, ...)
|
||||
{
|
||||
static uint64_t args_p = 0;
|
||||
if(!args_p)
|
||||
args_p = r0gdb_kmalloc(48);
|
||||
uint64_t args[6];
|
||||
va_list l;
|
||||
va_start(l, sysc);
|
||||
for(int i = 0; i < 6; i++)
|
||||
args[i] = va_arg(l, uint64_t);
|
||||
va_end(l);
|
||||
uint64_t proc;
|
||||
uint64_t target = 0;
|
||||
copyout(&proc, kdata_base+0x27edcb8, 8);
|
||||
while(proc)
|
||||
{
|
||||
uint32_t pid1;
|
||||
copyout(&pid1, proc+0xbc, 4);
|
||||
if(pid1 == pid)
|
||||
{
|
||||
target = proc;
|
||||
break;
|
||||
}
|
||||
copyout(&proc, proc, 8);
|
||||
}
|
||||
if(!target)
|
||||
asm volatile("ud2");
|
||||
uint64_t target_thread;
|
||||
copyout(&target_thread, target+16, 8);
|
||||
copyin(args_p, args, 48);
|
||||
uint64_t syscall_fn;
|
||||
copyout(&syscall_fn, kdata_base+0x1709c0+48*sysc+8, 8);
|
||||
int err = r0gdb_kfncall(syscall_fn, target_thread, args_p);
|
||||
if(err)
|
||||
return -err;
|
||||
int64_t ans;
|
||||
copyout(&ans, target_thread+0x408, 8);
|
||||
return ans;
|
||||
}
|
||||
|
||||
struct module_segment
|
||||
{
|
||||
uint64_t addr;
|
||||
uint32_t size;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct module_info_ex
|
||||
{
|
||||
size_t st_size;
|
||||
char name[256];
|
||||
int id;
|
||||
uint32_t tls_index;
|
||||
uint64_t tls_init_addr;
|
||||
uint32_t tls_init_size;
|
||||
uint32_t tls_size;
|
||||
uint32_t tls_offset;
|
||||
uint32_t tls_align;
|
||||
uint64_t init_proc_addr;
|
||||
uint64_t fini_proc_addr;
|
||||
uint64_t reserved1;
|
||||
uint64_t reserved2;
|
||||
uint64_t eh_frame_hdr_addr;
|
||||
uint64_t eh_frame_addr;
|
||||
uint32_t eh_frame_hdr_size;
|
||||
uint32_t eh_frame_size;
|
||||
struct module_segment segments[4];
|
||||
uint32_t segment_count;
|
||||
uint32_t ref_count;
|
||||
};
|
||||
|
||||
static uint64_t shellcore_args_base;
|
||||
|
||||
static void temp_patch_shellcore(int do_lk)
|
||||
{
|
||||
int pid = find_proc("SceShellCore");
|
||||
struct module_info_ex mod_info;
|
||||
mod_info.st_size = sizeof(mod_info);
|
||||
do_remote_syscall(pid, SYS_dynlib_get_info_ex, 0, 0, &mod_info);
|
||||
uint64_t shellcore_base = mod_info.eh_frame_hdr_addr - 0x13c0000;
|
||||
mod_info.st_size = sizeof(mod_info);
|
||||
do_remote_syscall(pid, SYS_dynlib_get_info_ex, 0x2001, 0, &mod_info);
|
||||
uint64_t libkernel_base = mod_info.eh_frame_hdr_addr - 0x44000;
|
||||
shellcore_args_base = do_remote_syscall(pid, SYS_mmap, 0, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
|
||||
struct
|
||||
{
|
||||
uint64_t addr;
|
||||
void* data;
|
||||
size_t sz;
|
||||
} patches[] = {
|
||||
{shellcore_base+0x974fe0, "\x31\xc0\xc3", 3},
|
||||
{shellcore_base+0x974bb0, "\x31\xc0\xc3", 3},
|
||||
{shellcore_base+0x5307f9, "\xeb\x04", 2},
|
||||
{shellcore_base+0x26f35c, "\xeb\x04", 2},
|
||||
{shellcore_base+0x54e1f0, "\xeb", 1},
|
||||
{shellcore_base+0x536e1d, "\x90\xe9", 2},
|
||||
{libkernel_base+0x18f0, "\x48\xb8\xef\xbe\xad\xde\xef\xbe\xad\xde\x48\x89\x38\x48\x89\x70\x08\x48\x89\x50\x10\xeb\xfe", do_lk ? 23 : 0},
|
||||
{libkernel_base+0x18f2, &shellcore_args_base, do_lk ? 8 : 0},
|
||||
};
|
||||
for(int i = 0; i < sizeof(patches) / sizeof(*patches); i++)
|
||||
{
|
||||
uint64_t arg1[4] = {1, 0x13};
|
||||
uint64_t arg2[8] = {pid, patches[i].addr, (uint64_t)patches[i].data, patches[i].sz};
|
||||
uint64_t arg3[4] = {0};
|
||||
mdbg_call_20(arg1, arg2, arg3);
|
||||
}
|
||||
}
|
||||
|
||||
static void* get_nmount_args(void)
|
||||
{
|
||||
int pid = find_proc("SceShellCore");
|
||||
uint64_t args[3];
|
||||
#define READ(dst, src, sz) (mdbg_call_20((uint64_t[4]){1, 0x12}, (uint64_t[8]){pid, (src), (uint64_t)(dst), (sz)}, (uint64_t[4]){}))
|
||||
READ(args, shellcore_args_base, 24);
|
||||
uint64_t* ptrs = malloc(sizeof(*ptrs) * args[1] * 2);
|
||||
READ(ptrs, args[0], sizeof(*ptrs) * args[1] * 2);
|
||||
for(int i = 0; i < args[1]; i++)
|
||||
{
|
||||
uint64_t ptr = ptrs[2*i];
|
||||
uint64_t sz = ptrs[2*i+1];
|
||||
char* buf = malloc(sz+1);
|
||||
READ(buf, ptr, sz);
|
||||
buf[sz] = 0;
|
||||
ptrs[2*i] = (uint64_t)buf;
|
||||
}
|
||||
#undef READ
|
||||
return ptrs;
|
||||
}
|
||||
|
||||
int my_nmount(void* a, int b, int c)
|
||||
{
|
||||
return kekcall((uintptr_t)a, b, c, 0, 0, 0, SYS_nmount);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/* disable use of POSIX functions */
|
||||
#undef __linux__
|
||||
#undef __unix__
|
||||
|
||||
/* disable XMM intrinsics */
|
||||
#undef __x86_64__
|
||||
|
||||
/* for BearSSL */
|
||||
#define BR_64 1
|
||||
#define BR_INT128 1
|
||||
|
||||
/* for libtomcrypt */
|
||||
#define ARGTYPE 3
|
||||
#define TAB_SIZE 1
|
||||
#define LTC_NO_TEST 1
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
%define p_pid 0xbc
|
||||
|
||||
%define pcb_fsbase 0x40
|
||||
%define pcb_gsbase 0x48
|
||||
%define pcb_flags 0x100
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ use64
|
||||
|
||||
global yield
|
||||
global memcpy
|
||||
global memset
|
||||
global memmove
|
||||
global cr3_phys
|
||||
global trap_frame
|
||||
global wrmsr_args
|
||||
@@ -25,6 +27,32 @@ mov rcx, rdx
|
||||
rep movsb
|
||||
ret
|
||||
|
||||
memset:
|
||||
movzx eax, sil
|
||||
mov rsi, rdi
|
||||
mov rcx, rdx
|
||||
rep stosb
|
||||
mov rax, rsi
|
||||
ret
|
||||
|
||||
memmove:
|
||||
mov rax, rdi
|
||||
sub rax, rsi
|
||||
cmp rax, rdx
|
||||
jae memcpy
|
||||
test rax, rax
|
||||
je .mov_rax_rdi_ret
|
||||
lea rdi, [rdi+rdx-1]
|
||||
lea rsi, [rsi+rdx-1]
|
||||
mov rcx, rdx
|
||||
std
|
||||
rep movsb
|
||||
cld
|
||||
inc rdi
|
||||
.mov_rax_rdi_ret:
|
||||
mov rax, rdi
|
||||
ret
|
||||
|
||||
; rdi = trap_frame
|
||||
; rsi = cr3 of caller
|
||||
; rdx = our cr3 (currently unused)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "fakekeys.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
extern struct
|
||||
{
|
||||
uint64_t bitmask;
|
||||
char pad[24];
|
||||
char key_data[63][32];
|
||||
} shared_area;
|
||||
|
||||
int register_fake_key(const char key_data[32])
|
||||
{
|
||||
uint64_t mask, mask1;
|
||||
mask = __atomic_load_n(&shared_area.bitmask, __ATOMIC_ACQUIRE);
|
||||
do
|
||||
{
|
||||
mask1 = (mask | (mask + 1)) & ((1ull << 63) - 1);
|
||||
if(mask1 == mask)
|
||||
return -1;
|
||||
}
|
||||
while(!__atomic_compare_exchange_n(&shared_area.bitmask, &mask, mask1, 1, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE));
|
||||
int key_idx = 63 - __builtin_clzll(mask ^ mask1);
|
||||
memcpy(shared_area.key_data[key_idx], key_data, 32);
|
||||
return key_idx;
|
||||
}
|
||||
|
||||
void unregister_fake_key(int key_id)
|
||||
{
|
||||
uint64_t mask, mask1;
|
||||
mask = __atomic_load_n(&shared_area.bitmask, __ATOMIC_ACQUIRE);
|
||||
do
|
||||
mask1 = mask & ~(1ull << key_id);
|
||||
while(!__atomic_compare_exchange_n(&shared_area.bitmask, &mask, mask1, 1, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE));
|
||||
}
|
||||
|
||||
int get_fake_key(int key_id, char key_data[32])
|
||||
{
|
||||
uint64_t mask = __atomic_load_n(&shared_area.bitmask, __ATOMIC_ACQUIRE);
|
||||
if(!(mask & (1ull << key_id)))
|
||||
return 0;
|
||||
memcpy(key_data, shared_area.key_data[key_id], 32);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
int register_fake_key(const char key_data[32]);
|
||||
void unregister_fake_key(int key_id);
|
||||
int get_fake_key(int key_id, char key_data[32]);
|
||||
@@ -0,0 +1,188 @@
|
||||
#include <string.h>
|
||||
#include "fpkg.h"
|
||||
#include "utils.h"
|
||||
#include "traps.h"
|
||||
#include "log.h"
|
||||
#include "pfs_crypto.h"
|
||||
#include "fakekeys.h"
|
||||
|
||||
extern char sceSblServiceMailbox[];
|
||||
extern char sceSblServiceCryptAsync_deref_singleton[];
|
||||
extern char crypt_message_resolve[];
|
||||
extern char doreti_iret[];
|
||||
|
||||
extern char kdata_base[];
|
||||
|
||||
#define IDX_TO_HANDLE(x) (0x13374100 | ((uint8_t)((x)+1)))
|
||||
#define HANDLE_TO_IDX(x) ((((x) & 0xffffff00) == 0x13374100 ? ((int)(uint8_t)(x)) : (int)0) - 1)
|
||||
|
||||
static void crypto_request_emulated(uint64_t* regs, uint64_t msg, uint32_t status)
|
||||
{
|
||||
uint64_t frame[7] = {
|
||||
(uint64_t)doreti_iret,
|
||||
MKTRAP(TRAP_FPKG, 1), 0, 0, 0, 0,
|
||||
0
|
||||
};
|
||||
push_stack(regs, frame, sizeof(frame));
|
||||
regs[RIP] = (uint64_t)crypt_message_resolve;
|
||||
regs[RDI] = msg;
|
||||
regs[RSI] = status;
|
||||
}
|
||||
|
||||
static int handle_crypto_request(uint64_t* regs)
|
||||
{
|
||||
uint64_t dbgregs[6] = {0};
|
||||
read_dbgregs(dbgregs);
|
||||
//if(dbgregs[0] == 0x1337)
|
||||
{
|
||||
//uint64_t req = regs[R13];
|
||||
uint64_t msg = regs[R14];
|
||||
/*if(msg != kpeek64(req))
|
||||
{
|
||||
log_word(0xdead0008dead0008);
|
||||
log_word(req);
|
||||
log_word(msg);
|
||||
return 0;
|
||||
}*/
|
||||
uint64_t msg_data[32];
|
||||
copy_from_kernel(msg_data, msg, sizeof(msg_data));
|
||||
if((msg_data[0] & 0x7fffffff) == 0x9132000) // SHA256HMAC with key handle
|
||||
{
|
||||
int idx = HANDLE_TO_IDX(msg_data[20]);
|
||||
//log_word(0xfee10006dead0000|(uint16_t)idx);
|
||||
if(idx < 0)
|
||||
return 0;
|
||||
uint8_t key[32];
|
||||
if(!get_fake_key(idx, key))
|
||||
return 0;
|
||||
if(msg_data[3] != msg_data[1] * 8)
|
||||
return 0;
|
||||
//log_word(0xdead0006dead0007);
|
||||
uint8_t hash[32] = {0};
|
||||
if(pfs_hmac_virtual(hash, key, msg_data[2], msg_data[1]))
|
||||
{
|
||||
crypto_request_emulated(regs, msg, -1);
|
||||
return 1;
|
||||
}
|
||||
/*for(int i = 0; i < 4; i++)
|
||||
log_word(*(uint64_t*)(hash+8*i));*/
|
||||
copy_to_kernel(msg+32, hash, 32);
|
||||
crypto_request_emulated(regs, msg, 0);
|
||||
return 1;
|
||||
/*for(int i = 0; i < 16; i++)
|
||||
{
|
||||
uint8_t tmp = key[i];
|
||||
key[i] = key[31-i];
|
||||
key[31-i] = tmp;
|
||||
}
|
||||
kpoke64(msg, msg_data[0] & ~(1ull << 20));
|
||||
copy_to_kernel(msg+160, key, 32);
|
||||
for(int i = 32; i < 256; i += 8)
|
||||
kpoke64(msg+i, 0x100000001);*/
|
||||
}
|
||||
else if((msg_data[0] & 0x7ffff7ff) == 0x2108000) // AES-XTS decrypt/encrypt with key handle
|
||||
{
|
||||
int idx = HANDLE_TO_IDX(msg_data[5]);
|
||||
//log_word(0xfee10006dead0100|(uint16_t)idx);
|
||||
if(idx < 0)
|
||||
return 0;
|
||||
uint8_t key[32];
|
||||
if(!get_fake_key(idx, key))
|
||||
return 0;
|
||||
if(pfs_xts_virtual(msg_data[3], msg_data[2], key, msg_data[4], msg_data[1], (msg_data[0] & 0x800) >> 11))
|
||||
crypto_request_emulated(regs, msg, -1);
|
||||
else
|
||||
crypto_request_emulated(regs, msg, 0);
|
||||
return 1;
|
||||
/*kpoke64(msg, msg_data[0] & ~(1ull << 20));
|
||||
copy_to_kernel(msg+40, key, 32);*/
|
||||
}
|
||||
/*log_word(0xdead0006dead0006);
|
||||
log_word(msg);
|
||||
for(int i = 0; i < 32; i++)
|
||||
log_word(msg_data[i]);
|
||||
log_word(0xdead0006ffffffff);*/
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int try_handle_fpkg_trap(uint64_t* regs)
|
||||
{
|
||||
if(regs[RIP] == (uint64_t)kdata_base - 0x94a7f5)
|
||||
{
|
||||
uint64_t req[8];
|
||||
copy_from_kernel(req, regs[RDX], 64);
|
||||
uint64_t p_eekpfs = 0;
|
||||
memcpy(&p_eekpfs, DMEM+req[2]+32, 8);
|
||||
uint8_t eekpfs[256] = {0};
|
||||
memcpy(eekpfs, DMEM+p_eekpfs, 256);
|
||||
uint8_t crypt_seed[16];
|
||||
memcpy(crypt_seed, DMEM+req[3]+0x370, 16);
|
||||
uint8_t ek[32] = {}, sk[32] = {};
|
||||
if(pfs_derive_fake_keys(eekpfs, crypt_seed, ek, sk))
|
||||
{
|
||||
/*log_word(0xdead0004dead0001);
|
||||
{
|
||||
uint64_t* q = ek;
|
||||
for(int i = 0; i < 4; i++)
|
||||
log_word(q[i]);
|
||||
}
|
||||
{
|
||||
uint64_t* q = sk;
|
||||
for(int i = 0; i < 4; i++)
|
||||
log_word(q[i]);
|
||||
}*/
|
||||
int key1 = register_fake_key(ek);
|
||||
if(key1 >= 0)
|
||||
{
|
||||
int key2 = register_fake_key(sk);
|
||||
if(key2 >= 0)
|
||||
{
|
||||
regs[RIP] += 5;
|
||||
regs[RAX] = 0;
|
||||
uint32_t fake_resp[4] = {0, 0, IDX_TO_HANDLE(key1), IDX_TO_HANDLE(key2)};
|
||||
copy_to_kernel(regs[RDX], fake_resp, sizeof(fake_resp));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(regs[RIP] == (uint64_t)sceSblServiceCryptAsync_deref_singleton)
|
||||
{
|
||||
if(!handle_crypto_request(regs))
|
||||
{
|
||||
regs[RAX] |= -1ull << 48;
|
||||
regs[RBX] |= -1ull << 48;
|
||||
}
|
||||
}
|
||||
/*else if(regs[RIP] == (uint64_t)kdata_base - 0x94a7a0)
|
||||
{
|
||||
log_word(0xdead0004dead0005);
|
||||
log_word(regs[R13]);
|
||||
log_word(regs[R14]);
|
||||
}*/
|
||||
else
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void handle_fpkg_trap(uint64_t* regs, uint32_t trapno)
|
||||
{
|
||||
if(trapno == 1)
|
||||
{
|
||||
uint64_t frame[12];
|
||||
pop_stack(regs, frame, sizeof(frame));
|
||||
regs[RBX] = frame[7];
|
||||
regs[R14] = frame[8];
|
||||
regs[R15] = frame[9];
|
||||
regs[RBP] = frame[10];
|
||||
regs[RIP] = frame[11];
|
||||
regs[RAX] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const uint64_t dbgregs_for_nmount[6] = {0x1337, (uint64_t)kdata_base - 0x94a7f5, 0, 0, 0, 0x404};
|
||||
|
||||
void handle_fpkg_syscall(uint64_t* regs)
|
||||
{
|
||||
start_syscall_with_dbgregs(regs, dbgregs_for_nmount);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
void handle_fpkg_syscall(uint64_t* regs);
|
||||
void handle_fpkg_trap(uint64_t* regs, uint32_t trapno);
|
||||
int try_handle_fpkg_trap(uint64_t* regs);
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <errno.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <string.h>
|
||||
#include "kekcall.h"
|
||||
#include "traps.h"
|
||||
@@ -105,17 +107,35 @@ void handle_kekcall_trap(uint64_t* regs, uint32_t trap)
|
||||
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);
|
||||
if(sysc_no == SYS_sysarch && (uint32_t)stack_frame[7] == AMD64_GET_FSBASE)
|
||||
{
|
||||
stack_frame_2[1] = MKTRAP(TRAP_KEKCALL, 4);
|
||||
stack_frame_2[8] = kpeek64(kpeek64(regs[RDI]+td_pcb)+pcb_fsbase);
|
||||
kpoke64(stack_frame[13]+td_retval, 0);
|
||||
}
|
||||
else
|
||||
kpoke64(regs[RDI]+td_retval, 0);
|
||||
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);
|
||||
if(sysc_no == SYS_sysarch && (uint32_t)stack_frame[7] == AMD64_GET_FSBASE)
|
||||
{
|
||||
regs[RIP] = (uint64_t)copyout;
|
||||
regs[RDI] = regs[RSP] + 64;
|
||||
regs[RSI] = stack_frame[8];
|
||||
regs[RDX] = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
regs[RIP] = kpeek64((uint64_t)&sysents[sysc_no].sy_call);
|
||||
regs[RSI] = regs[RSP] + 64;
|
||||
handle_syscall(regs, 0);
|
||||
}
|
||||
}
|
||||
else if(trap == 3)
|
||||
else if(trap == 3 || trap == 4)
|
||||
{
|
||||
uint64_t stack_frame[14];
|
||||
pop_stack(regs, stack_frame, sizeof(stack_frame));
|
||||
if(!(uint32_t)regs[RAX])
|
||||
if(trap == 3 && !(uint32_t)regs[RAX])
|
||||
kpoke64(stack_frame[5]+td_retval, kpeek64(stack_frame[6]+td_retval));
|
||||
regs[RIP] = stack_frame[13];
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "traps.h"
|
||||
#include "kekcall.h"
|
||||
#include "fself.h"
|
||||
#include "fpkg.h"
|
||||
#include "syscall_fixes.h"
|
||||
|
||||
int have_error_code;
|
||||
@@ -55,6 +56,8 @@ void handle_syscall(uint64_t* regs, int allow_kekcall)
|
||||
|| IS(get_sdk_compiled_version)
|
||||
|| IS_PPR(get_ppr_sdk_compiled_version))
|
||||
handle_fself_syscall(regs);
|
||||
else if(IS(nmount))
|
||||
handle_fpkg_syscall(regs);
|
||||
else if(IS(mprotect)
|
||||
|| IS_PPR(mdbg_call))
|
||||
handle_syscall_fix(regs);
|
||||
@@ -138,6 +141,7 @@ from_userspace:
|
||||
case TRAP_KEKCALL: handle_kekcall_trap(regs, TRAP_IDX(lr)); break;
|
||||
#ifndef FREEBSD
|
||||
case TRAP_FSELF: handle_fself_trap(regs, TRAP_IDX(lr)); break;
|
||||
case TRAP_FPKG: handle_fpkg_trap(regs, TRAP_IDX(lr)); break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -146,6 +150,8 @@ from_userspace:
|
||||
return;
|
||||
else if(handle_fself_parasites(regs))
|
||||
return;
|
||||
else if(try_handle_fpkg_trap(regs))
|
||||
return;
|
||||
else if(try_handle_syscall_fix_trap(regs))
|
||||
return;
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "pfs_crypto.h"
|
||||
#include "utils.h"
|
||||
#include "../BearSSL/inc/bearssl.h"
|
||||
#include "../libtomcrypt/src/headers/tomcrypt.h"
|
||||
|
||||
static const uint8_t ypkg_n[256] = {0xc6, 0xcf, 0x71, 0xe7, 0xe5, 0x9a, 0xf0, 0xd1, 0x2a, 0x2c, 0x45, 0x8b, 0xf9, 0x2a, 0xe, 0xc1, 0x43, 0x5, 0x8b, 0xc3, 0x71, 0x17, 0x80, 0x1d, 0xcd, 0x49, 0x7d, 0xde, 0x35, 0x9d, 0x25, 0x9b, 0xa0, 0xd7, 0xa0, 0xf2, 0x7d, 0x6c, 0x8, 0x7e, 0xaa, 0x55, 0x2, 0x68, 0x2b, 0x23, 0xc6, 0x44, 0xb8, 0x44, 0x18, 0xeb, 0x56, 0xcf, 0x16, 0xa2, 0x48, 0x3, 0xc9, 0xe7, 0x4f, 0x87, 0xeb, 0x3d, 0x30, 0xc3, 0x15, 0x88, 0xbf, 0x20, 0xe7, 0x9d, 0xff, 0x77, 0xc, 0xde, 0x1d, 0x24, 0x1e, 0x63, 0xa9, 0x4f, 0x8a, 0xbf, 0x5b, 0xbe, 0x60, 0x19, 0x68, 0x33, 0x3b, 0xfc, 0xed, 0x9f, 0x47, 0x4e, 0x5f, 0xf8, 0xea, 0xcb, 0x3d, 0x0, 0xbd, 0x67, 0x1, 0xf9, 0x2c, 0x6d, 0xc6, 0xac, 0x13, 0x64, 0xe7, 0x67, 0x14, 0xf3, 0xdc, 0x52, 0x69, 0x6a, 0xb9, 0x83, 0x2c, 0x42, 0x30, 0x13, 0x1b, 0xb2, 0xd8, 0xa5, 0x2, 0xd, 0x79, 0xed, 0x96, 0xb1, 0xd, 0xf8, 0xcc, 0xc, 0xdf, 0x81, 0x95, 0x4f, 0x3, 0x58, 0x9, 0x57, 0xe, 0x80, 0x69, 0x2e, 0xfe, 0xff, 0x52, 0x77, 0xea, 0x75, 0x28, 0xa8, 0xfb, 0xc9, 0xbe, 0xbf, 0x9f, 0xbb, 0xb7, 0x79, 0x8e, 0x18, 0x5, 0xe1, 0x80, 0xbd, 0x50, 0x34, 0x94, 0x81, 0xd3, 0x53, 0xc2, 0x69, 0xa2, 0xd2, 0x4c, 0xcf, 0x6c, 0xf4, 0x57, 0x2c, 0x10, 0x4a, 0x3f, 0xfb, 0x22, 0xfd, 0x8b, 0x97, 0xe2, 0xc9, 0x5b, 0xa6, 0x2b, 0xcd, 0xd6, 0x1b, 0x6b, 0xdb, 0x68, 0x7f, 0x4b, 0xc2, 0xa0, 0x50, 0x34, 0xc0, 0x5, 0xe5, 0x8d, 0xef, 0x24, 0x67, 0xff, 0x93, 0x40, 0xcf, 0x2d, 0x62, 0xa2, 0xa0, 0x50, 0xb1, 0xf1, 0x3a, 0xa8, 0x3d, 0xfd, 0x80, 0xd1, 0xf9, 0xb8, 0x5, 0x22, 0xaf, 0xc8, 0x35, 0x45, 0x90, 0x58, 0x8e, 0xe3, 0x3a, 0x7c, 0xbd, 0x3e, 0x27};
|
||||
static const uint8_t ypkg_d[256] = {0x7f, 0x76, 0xcd, 0xe, 0xe2, 0xd4, 0xde, 0x5, 0x1c, 0xc6, 0xd9, 0xa8, 0xe, 0x8d, 0xfa, 0x7b, 0xca, 0x1e, 0xaa, 0x27, 0x1a, 0x40, 0xf8, 0xf1, 0x22, 0x87, 0x35, 0xdd, 0xdb, 0xfd, 0xee, 0xf8, 0xc2, 0xbc, 0xbd, 0x1, 0xfb, 0x8b, 0xe2, 0x3e, 0x63, 0xb2, 0xb1, 0x22, 0x5c, 0x56, 0x49, 0x6e, 0x11, 0xbe, 0x7, 0x44, 0xb, 0x9a, 0x26, 0x66, 0xd1, 0x49, 0x2c, 0x8f, 0xd3, 0x1b, 0xcf, 0xa4, 0xa1, 0xb8, 0xd1, 0xfb, 0xa4, 0x9e, 0xd2, 0x21, 0x28, 0x83, 0x9, 0x8a, 0xf6, 0xa0, 0xb, 0xa3, 0xd6, 0xf, 0x9b, 0x63, 0x68, 0xcc, 0xbc, 0xc, 0x4e, 0x14, 0x5b, 0x27, 0xa4, 0xa9, 0xf4, 0x2b, 0xb9, 0xb8, 0x7b, 0xc0, 0xe6, 0x51, 0xad, 0x1d, 0x77, 0xd4, 0x6b, 0xb9, 0xce, 0x20, 0xd1, 0x26, 0x66, 0x7e, 0x5e, 0x9e, 0xa2, 0xe9, 0x6b, 0x90, 0xf3, 0x73, 0xb8, 0x52, 0x8f, 0x44, 0x11, 0x3, 0xc, 0x13, 0x97, 0x39, 0x3d, 0x13, 0x22, 0x58, 0xd5, 0x43, 0x82, 0x49, 0xda, 0x6e, 0x7c, 0xa1, 0xc5, 0x8c, 0xa5, 0xb0, 0x9, 0xe0, 0xce, 0x3d, 0xdf, 0xf4, 0x9d, 0x3c, 0x97, 0x15, 0xe2, 0x6a, 0xc7, 0x2b, 0x3c, 0x50, 0x93, 0x23, 0xdb, 0xba, 0x4a, 0x22, 0x66, 0x44, 0xac, 0x78, 0xbb, 0xe, 0x1a, 0x27, 0x43, 0xb5, 0x71, 0x67, 0xaf, 0xf4, 0xab, 0x48, 0x46, 0x93, 0x73, 0xd0, 0x42, 0xab, 0x93, 0x63, 0xe5, 0x6c, 0x9a, 0xde, 0x50, 0x24, 0xc0, 0x23, 0x7d, 0x99, 0x79, 0x3f, 0x22, 0x7, 0xe0, 0xc1, 0x48, 0x56, 0x1b, 0xdf, 0x83, 0x9, 0x12, 0xb4, 0x2d, 0x45, 0x6b, 0xc9, 0xc0, 0x68, 0x85, 0x99, 0x90, 0x79, 0x96, 0x1a, 0xd7, 0xf5, 0x4d, 0x1f, 0x37, 0x83, 0x40, 0x4a, 0xec, 0x39, 0x37, 0xa6, 0x80, 0x92, 0x7d, 0xc5, 0x80, 0xc7, 0xd6, 0x6f, 0xfe, 0x8a, 0x79, 0x89, 0xc6, 0xb1};
|
||||
|
||||
static const br_rsa_public_key ypkg = {
|
||||
.n = (void*)ypkg_n,
|
||||
.nlen = sizeof(ypkg_n),
|
||||
.e = (void*)ypkg_d,
|
||||
.elen = sizeof(ypkg_d),
|
||||
};
|
||||
|
||||
static void pfs_gen_key(uint32_t idx, const uint8_t* seed, const uint8_t* ekpfs, uint8_t* out)
|
||||
{
|
||||
br_hmac_key_context key_ctx;
|
||||
br_hmac_key_init(&key_ctx, &br_sha256_vtable, ekpfs, 32);
|
||||
br_hmac_context ctx;
|
||||
br_hmac_init(&ctx, &key_ctx, 0);
|
||||
br_hmac_update(&ctx, &idx, sizeof(idx));
|
||||
br_hmac_update(&ctx, seed, 16);
|
||||
br_hmac_out(&ctx, out);
|
||||
}
|
||||
|
||||
int pfs_derive_fake_keys(const uint8_t* p_eekpfs, const uint8_t* crypt_seed, uint8_t* ek, uint8_t* sk)
|
||||
{
|
||||
uint8_t eekpfs[256];
|
||||
memcpy(eekpfs, p_eekpfs, 256);
|
||||
if(!br_rsa_i62_public(eekpfs, 256, &ypkg))
|
||||
return 0;
|
||||
if(eekpfs[0] != 0 || eekpfs[1] != 2)
|
||||
return 0;
|
||||
size_t idx = 1;
|
||||
while(idx < 256 && eekpfs[idx])
|
||||
idx++;
|
||||
if(idx != 255 - 32)
|
||||
return 0;
|
||||
uint8_t* ekpfs = eekpfs+idx+1;
|
||||
pfs_gen_key(1, crypt_seed, ekpfs, ek);
|
||||
pfs_gen_key(2, crypt_seed, ekpfs, sk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pfs_hmac_virtual(uint8_t* out, const uint8_t* key, uint64_t data, size_t data_size)
|
||||
{
|
||||
br_hmac_key_context key_ctx;
|
||||
br_hmac_key_init(&key_ctx, &br_sha256_vtable, key, 32);
|
||||
br_hmac_context ctx;
|
||||
br_hmac_init(&ctx, &key_ctx, 0);
|
||||
while(data_size)
|
||||
{
|
||||
uint64_t chunk_cur;
|
||||
uint64_t chunk_end;
|
||||
if(!virt2phys(data, &chunk_cur, &chunk_end))
|
||||
return -1;
|
||||
size_t chk = chunk_end - chunk_cur;
|
||||
if(chk > data_size)
|
||||
chk = data_size;
|
||||
br_hmac_update(&ctx, DMEM+chunk_cur, chk);
|
||||
data += chk;
|
||||
data_size -= chk;
|
||||
}
|
||||
br_hmac_out(&ctx, out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pfs_xts_virtual(uint64_t dst, uint64_t src, const uint8_t* key, uint64_t start, uint32_t count, int is_encrypt)
|
||||
{
|
||||
enum { SECTOR_SIZE = 4096 };
|
||||
static int aes_cipher = -1;
|
||||
if(aes_cipher < 0)
|
||||
{
|
||||
aes_cipher = register_cipher(&aes_desc);
|
||||
if(aes_cipher < 0)
|
||||
{
|
||||
log_word(0xdeaddeaddeaddead);
|
||||
log_word(aes_cipher);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
symmetric_xts xts = {};
|
||||
xts_start(aes_cipher, key+16, key, 16, 0, &xts);
|
||||
while(count--)
|
||||
{
|
||||
static uint8_t input[SECTOR_SIZE], output[SECTOR_SIZE];
|
||||
uint64_t tweak[2] = {start, 0};
|
||||
if(copy_from_kernel(input, src, SECTOR_SIZE))
|
||||
return -1;
|
||||
if(is_encrypt)
|
||||
xts_encrypt(input, SECTOR_SIZE, output, (void*)tweak, &xts);
|
||||
else
|
||||
xts_decrypt(input, SECTOR_SIZE, output, (void*)tweak, &xts);
|
||||
if(copy_to_kernel(dst, output, SECTOR_SIZE))
|
||||
return -1;
|
||||
dst += SECTOR_SIZE;
|
||||
src += SECTOR_SIZE;
|
||||
start++;
|
||||
}
|
||||
xts_done(&xts);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
int pfs_derive_fake_keys(const uint8_t* p_eekpfs, const uint8_t* crypt_seed, uint8_t* ek, uint8_t* sk);
|
||||
int pfs_hmac_virtual(uint8_t* out, const uint8_t* key, uint64_t data, size_t data_size);
|
||||
int pfs_xts_virtual(uint64_t dst, uint64_t src, const uint8_t* key, uint64_t start, uint32_t count, int is_encrypt);
|
||||
@@ -5,6 +5,7 @@ enum
|
||||
TRAP_UTILS = 0xdead0000,
|
||||
TRAP_KEKCALL,
|
||||
TRAP_FSELF,
|
||||
TRAP_FPKG,
|
||||
};
|
||||
|
||||
#define MKTRAP(kind, idx) (((uint64_t)(kind) << 32) | ((uint64_t)(idx)))
|
||||
|
||||
@@ -19,6 +19,7 @@ int virt2phys(uint64_t addr, uint64_t* phys, uint64_t* phys_limit)
|
||||
if(!(next_pml & 1))
|
||||
{
|
||||
log_word(0xdeaddeaddeaddead);
|
||||
log_word((uint64_t)__builtin_return_address(0));
|
||||
return 0;
|
||||
}
|
||||
if((next_pml & 128) || i == 12)
|
||||
@@ -40,7 +41,10 @@ int copy_from_kernel(void* dst, uint64_t src, uint64_t sz)
|
||||
while(sz)
|
||||
{
|
||||
if(!virt2phys(src, &phys, &phys_end))
|
||||
{
|
||||
log_word((uint64_t)__builtin_return_address(0));
|
||||
return EFAULT;
|
||||
}
|
||||
size_t chk = phys_end - phys;
|
||||
if(sz < chk)
|
||||
chk = sz;
|
||||
@@ -59,7 +63,10 @@ int copy_to_kernel(uint64_t dst, const void* src, uint64_t sz)
|
||||
while(sz)
|
||||
{
|
||||
if(!virt2phys(dst, &phys, &phys_end))
|
||||
{
|
||||
log_word((uint64_t)__builtin_return_address(0));
|
||||
return EFAULT;
|
||||
}
|
||||
size_t chk = phys_end - phys;
|
||||
if(sz < chk)
|
||||
chk = sz;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
#include "structs.h"
|
||||
#include "log.h"
|
||||
|
||||
extern uint64_t cr3_phys;
|
||||
extern uint64_t trap_frame;
|
||||
@@ -23,8 +24,9 @@ int wrmsr(uint32_t which, uint64_t value);
|
||||
|
||||
static inline uint64_t kpeek64(uintptr_t kptr)
|
||||
{
|
||||
uint64_t ans;
|
||||
copy_from_kernel(&ans, kptr, sizeof(ans));
|
||||
uint64_t ans = 0;
|
||||
if(copy_from_kernel(&ans, kptr, sizeof(ans)))
|
||||
log_word((uint64_t)__builtin_return_address(0));
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user