Xbox 360 executable designed to apply freedom-unlocking patches based on xeBuild to the kernel and hypervisor. (Mirrored from https://github.com/FreeMyXe/FreeMyXe)

initial commit

+9
.gitignore
··· 1 + build/ 2 + out/ 3 + package/ 4 + *.exe 5 + *.xex 6 + *.dll 7 + *.pdb 8 + *.xdb 9 + *.obj
+19
.vscode/c_cpp_properties.json
··· 1 + { 2 + "configurations": [ 3 + { 4 + "name": "Xbox 360", 5 + "includePath": [ 6 + "${XEDK}/include/xbox", 7 + "include" 8 + ], 9 + "defines": [ 10 + "_DEBUG", 11 + "_XBOX" 12 + ], 13 + "compilerPath": "${XEDK}/bin/win32/cl.exe", 14 + "cStandard": "c89", 15 + "intelliSenseMode": "msvc-x86" 16 + } 17 + ], 18 + "version": 4 19 + }
+6
.vscode/settings.json
··· 1 + { 2 + "editor.tabSize": 4, 3 + "editor.insertSpaces": true, 4 + //"editor.formatOnSave": true, 5 + //"editor.formatOnPaste": true, 6 + }
+67
Makefile
··· 1 + # FreeMyXe Makefile 2 + 3 + # the source code files to compile from 4 + SRC_DIR := source 5 + SOURCES := $(wildcard $(SRC_DIR)/*.c) 6 + INC_DIR := include 7 + 8 + # output filename for final XEX file 9 + OUTNAME := FreeMyXe 10 + 11 + # definitions for compilation 12 + DEFINES := NDEBUG 13 + 14 + # build directory 15 + BUILD := build 16 + # .obj object files 17 + OBJECTS := $(subst $(SRC_DIR),$(BUILD),$(patsubst %.c,%.obj,$(SOURCES))) 18 + # executable tool path 19 + TOOLPATH := $(XEDK)/bin/win32 20 + COMPILER := "$(TOOLPATH)/cl.exe" 21 + LINKER := "$(TOOLPATH)/link.exe" 22 + IMAGEXEX := "$(TOOLPATH)/imagexex.exe" 23 + XEXTOOL := $(XEXTOOL)/XexTool.exe 24 + # include directories 25 + INCLUDES := "$(XEDK)/include/xbox" 26 + # library directories 27 + LIBDIR := "$(XEDK)/lib/xbox" 28 + # library includes 29 + LIBS := xapilib.lib xboxkrnl.lib 30 + # compiler flags 31 + CFLAGS := -c -Zi -nologo -W3 -WX- -Ox -Os -D _XBOX -D RB3E_XBOX $(patsubst %,-D %,$(DEFINES)) \ 32 + -GF -Gm- -MT -GS- -Gy -fp:fast -fp:except- -Zc:wchar_t -Zc:forScope \ 33 + -GR- -openmp- -FI"$(XEDK)/include/xbox/xbox_intellisense_platform.h" \ 34 + -Fd"$(BUILD)/" -I "$(INC_DIR)" 35 + # linker flags 36 + LFLAGS := -ERRORREPORT:PROMPT -INCREMENTAL:NO -NOLOGO $(LIBS) \ 37 + -MANIFESTUAC:"level='asInvoker' uiAccess='false'" -DEBUG \ 38 + -STACK:"262144","262144" -OPT:REF -OPT:ICF -TLBID:1 -RELEASE \ 39 + -XEX:NO 40 + # xex generation flags 41 + XEXFLAGS := -nologo -config:"xex.xml" 42 + # xextool flags 43 + XEXTOOLFLAGS := -e e -c c -m r -r a 44 + # ================= 45 + 46 + .PHONY: all 47 + all: $(OUTNAME).xex 48 + 49 + .PHONY: clean 50 + clean: 51 + @rm -rf $(wildcard $(BUILD) $(OUTPUT)) 52 + @rm -f $(OUTNAME) 53 + 54 + $(OUTNAME).xex: $(BUILD)/$(OUTNAME).exe 55 + @echo "Creating XEX..." 56 + @mkdir -p $(@D) 57 + @$(WINDOWS_SHIM) $(IMAGEXEX) $(XEXFLAGS) -out:"$@" "$^" 58 + @$(WINDOWS_SHIM) $(XEXTOOL) $(XEXTOOLFLAGS) $@ 59 + 60 + $(BUILD)/$(OUTNAME).exe: $(OBJECTS) 61 + @echo "Linking EXE..." 62 + @mkdir -p $(@D) 63 + @LIB=$(LIBDIR) $(WINDOWS_SHIM) $(LINKER) $(LFLAGS) -OUT:"$@" -PDB:"$(BUILD)/$(OUTNAME).pdb" -IMPLIB:"$(BUILD)/$(OUTNAME)" $^ 64 + 65 + $(BUILD)/%.obj: $(SRC_DIR)/%.c 66 + @mkdir -p $(@D) 67 + @INCLUDE=$(INCLUDES) $(WINDOWS_SHIM) $(COMPILER) $(CFLAGS) -Fo"$@" -TC $<
+26
README.md
··· 1 + # FreeMyXe 2 + 3 + by Emma / InvoxiPlayGames 4 + 5 + Xbox 360 executable designed to apply freedom-unlocking patches to the kernel 6 + and hypervisor. 7 + 8 + For use with [Xbox360BadUpdate](https://github.com/grimdoomer/Xbox360BadUpdate). 9 + 10 + Nowhere near finished or ready or stable or anything. Currently patches some 11 + XEX load checks as well as LIVE/PIRS signature verification in the kernel. 12 + 13 + ## TODO 14 + 15 + * Userland memory protection patches 16 + * Actual patch compiler and loader 17 + * Daaaashlaaaaaaunch? 18 + 19 + ## Credits 20 + 21 + * ikari's original freeBOOT 22 + * cOz et al. for xeBuild 17559 patches 23 + (see also https://www.xbins.org/nfo.php?file=xboxnfo2430.nfo) 24 + * RGLoader 25 + 26 + (let me know if I got anything wrong!)
+13
include/hv_funcs.h
··· 1 + #include <stdint.h> 2 + 3 + uint64_t HvxGetVersions(uint32_t magic, int op, uint64_t source, uint64_t dest, uint64_t length); 4 + 5 + void SetUsingFreeboot(int val); 6 + uint64_t GetHVTargetAddress(uint32_t address); 7 + void WriteHypervisor(uint32_t hv_address, void *userland_data, size_t length); 8 + void HypervisorClearCache(uint32_t address); 9 + void ReadHypervisor(void *userland_data, uint32_t hv_address, size_t length); 10 + void WriteHypervisorUInt32(uint32_t hv_address, uint32_t value); 11 + void WriteHypervisorUInt64(uint32_t hv_address, uint64_t value); 12 + void WriteHypervisorUInt32_RMCI(uint32_t address, uint32_t value); 13 + void WriteHypervisorUInt64_RMCI(uint32_t address, uint64_t value);
+34
include/ppcasm.h
··· 1 + /* 2 + ppcasm.h by InvoxiPlayGames, 2021 3 + WTFPL License 4 + */ 5 + 6 + #include <stdint.h> 7 + 8 + // Poke values 9 + #define POKE_8(addr, val) do { *(uint8_t*)(addr) = (uint8_t)(val); } while (0) 10 + #define POKE_16(addr, val) do { *(uint16_t*)(addr) = (uint16_t)(val); } while (0) 11 + #define POKE_32(addr, val) do { *(uint32_t*)(addr) = (uint32_t)(val); } while (0) 12 + 13 + // PowerPC instructions! 14 + #define ADDI(dest, src, val) (0x38000000 + ((uint8_t)dest << 21) + ((uint8_t)src << 16) + ((uint16_t)val)) 15 + #define ADDIS(dest, src, val) (0x3C000000 + ((uint8_t)dest << 21) + ((uint8_t)src << 16) + ((uint16_t)val)) 16 + #define ORI(dest, src, val) (0x60000000 + ((uint8_t)dest << 21) + ((uint8_t)src << 16) + ((uint16_t)val)) 17 + #define ORIS(dest, src, val) (0x64000000 + ((uint8_t)dest << 21) + ((uint8_t)src << 16) + ((uint16_t)val)) 18 + #define B(dest, src) (0x48000000 + (((uint32_t)(dest) - (uint32_t)(src)) & 0x3ffffff)) 19 + 20 + // PowerPC shorthand instructions! 21 + #define LI(dest, val) ADDI(dest, 0, val) 22 + #define LIS(dest, val) ADDIS(dest, 0, val) 23 + #define BL(dest, src) B(dest, src) + 1 24 + #define NOP ORI(0, 0, 0) 25 + 26 + // PowerPC instructions 2: This time it's hardcoded 27 + #define BLR 0x4e800020 28 + #define BCTR 0x4e800420 29 + #define BLRL BLR+1 30 + #define BCTRL BCTR+1 31 + 32 + // Poke branches 33 + #define POKE_B(addr, dest) POKE_32(addr, B(dest, addr)) 34 + #define POKE_BL(addr, dest) POKE_32(addr, BL(dest, addr))
+8
include/xboxkrnl.h
··· 1 + #include <xtl.h> 2 + 3 + extern void DbgPrint(const char *s, ...); 4 + extern unsigned int MmGetPhysicalAddress(void *buffer); 5 + extern unsigned int ExCreateThread(PHANDLE pHandle, DWORD dwStackSize, LPDWORD lpThreadId, PVOID apiThreadStartup, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlagsMod); 6 + extern void XapiThreadStartup(void (__cdecl *StartRoutine)(void *), void * StartContext); 7 + extern unsigned int XexGetModuleHandle(PCSTR moduleName, PHANDLE hand); 8 + extern unsigned int XexGetProcedureAddress(HANDLE hand, DWORD dwOrdinal, PVOID Address);
+161
source/FreeMyXe.c
··· 1 + #include <xtl.h> 2 + #include <stdint.h> 3 + #include "xboxkrnl.h" 4 + #include "ppcasm.h" 5 + #include "hv_funcs.h" 6 + 7 + static LPWSTR buttons[1] = {L"OK"}; 8 + static MESSAGEBOX_RESULT result; 9 + static XOVERLAPPED overlapped; 10 + static wchar_t dialog_text_buffer[256]; 11 + 12 + void MessageBox(wchar_t *text) 13 + { 14 + if (XShowMessageBoxUI(0, L"FreeMyXe beta1", text, 1, buttons, 0, XMB_ALERTICON, &result, &overlapped) == ERROR_IO_PENDING) 15 + { 16 + while (!XHasOverlappedIoCompleted(&overlapped)) 17 + Sleep(50); 18 + } 19 + } 20 + 21 + // the Freeboot syscall 0 backdoor for 17559 22 + static uint8_t freeboot_memcpy_bytecode[] = 23 + { 24 + 0x3D, 0x60, 0x72, 0x62, 0x61, 0x6B, 0x74, 0x72, 0x7F, 0x03, 0x58, 0x40, 0x41, 0x9A, 0x00, 0x08, 25 + 0x48, 0x00, 0x1C, 0xCA, 0x2B, 0x04, 0x00, 0x04, 0x41, 0x99, 0x00, 0x94, 0x41, 0x9A, 0x00, 0x44, 26 + 0x38, 0xA0, 0x15, 0x4C, 0x3C, 0xC0, 0x38, 0x80, 0x2B, 0x04, 0x00, 0x02, 0x40, 0x9A, 0x00, 0x0C, 27 + 0x60, 0xC6, 0x00, 0x07, 0x48, 0x00, 0x00, 0x0C, 0x2B, 0x04, 0x00, 0x03, 0x40, 0x9A, 0x00, 0x1C, 28 + 0x38, 0x00, 0x00, 0x00, 0x90, 0xC5, 0x00, 0x00, 0x7C, 0x00, 0x28, 0x6C, 0x7C, 0x00, 0x2F, 0xAC, 29 + 0x7C, 0x00, 0x04, 0xAC, 0x4C, 0x00, 0x01, 0x2C, 0x38, 0x60, 0x00, 0x01, 0x4E, 0x80, 0x00, 0x20, 30 + 0x7D, 0x88, 0x02, 0xA6, 0xF9, 0x81, 0xFF, 0xF8, 0xF8, 0x21, 0xFF, 0xF1, 0x7C, 0xA8, 0x03, 0xA6, 31 + 0x7C, 0xE9, 0x03, 0xA6, 0x80, 0x86, 0x00, 0x00, 0x90, 0x85, 0x00, 0x00, 0x7C, 0x00, 0x28, 0x6C, 32 + 0x7C, 0x00, 0x2F, 0xAC, 0x7C, 0x00, 0x04, 0xAC, 0x4C, 0x00, 0x01, 0x2C, 0x38, 0xA5, 0x00, 0x04, 33 + 0x38, 0xC6, 0x00, 0x04, 0x42, 0x00, 0xFF, 0xE0, 0x4E, 0x80, 0x00, 0x20, 0x38, 0x21, 0x00, 0x10, 34 + 0xE9, 0x81, 0xFF, 0xF8, 0x7D, 0x88, 0x03, 0xA6, 0x4E, 0x80, 0x00, 0x20, 0x2B, 0x04, 0x00, 0x05, 35 + 0x40, 0x9A, 0x00, 0x14, 0x7C, 0xC3, 0x33, 0x78, 0x7C, 0xA4, 0x2B, 0x78, 0x7C, 0xE5, 0x3B, 0x78, 36 + 0x48, 0x00, 0xA8, 0x82, 0x38, 0x60, 0x00, 0x02, 0x4E, 0x80, 0x00, 0x20, 37 + }; 38 + 39 + // the memory protection patches for 17559 40 + static uint8_t memory_protection_bytecode[] = 41 + { 42 + 0x38, 0x80, 0x00, 0x07, 0x7C, 0x21, 0x20, 0x78, 0x7C, 0x35, 0xEB, 0xA6, 0x48, 0x00, 0x11, 0xC2 43 + }; 44 + 45 + void __cdecl main() 46 + { 47 + uint8_t cpu_key[0x10]; 48 + HANDLE hThread; 49 + DWORD threadId; 50 + 51 + memset(cpu_key, 0, sizeof(cpu_key)); 52 + 53 + DbgPrint("FreeMyXe!\n"); 54 + 55 + if (HvxGetVersions(0x72627472, 1, 0, 0, 0) == 1) 56 + { 57 + DbgPrint("Freeboot detected, installing POST out backdoor\n"); 58 + // downgrade to badupdate backdoor for testing 59 + // set HvxPostOutput syscall to point to mtctr r4; bctr; pair 60 + SetUsingFreeboot(1); 61 + WriteHypervisorUInt32(0x00015FD0 + (0xD * 4), 0x00000354); 62 + SetUsingFreeboot(0); 63 + } 64 + else 65 + { 66 + DbgPrint("using BadUpdate POST out backdoor\n"); 67 + } 68 + 69 + // read out the CPU key 70 + ReadHypervisor(cpu_key, 0x20, sizeof(cpu_key)); 71 + 72 + DbgPrint("CPU key: %08X%08X%08X%08X\n", 73 + *(uint32_t *)(cpu_key + 0x0), *(uint32_t *)(cpu_key + 0x4), *(uint32_t *)(cpu_key + 0x8), *(uint32_t *)(cpu_key + 0xC)); 74 + 75 + wsprintfW(dialog_text_buffer, L"About to start patching HV and kernel...\n\nYour CPU key is:\n%08X%08X%08X%08X\n\ngithub.com/InvoxiPlayGames/FreeMyXe", *(uint32_t *)(cpu_key + 0x0), *(uint32_t *)(cpu_key + 0x4), *(uint32_t *)(cpu_key + 0x8), *(uint32_t *)(cpu_key + 0xC)); 76 + MessageBox(dialog_text_buffer); 77 + 78 + DbgPrint("Writing syscall 0 backdoor...\n"); 79 + // install the syscall 0 backdoor at a spare place in memory 80 + WriteHypervisor(0x0000B564, freeboot_memcpy_bytecode, sizeof(freeboot_memcpy_bytecode)); 81 + // set syscall 0 to point to our backdoor 82 + WriteHypervisorUInt32(0x00015FD0, 0x0000B564); 83 + 84 + DbgPrint("Writing memory protection patches...\n"); 85 + // write the patched memory protection instructions 86 + WriteHypervisor(0x0000154C, memory_protection_bytecode, sizeof(memory_protection_bytecode)); 87 + // jump to the above shellcode 88 + WriteHypervisorUInt32(0x000011BC, 0x4800154E); 89 + HypervisorClearCache(0x0000154C); 90 + 91 + DbgPrint("Writing expansion signature patches...\n"); 92 + WriteHypervisorUInt32(0x00030894, LI(3, 1)); // call to XeCryptBnQwBeSigVerify 93 + WriteHypervisorUInt32(0x00030914, LI(3, 0)); // call to memcmp 94 + 95 + DbgPrint("HV patched! Patching kernel\n"); 96 + 97 + { 98 + uint64_t returnTrue = (((uint64_t)LI(3, 1)) << 32) | (BLR); 99 + uint64_t returnZero = (((uint64_t)LI(3, 0)) << 32) | (BLR); 100 + uint64_t valTo = 0; 101 + HANDLE hKernel = NULL; 102 + PDWORD pdwFunction = NULL; 103 + 104 + XexGetModuleHandle("xboxkrnl.exe", &hKernel); 105 + 106 + // patch XeKeysVerifyRSASignature 107 + XexGetProcedureAddress(hKernel, 600, &pdwFunction); 108 + WriteHypervisorUInt64_RMCI(MmGetPhysicalAddress(pdwFunction), returnTrue); 109 + HypervisorClearCache(MmGetPhysicalAddress(pdwFunction)); 110 + 111 + // patch XeKeysVerifyPIRSSignature 112 + XexGetProcedureAddress(hKernel, 862, &pdwFunction); 113 + WriteHypervisorUInt64_RMCI(MmGetPhysicalAddress(pdwFunction), returnTrue); 114 + HypervisorClearCache(MmGetPhysicalAddress(pdwFunction)); 115 + 116 + // patch UsbdIsDeviceAuthenticated 117 + XexGetProcedureAddress(hKernel, 745, &pdwFunction); 118 + WriteHypervisorUInt64_RMCI(MmGetPhysicalAddress(pdwFunction), returnTrue); 119 + HypervisorClearCache(MmGetPhysicalAddress(pdwFunction)); 120 + 121 + // patch XexpVerifyMediaType 122 + pdwFunction = (PDWORD)0x80078ed0; 123 + WriteHypervisorUInt64_RMCI(MmGetPhysicalAddress(pdwFunction), returnTrue); 124 + HypervisorClearCache(MmGetPhysicalAddress(pdwFunction)); 125 + 126 + // patch XexpVerifyDeviceId 127 + pdwFunction = (PDWORD)0x80079e10; 128 + WriteHypervisorUInt64_RMCI(MmGetPhysicalAddress(pdwFunction), returnZero); 129 + HypervisorClearCache(MmGetPhysicalAddress(pdwFunction)); 130 + 131 + // patch XexpConvertError 132 + pdwFunction = (PDWORD)0x8007b920; 133 + WriteHypervisorUInt64_RMCI(MmGetPhysicalAddress(pdwFunction), returnZero); 134 + HypervisorClearCache(MmGetPhysicalAddress(pdwFunction)); 135 + 136 + // patch a hash check in XexpVerifyXexHeaders 137 + pdwFunction = (PDWORD)0x8007c034; 138 + valTo = (((uint64_t)NOP) << 32) | NOP; 139 + WriteHypervisorUInt64_RMCI(MmGetPhysicalAddress(pdwFunction), valTo); 140 + HypervisorClearCache(MmGetPhysicalAddress(pdwFunction)); 141 + 142 + // patch XexpVerifyMinimumVersion 143 + pdwFunction = (PDWORD)0x8007af08; 144 + WriteHypervisorUInt64_RMCI(MmGetPhysicalAddress(pdwFunction), returnZero); 145 + HypervisorClearCache(MmGetPhysicalAddress(pdwFunction)); 146 + 147 + // patch XexpTranslateAndVerifyBoundPath to always return true 148 + pdwFunction = (PDWORD)0x80078eb0; 149 + valTo = (((uint64_t)LI(3, 1)) << 32) | ADDI(1, 1, 0x190); 150 + WriteHypervisorUInt64_RMCI(MmGetPhysicalAddress(pdwFunction), valTo); 151 + HypervisorClearCache(MmGetPhysicalAddress(pdwFunction)); 152 + } 153 + 154 + DbgPrint("Done\n"); 155 + 156 + Sleep(500); 157 + 158 + buttons[0] = L"Yay!"; 159 + wsprintfW(dialog_text_buffer, L"Hypervisor and kernel have been patched!\n\nYour CPU key is:\n%08X%08X%08X%08X\n\ngithub.com/InvoxiPlayGames/FreeMyXe", *(uint32_t *)(cpu_key + 0x0), *(uint32_t *)(cpu_key + 0x4), *(uint32_t *)(cpu_key + 0x8), *(uint32_t *)(cpu_key + 0xC)); 160 + MessageBox(dialog_text_buffer); 161 + }
+210
source/hv_funcs.c
··· 1 + #include <xtl.h> 2 + #include <stdint.h> 3 + #include "xboxkrnl.h" 4 + #include "ppcasm.h" 5 + 6 + static uint8_t freeboot_memcpy_bytecode[] = 7 + { 8 + 0x3D, 0x60, 0x72, 0x62, 0x61, 0x6B, 0x74, 0x72, 0x7F, 0x03, 0x58, 0x40, 0x41, 0x9A, 0x00, 0x08, 9 + 0x48, 0x00, 0x1C, 0xCA, 0x2B, 0x04, 0x00, 0x04, 0x41, 0x99, 0x00, 0x94, 0x41, 0x9A, 0x00, 0x44, 10 + 0x38, 0xA0, 0x15, 0x4C, 0x3C, 0xC0, 0x38, 0x80, 0x2B, 0x04, 0x00, 0x02, 0x40, 0x9A, 0x00, 0x0C, 11 + 0x60, 0xC6, 0x00, 0x07, 0x48, 0x00, 0x00, 0x0C, 0x2B, 0x04, 0x00, 0x03, 0x40, 0x9A, 0x00, 0x1C, 12 + 0x38, 0x00, 0x00, 0x00, 0x90, 0xC5, 0x00, 0x00, 0x7C, 0x00, 0x28, 0x6C, 0x7C, 0x00, 0x2F, 0xAC, 13 + 0x7C, 0x00, 0x04, 0xAC, 0x4C, 0x00, 0x01, 0x2C, 0x38, 0x60, 0x00, 0x01, 0x4E, 0x80, 0x00, 0x20, 14 + 0x7D, 0x88, 0x02, 0xA6, 0xF9, 0x81, 0xFF, 0xF8, 0xF8, 0x21, 0xFF, 0xF1, 0x7C, 0xA8, 0x03, 0xA6, 15 + 0x7C, 0xE9, 0x03, 0xA6, 0x80, 0x86, 0x00, 0x00, 0x90, 0x85, 0x00, 0x00, 0x7C, 0x00, 0x28, 0x6C, 16 + 0x7C, 0x00, 0x2F, 0xAC, 0x7C, 0x00, 0x04, 0xAC, 0x4C, 0x00, 0x01, 0x2C, 0x38, 0xA5, 0x00, 0x04, 17 + 0x38, 0xC6, 0x00, 0x04, 0x42, 0x00, 0xFF, 0xE0, 0x4E, 0x80, 0x00, 0x20, 0x38, 0x21, 0x00, 0x10, 18 + 0xE9, 0x81, 0xFF, 0xF8, 0x7D, 0x88, 0x03, 0xA6, 0x4E, 0x80, 0x00, 0x20, 0x2B, 0x04, 0x00, 0x05, 19 + 0x40, 0x9A, 0x00, 0x14, 0x7C, 0xC3, 0x33, 0x78, 0x7C, 0xA4, 0x2B, 0x78, 0x7C, 0xE5, 0x3B, 0x78, 20 + 0x48, 0x00, 0xA8, 0x82, 0x38, 0x60, 0x00, 0x02, 0x4E, 0x80, 0x00, 0x20, 21 + }; 22 + 23 + static uint8_t icbi_bytecode[] = 24 + { 25 + 0x38, 0x80, 0x00, 0x7F, 0x7C, 0xA3, 0x20, 0x78, 0x7C, 0x00, 0x1F, 0xAC, 0x4E, 0x80, 0x00, 0x20 26 + }; 27 + 28 + static uint8_t rmci_write_std_bytecode[] = 29 + { 30 + 0x7D, 0x88, 0x02, 0xA6, 0x38, 0x60, 0x00, 0x00, 0x39, 0x60, 0x03, 0x98, 0x7D, 0x69, 0x03, 0xA6, 31 + 0x4E, 0x80, 0x04, 0x21, 0xF8, 0xC5, 0x00, 0x00, 0x38, 0x60, 0x00, 0x01, 0x39, 0x60, 0x03, 0x98, 32 + 0x7D, 0x69, 0x03, 0xA6, 0x4E, 0x80, 0x04, 0x21, 0x7D, 0x88, 0x03, 0xA6, 0x4E, 0x80, 0x00, 0x20, 33 + }; 34 + 35 + static uint8_t rmci_write_stw_bytecode[] = 36 + { 37 + 0x7D, 0x88, 0x02, 0xA6, 0x38, 0x60, 0x00, 0x00, 0x39, 0x60, 0x03, 0x98, 0x7D, 0x69, 0x03, 0xA6, 38 + 0x4E, 0x80, 0x04, 0x21, 0x90, 0xC5, 0x00, 0x00, 0x38, 0x60, 0x00, 0x01, 0x39, 0x60, 0x03, 0x98, 39 + 0x7D, 0x69, 0x03, 0xA6, 0x4E, 0x80, 0x04, 0x21, 0x7D, 0x88, 0x03, 0xA6, 0x4E, 0x80, 0x00, 0x20, 40 + }; 41 + 42 + // Freeboot memcpy 43 + uint64_t __declspec(naked) HvxGetVersions(uint32_t magic, int op, uint64_t source, uint64_t dest, uint64_t length) { 44 + __asm 45 + { 46 + li r0, 0x0 47 + sc 48 + blr 49 + } 50 + } 51 + 52 + // BadUpdate backdoor, args for glorified Freeboot memcpy 53 + static uint64_t __declspec(naked) HvxPostOutputMemcpy(uint32_t r3, uint64_t shellcode_addy, uint64_t source, uint64_t dest, uint64_t length) 54 + { 55 + _asm 56 + { 57 + li r0, 0xD 58 + sc 59 + blr 60 + } 61 + } 62 + 63 + // BadUpdate backdoor, args for flushing cache 64 + static uint64_t __declspec(naked) HvxPostOutputIcbi(uint32_t r3, uint64_t shellcode_addy, uint64_t address) 65 + { 66 + _asm 67 + { 68 + li r0, 0xD 69 + sc 70 + blr 71 + } 72 + } 73 + 74 + // BadUpdate backdoor, args for writing with rmci disabled 75 + static uint64_t __declspec(naked) HvxPostOutputRMCIWrite(uint32_t r3, uint64_t shellcode_addy, uint64_t address, uint64_t value) 76 + { 77 + _asm 78 + { 79 + li r0, 0xD 80 + sc 81 + blr 82 + } 83 + } 84 + 85 + static int use_freeboot_syscall = 0; 86 + 87 + void SetUsingFreeboot(int val) 88 + { 89 + use_freeboot_syscall = val; 90 + } 91 + 92 + uint64_t GetHVTargetAddress(uint32_t address) 93 + { 94 + if (address >= 0x00000 && address < 0x10000) 95 + return 0x8000010000000000 | address; 96 + else if (address >= 0x10000 && address < 0x20000) 97 + return 0x8000010200000000 | address; 98 + else if (address >= 0x20000 && address < 0x30000) 99 + return 0x8000010400000000 | address; 100 + else if (address >= 0x30000 && address < 0x40000) 101 + return 0x8000010600000000 | address; 102 + else 103 + return 0x8000030000000000 | address; 104 + } 105 + 106 + void WriteHypervisor(uint32_t hv_address, void *userland_data, size_t length) 107 + { 108 + // get the hypervisor address to patch 109 + uint64_t hv_target = GetHVTargetAddress(hv_address); 110 + // copy the data to write into physical memory 111 + uint8_t *data_buf = (uint8_t *)XPhysicalAlloc(0x1000, MAXULONG_PTR, 0, PAGE_READWRITE); 112 + uint64_t data_addr = 0x8000000000000000 | MmGetPhysicalAddress(data_buf); 113 + memcpy(data_buf, userland_data, length); 114 + // decide which syscall to use 115 + if (use_freeboot_syscall) 116 + { 117 + HvxGetVersions(0x72627472, 5, data_addr, hv_target, length); 118 + } 119 + else 120 + { 121 + // allocate a buffer for our freeboot memcpy 122 + uint8_t *shellcode_buf = (uint8_t *)XPhysicalAlloc(0x1000, MAXULONG_PTR, 0, PAGE_READWRITE); 123 + uint64_t shellcode_addr = 0x8000000000000000 | MmGetPhysicalAddress(shellcode_buf); 124 + memcpy(shellcode_buf, freeboot_memcpy_bytecode, sizeof(freeboot_memcpy_bytecode)); 125 + // patch the freeboot memcpy to always have r4 as memcpy (5) and turn the beq after to a b 126 + *(uint32_t *)(shellcode_buf + 0x8) = LI(4, 5); 127 + *(uint16_t *)(shellcode_buf + 0xC) = 0x4800; 128 + // use the hvxpostoutput backdoor to perform the memcpy 129 + HvxPostOutputMemcpy(0x72627472, shellcode_addr, data_addr, hv_target, length); 130 + XPhysicalFree(shellcode_buf); 131 + } 132 + XPhysicalFree(data_buf); 133 + } 134 + 135 + void WriteHypervisorUInt64_RMCI(uint32_t address, uint64_t value) 136 + { 137 + uint64_t hv_target = GetHVTargetAddress(address); 138 + // allocate a buffer for our write 139 + uint8_t *shellcode_buf = (uint8_t *)XPhysicalAlloc(0x1000, MAXULONG_PTR, 0, PAGE_READWRITE); 140 + uint64_t shellcode_addr = 0x8000000000000000 | MmGetPhysicalAddress(shellcode_buf); 141 + memcpy(shellcode_buf, rmci_write_std_bytecode, sizeof(rmci_write_std_bytecode)); 142 + // use the hvxpostoutput backdoor to perform the memcpy 143 + HvxPostOutputRMCIWrite(0x72627472, shellcode_addr, hv_target, value); 144 + XPhysicalFree(shellcode_buf); 145 + } 146 + 147 + void WriteHypervisorUInt32_RMCI(uint32_t address, uint32_t value) 148 + { 149 + uint64_t hv_target = GetHVTargetAddress(address); 150 + // allocate a buffer for our write 151 + uint8_t *shellcode_buf = (uint8_t *)XPhysicalAlloc(0x1000, MAXULONG_PTR, 0, PAGE_READWRITE); 152 + uint64_t shellcode_addr = 0x8000000000000000 | MmGetPhysicalAddress(shellcode_buf); 153 + memcpy(shellcode_buf, rmci_write_stw_bytecode, sizeof(rmci_write_stw_bytecode)); 154 + // use the hvxpostoutput backdoor to perform the memcpy 155 + HvxPostOutputRMCIWrite(0x72627472, shellcode_addr, hv_target, value); 156 + XPhysicalFree(shellcode_buf); 157 + } 158 + 159 + void HypervisorClearCache(uint32_t address) 160 + { 161 + uint64_t hv_target = GetHVTargetAddress(address); 162 + // allocate a buffer for our write 163 + uint8_t *shellcode_buf = (uint8_t *)XPhysicalAlloc(0x1000, MAXULONG_PTR, 0, PAGE_READWRITE); 164 + uint64_t shellcode_addr = 0x8000000000000000 | MmGetPhysicalAddress(shellcode_buf); 165 + memcpy(shellcode_buf, icbi_bytecode, sizeof(icbi_bytecode)); 166 + // use the hvxpostoutput backdoor to perform the memcpy 167 + HvxPostOutputIcbi(0x72627472, shellcode_addr, hv_target); 168 + XPhysicalFree(shellcode_buf); 169 + } 170 + 171 + void ReadHypervisor(void *userland_data, uint32_t hv_address, size_t length) 172 + { 173 + // get the hypervisor address to patch 174 + uint64_t hv_target = GetHVTargetAddress(hv_address); 175 + // allocate some physical memory for the memcpy to copy to 176 + uint8_t *data_buf = (uint8_t *)XPhysicalAlloc(0x1000, MAXULONG_PTR, 0, PAGE_READWRITE); 177 + uint64_t data_addr = 0x8000000000000000 | MmGetPhysicalAddress(data_buf); 178 + // decide which syscall to use 179 + if (use_freeboot_syscall) 180 + { 181 + HvxGetVersions(0x72627472, 5, hv_target, data_addr, length); 182 + } 183 + else 184 + { 185 + // allocate a buffer for our freeboot memcpy 186 + uint8_t *shellcode_buf = (uint8_t *)XPhysicalAlloc(0x1000, MAXULONG_PTR, 0, PAGE_READWRITE); 187 + uint64_t shellcode_addr = 0x8000000000000000 | MmGetPhysicalAddress(shellcode_buf); 188 + memcpy(shellcode_buf, freeboot_memcpy_bytecode, sizeof(freeboot_memcpy_bytecode)); 189 + // patch the freeboot memcpy to always have r4 as memcpy (5) and turn the beq after to a b 190 + *(uint32_t *)(shellcode_buf + 0x8) = LI(4, 5); 191 + *(uint16_t *)(shellcode_buf + 0xC) = 0x4800; 192 + // use the hvxpostoutput backdoor to perform the memcpy 193 + HvxPostOutputMemcpy(0x72627472, shellcode_addr, hv_target, data_addr, length); 194 + XPhysicalFree(shellcode_buf); 195 + } 196 + memcpy(userland_data, data_buf, length); 197 + XPhysicalFree(data_buf); 198 + } 199 + 200 + void WriteHypervisorUInt32(uint32_t hv_address, uint32_t value) 201 + { 202 + uint32_t val = value; 203 + WriteHypervisor(hv_address, &val, sizeof(uint32_t)); 204 + } 205 + 206 + void WriteHypervisorUInt64(uint32_t hv_address, uint64_t value) 207 + { 208 + uint64_t val = value; 209 + WriteHypervisor(hv_address, &val, sizeof(uint64_t)); 210 + }
+10
xex.xml
··· 1 + <?xml version="1.0"?> 2 + <xex> 3 + <format> 4 + <compressed/> 5 + </format> 6 + <mediatypes> 7 + <allpackages/> 8 + </mediatypes> 9 + <titleid id="0xFFFE07D1"/> 10 + </xex>