remove data_cave offset and use page alloc for sc args

This commit is contained in:
Mateico
2026-05-15 15:04:08 +02:00
parent e84dcbf281
commit 85a16afa80
9 changed files with 92 additions and 94 deletions

View File

@@ -18,9 +18,12 @@
#define hv_stack_size 0x1000ULL #define hv_stack_size 0x1000ULL
// This is used as transitional storage from ProsperoOS to Kernel shellcode // This is used as transitional storage from ProsperoOS to Kernel shellcode
#define kernel_cave_files 0xFFFF800000000000 #define kernel_cave 0xFFFF800000000000
#define kernel_cave_arguments kernel_cave
#define kernel_cave_files kernel_cave_arguments + PAGE_SIZE
#define kernel_cave_linux_info kernel_cave_files #define kernel_cave_linux_info kernel_cave_files
#define kernel_cave_bzImage kernel_cave_linux_info + PAGE_SIZE #define kernel_cave_bzImage kernel_cave_linux_info + PAGE_SIZE
// #define kernel_cave_initrd // Allocated dynamically after bzImage // #define kernel_cave_initrd // Allocated dynamically after bzImage
// Linux boot config // Linux boot config

View File

@@ -3,7 +3,6 @@
#include "utils.h" #include "utils.h"
#include <stdint.h> #include <stdint.h>
uint64_t alloc_page(void);
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits); void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits);
void pte_store(uintptr_t ptep, uint64_t pte); void pte_store(uintptr_t ptep, uint64_t pte);
int read_file(const char *path, void *buf, size_t bufsize); int read_file(const char *path, void *buf, size_t bufsize);

View File

@@ -12,7 +12,6 @@ typedef struct _offset_list {
/* Shellcode Kernel */ /* Shellcode Kernel */
uint64_t HOOK_ACPI_WAKEUP_MACHDEP; uint64_t HOOK_ACPI_WAKEUP_MACHDEP;
uint64_t KERNEL_CODE_CAVE; uint64_t KERNEL_CODE_CAVE;
uint64_t KERNEL_DATA_CAVE;
uint64_t FUN_PRINTF; uint64_t FUN_PRINTF;
uint64_t FUN_HV_IOMMU_SET_BUFFERS; uint64_t FUN_HV_IOMMU_SET_BUFFERS;
uint64_t FUN_HV_IOMM_WAIT_COMPLETION; uint64_t FUN_HV_IOMM_WAIT_COMPLETION;

View File

@@ -5,8 +5,8 @@
extern struct linux_info linux_i; extern struct linux_info linux_i;
int prepare_resume(void); int prepare_resume(void);
int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data); uint64_t prepare_sck_args(void);
int update_sck_args_ptr(uint64_t shellcode, uint64_t args);
void hook_call_near(uint64_t hook, uint64_t dst); void hook_call_near(uint64_t hook, uint64_t dst);
void prepare_sck_args(uint64_t dest_data);
#endif #endif

View File

@@ -167,4 +167,10 @@ enum kit_type { KIT_RETAIL, KIT_TESTKIT, KIT_DEVKIT };
enum kit_type get_kit_type(void); enum kit_type get_kit_type(void);
#define MINI_SYSCORE_PID 1
uint64_t alloc_page(void);
void pte_store(uintptr_t ptep, uint64_t pte);
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits);
void install_page_syscore(vm_offset_t va, vm_paddr_t pa, int bits);
#endif #endif

View File

@@ -19,59 +19,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#define MINI_SYSCORE_PID 1
uint64_t alloc_page(void) {
void *page = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// Fault it to force physical allocation
*(uint8_t *)page = 0;
return vtophys_user((uintptr_t)page);
}
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits) {
uint64_t entry;
uintptr_t pml4e = pml4 + pmap_pml4e_index(va) * 8;
entry = kread64(pml4e);
if (!PAGE_P(entry)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pml4e, entry);
}
uintptr_t pdpe = pa_to_dmap(PAGE_PA(entry)) + pmap_pdpe_index(va) * 8;
entry = kread64(pdpe);
if (!(entry & PG_B_P)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pdpe, entry);
}
uintptr_t pde = pa_to_dmap(PAGE_PA(entry)) + pmap_pde_index(va) * 8;
entry = kread64(pde);
if (!(entry & PG_B_P)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pde, entry);
}
uintptr_t pte = pa_to_dmap(PAGE_PA(entry)) + pmap_pte_index(va) * 8;
entry = pa | PG_B_RW | PG_B_P | bits;
pte_store(pte, entry);
}
void pte_store(uintptr_t ptep, uint64_t pte) {
static_assert((PAGE_SIZE % 0x1000) == 0,
"PAGE_SIZE should be a multiple of 0x1000");
for (uint64_t i = 0; i < (PAGE_SIZE / 0x1000); i++) {
kwrite64(ptep + i * 8, pte + i * 0x1000);
}
}
const char *file_paths[] = { const char *file_paths[] = {
"/mnt/usb0/", "/mnt/usb1/", "/mnt/usb2/", "/mnt/usb0/", "/mnt/usb1/", "/mnt/usb2/",
"/mnt/usb3/", "/mnt/usb0/PS5/Linux/", "/mnt/usb1/PS5/Linux/", "/mnt/usb3/", "/mnt/usb0/PS5/Linux/", "/mnt/usb1/PS5/Linux/",
@@ -179,9 +126,6 @@ void trim_newline(char *s) {
} }
int fetch_linux(struct linux_info *info) { int fetch_linux(struct linux_info *info) {
uintptr_t syscore_pmap = getpmap(kernel_get_proc(MINI_SYSCORE_PID));
uintptr_t syscore_pml4 = kread64(syscore_pmap + 0x20);
char bzimage_path[256]; char bzimage_path[256];
char initrd_path[256]; char initrd_path[256];
@@ -269,16 +213,16 @@ int fetch_linux(struct linux_info *info) {
uint64_t page = alloc_page(); uint64_t page = alloc_page();
kwrite(pa_to_dmap(page), info, sizeof(struct linux_info)); kwrite(pa_to_dmap(page), info, sizeof(struct linux_info));
install_page(syscore_pml4, kernel_cave_linux_info, page, 0); install_page_syscore(kernel_cave_linux_info, page, 0);
for (int i = 0; i < bzimage_size; i += PAGE_SIZE) { for (int i = 0; i < bzimage_size; i += PAGE_SIZE) {
install_page(syscore_pml4, info->bzimage + i, install_page_syscore(info->bzimage + i,
vtophys_user((uintptr_t)bzimage + i), 0); vtophys_user((uintptr_t)bzimage + i), 0);
} }
for (int i = 0; i < initrd_size; i += PAGE_SIZE) { for (int i = 0; i < initrd_size; i += PAGE_SIZE) {
install_page(syscore_pml4, info->initrd + i, install_page_syscore(info->initrd + i, vtophys_user((uintptr_t)initrd + i),
vtophys_user((uintptr_t)initrd + i), 0); 0);
} }
return 0; return 0;

View File

@@ -7,7 +7,6 @@ offset_list off_0300 = {
.DATA_BASE_GVMSPACE = 0x06423F80, .DATA_BASE_GVMSPACE = 0x06423F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x0390E73, .HOOK_ACPI_WAKEUP_MACHDEP = 0x0390E73,
.KERNEL_CODE_CAVE = 0x500, .KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x048B9A0, .FUN_PRINTF = 0x048B9A0,
.FUN_HV_IOMMU_SET_BUFFERS = 0x0B33E20, .FUN_HV_IOMMU_SET_BUFFERS = 0x0B33E20,
.FUN_HV_IOMM_WAIT_COMPLETION = 0x0B33D50, .FUN_HV_IOMM_WAIT_COMPLETION = 0x0B33D50,
@@ -33,7 +32,6 @@ offset_list off_0310 = {
.DATA_BASE_GVMSPACE = 0x06423F80, .DATA_BASE_GVMSPACE = 0x06423F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x0390EB3, .HOOK_ACPI_WAKEUP_MACHDEP = 0x0390EB3,
.KERNEL_CODE_CAVE = 0x500, .KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x048B9E0, .FUN_PRINTF = 0x048B9E0,
.FUN_HV_IOMMU_SET_BUFFERS = 0x0B33E60, .FUN_HV_IOMMU_SET_BUFFERS = 0x0B33E60,
.FUN_HV_IOMM_WAIT_COMPLETION = 0x0B33D90, .FUN_HV_IOMM_WAIT_COMPLETION = 0x0B33D90,
@@ -59,7 +57,6 @@ offset_list off_0320 = {
.DATA_BASE_GVMSPACE = 0x06423F80, .DATA_BASE_GVMSPACE = 0x06423F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x391203, .HOOK_ACPI_WAKEUP_MACHDEP = 0x391203,
.KERNEL_CODE_CAVE = 0x500, .KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x48BD30, .FUN_PRINTF = 0x48BD30,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB34320, .FUN_HV_IOMMU_SET_BUFFERS = 0xB34320,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB34250, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB34250,
@@ -85,7 +82,6 @@ offset_list off_0321 = {
.DATA_BASE_GVMSPACE = 0x06423F80, .DATA_BASE_GVMSPACE = 0x06423F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x391203, .HOOK_ACPI_WAKEUP_MACHDEP = 0x391203,
.KERNEL_CODE_CAVE = 0x500, .KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x48BD30, .FUN_PRINTF = 0x48BD30,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB34320, .FUN_HV_IOMMU_SET_BUFFERS = 0xB34320,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB34250, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB34250,
@@ -112,7 +108,6 @@ offset_list off_0400 = {
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613, .HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613,
.FUN_PRINTF = 0x4A3240, .FUN_PRINTF = 0x4A3240,
.KERNEL_CODE_CAVE = 0x500, .KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB638F0, .FUN_HV_IOMMU_SET_BUFFERS = 0xB638F0,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63830, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB63830,
.FUN_SMP_RENDEZVOUS = 0xA6C920, .FUN_SMP_RENDEZVOUS = 0xA6C920,
@@ -137,7 +132,6 @@ offset_list off_0402 = {
.DATA_BASE_GVMSPACE = 0x064C3F80, .DATA_BASE_GVMSPACE = 0x064C3F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613, .HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613,
.KERNEL_CODE_CAVE = 0x500, .KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x4A3240, .FUN_PRINTF = 0x4A3240,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB63950, .FUN_HV_IOMMU_SET_BUFFERS = 0xB63950,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63890, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB63890,
@@ -163,7 +157,6 @@ offset_list off_0403 = {
.DATA_BASE_GVMSPACE = 0x064C3F80, .DATA_BASE_GVMSPACE = 0x064C3F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613, .HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613,
.KERNEL_CODE_CAVE = 0x500, .KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x4A3240, .FUN_PRINTF = 0x4A3240,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB639F0, .FUN_HV_IOMMU_SET_BUFFERS = 0xB639F0,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63930, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB63930,
@@ -189,7 +182,6 @@ offset_list off_0450 = {
.DATA_BASE_GVMSPACE = 0x064C3F80, .DATA_BASE_GVMSPACE = 0x064C3F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x03A75E3, .HOOK_ACPI_WAKEUP_MACHDEP = 0x03A75E3,
.KERNEL_CODE_CAVE = 0x500, .KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x04A3270, .FUN_PRINTF = 0x04A3270,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB63BB0, .FUN_HV_IOMMU_SET_BUFFERS = 0xB63BB0,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63AF0, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB63AF0,
@@ -215,7 +207,6 @@ offset_list off_0451 = {
.DATA_BASE_GVMSPACE = 0x64C3F80, .DATA_BASE_GVMSPACE = 0x64C3F80,
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A75E3, .HOOK_ACPI_WAKEUP_MACHDEP = 0x3A75E3,
.KERNEL_CODE_CAVE = 0x500, .KERNEL_CODE_CAVE = 0x500,
.KERNEL_DATA_CAVE = 0xC01300,
.FUN_PRINTF = 0x4A3270, .FUN_PRINTF = 0x4A3270,
.FUN_HV_IOMMU_SET_BUFFERS = 0xB63FE0, .FUN_HV_IOMMU_SET_BUFFERS = 0xB63FE0,
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63F20, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB63F20,

View File

@@ -1,6 +1,7 @@
#include "prepare_resume.h" #include "prepare_resume.h"
#include "../shellcode_kernel/shellcode_kernel.h" #include "../shellcode_kernel/shellcode_kernel.h"
#include "../shellcode_kernel/shellcode_kernel_args.h" #include "../shellcode_kernel/shellcode_kernel_args.h"
#include "config.h"
#include "iommu.h" #include "iommu.h"
#include "offsets.h" #include "offsets.h"
#include "utils.h" #include "utils.h"
@@ -14,21 +15,14 @@ int prepare_resume(void) {
return -1; return -1;
} }
if (env_offset.KERNEL_DATA_CAVE == 0) { uint64_t args_va = prepare_sck_args();
printf("Error: missing data cave offset\n"); if (update_sck_args_ptr((uint64_t)shellcode_kernel_bin, args_va))
return -1;
}
uint64_t dest_text = ktext + env_offset.KERNEL_CODE_CAVE;
uint64_t dest_data = ktext + env_offset.KERNEL_DATA_CAVE;
kwrite_large(dest_text, shellcode_kernel_bin, shellcode_kernel_bin_len);
prepare_sck_args(dest_data);
if (update_sck_data_ptr(shellcode_kernel_bin, dest_text, dest_data))
return -1; return -1;
hook_call_near(ktext + env_offset.HOOK_ACPI_WAKEUP_MACHDEP, dest_text); uint64_t sck_va = ktext + env_offset.KERNEL_CODE_CAVE;
kwrite_large(sck_va, shellcode_kernel_bin, shellcode_kernel_bin_len);
hook_call_near(ktext + env_offset.HOOK_ACPI_WAKEUP_MACHDEP, sck_va);
kwrite8(ktext + env_offset.KERNEL_DEBUG_PATCH, 0xC3); kwrite8(ktext + env_offset.KERNEL_DEBUG_PATCH, 0xC3);
kwrite8(ktext + env_offset.KERNEL_CFI_CHECK, 0xC3); kwrite8(ktext + env_offset.KERNEL_CFI_CHECK, 0xC3);
@@ -36,11 +30,11 @@ int prepare_resume(void) {
return 0; return 0;
} }
int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data) { int update_sck_args_ptr(uint64_t shellcode, uint64_t args) {
// Find the address 0x11AA11AA11AA11AA used as marker // Find the address 0x11AA11AA11AA11AA used as marker
int offset = -1; int offset = -1;
for (int i = 0; i < 0x40; i++) { for (uint64_t i = 0; i < 0x40; i++) {
if (*(uint64_t *)((uint64_t)sc + i) == 0x11AA11AA11AA11AA) { if (*(uint64_t *)(shellcode + i) == 0x11AA11AA11AA11AA) {
offset = i; offset = i;
break; break;
} }
@@ -49,7 +43,7 @@ int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data) {
notify("Could not find offset of args_ptr address - Aborting\n"); notify("Could not find offset of args_ptr address - Aborting\n");
return -1; return -1;
} }
kwrite64(dest_text + offset, dest_data); *(uint64_t *)(shellcode + offset) = args;
return 0; return 0;
} }
@@ -62,7 +56,7 @@ void hook_call_near(uint64_t hook, uint64_t dst) {
DEBUG_PRINT("Instruction patched\n"); DEBUG_PRINT("Instruction patched\n");
} }
void prepare_sck_args(uint64_t dest_data) { uint64_t prepare_sck_args(void) {
shellcode_kernel_args args; shellcode_kernel_args args;
args.fw_version = fw; args.fw_version = fw;
args.ktext = ktext; args.ktext = ktext;
@@ -94,5 +88,9 @@ void prepare_sck_args(uint64_t dest_data) {
args.linux_info_va = linux_i.linux_info; args.linux_info_va = linux_i.linux_info;
kernel_copyin(&args, dest_data, sizeof(args)); uint64_t args_cave = alloc_page();
kernel_copyin(&args, pa_to_dmap(args_cave), sizeof(args));
install_page_syscore(kernel_cave_arguments, args_cave, 0);
return kernel_cave_arguments;
} }

View File

@@ -4,6 +4,7 @@
#include <ps5/kernel.h> #include <ps5/kernel.h>
#include <stdio.h> #include <stdio.h>
#include <sys/cpuset.h> #include <sys/cpuset.h>
#include <sys/mman.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -284,3 +285,60 @@ enum kit_type get_kit_type(void) {
notify("Retail console detected\n"); notify("Retail console detected\n");
return KIT_RETAIL; return KIT_RETAIL;
} }
uint64_t alloc_page(void) {
void *page = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// Fault it to force physical allocation
*(uint8_t *)page = 0;
return vtophys_user((uintptr_t)page);
}
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits) {
uint64_t entry;
uintptr_t pml4e = pml4 + pmap_pml4e_index(va) * 8;
entry = kread64(pml4e);
if (!PAGE_P(entry)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pml4e, entry);
}
uintptr_t pdpe = pa_to_dmap(PAGE_PA(entry)) + pmap_pdpe_index(va) * 8;
entry = kread64(pdpe);
if (!(entry & PG_B_P)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pdpe, entry);
}
uintptr_t pde = pa_to_dmap(PAGE_PA(entry)) + pmap_pde_index(va) * 8;
entry = kread64(pde);
if (!(entry & PG_B_P)) {
uint64_t page = alloc_page();
entry = page | PG_B_RW | PG_B_P | bits;
kwrite64(pde, entry);
}
uintptr_t pte = pa_to_dmap(PAGE_PA(entry)) + pmap_pte_index(va) * 8;
entry = pa | PG_B_RW | PG_B_P | bits;
pte_store(pte, entry);
}
void pte_store(uintptr_t ptep, uint64_t pte) {
static_assert((PAGE_SIZE % 0x1000) == 0,
"PAGE_SIZE should be a multiple of 0x1000");
for (uint64_t i = 0; i < (PAGE_SIZE / 0x1000); i++) {
kwrite64(ptep + i * 8, pte + i * 0x1000);
}
}
void install_page_syscore(vm_offset_t va, vm_paddr_t pa, int bits) {
uintptr_t syscore_pmap = getpmap(kernel_get_proc(MINI_SYSCORE_PID));
uintptr_t syscore_pml4 = kread64(syscore_pmap + 0x20);
install_page(syscore_pml4, va, pa, bits);
}