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

freeboot backdoor "memcpy then execute" support

Changed files
+65 -2
include
source
+1
include/hv_funcs.h
··· 11 11 void WriteHypervisorUInt64(uint32_t hv_address, uint64_t value); 12 12 void WriteHypervisorUInt32_RMCI(uint32_t address, uint32_t value); 13 13 void WriteHypervisorUInt64_RMCI(uint32_t address, uint64_t value); 14 + void HypervisorExecute(uint64_t address, void *code, size_t length);
+1
include/xboxkrnl.h
··· 6 6 extern void XapiThreadStartup(void (__cdecl *StartRoutine)(void *), void * StartContext); 7 7 extern unsigned int XexGetModuleHandle(PCSTR moduleName, PHANDLE hand); 8 8 extern unsigned int XexGetProcedureAddress(HANDLE hand, DWORD dwOrdinal, PVOID Address); 9 + extern unsigned int XexLoadImage(LPCSTR szXexName, DWORD dwModuleTypeFlags, DWORD dwMinimumVersion, PHANDLE pHandle);
+41 -2
source/FreeMyXe.c
··· 42 42 0x38, 0x80, 0x00, 0x07, 0x7C, 0x21, 0x20, 0x78, 0x7C, 0x35, 0xEB, 0xA6, 0x48, 0x00, 0x11, 0xC2 43 43 }; 44 44 45 + // this doesn't work! 46 + void ApplyXeBuildPatches(uint8_t *patch_data) 47 + { 48 + uint32_t *patches = (uint32_t *)patch_data; 49 + while (1) 50 + { 51 + uint32_t length; 52 + size_t size; 53 + int i = 0; 54 + // get the address - if it's 0xFFFFFFFF we've hit the end 55 + uint32_t address = patches[0]; 56 + if (address == 0xFFFFFFFF) 57 + break; 58 + // get the length and byte size of the patch 59 + length = patches[1]; 60 + size = length * sizeof(uint32_t); 61 + patches += 2; 62 + // print info 63 + DbgPrint("0x%08x: 0x%x words (0x%x bytes)\n", address, length, size); 64 + for (i = 0; i < length; i++) 65 + { 66 + if (address > 0x40000) 67 + { 68 + // this isn't correct - the whole system locks up 69 + uint64_t val = (*(uint64_t *)(0x80000000 | (address - 4)) & 0xFFFFFFFF00000000) | patches[i]; 70 + WriteHypervisorUInt64_RMCI(address, val); 71 + } 72 + else 73 + { 74 + WriteHypervisorUInt32(address, patches[i]); 75 + } 76 + } 77 + patches += length; 78 + } 79 + } 80 + 45 81 void __cdecl main() 46 82 { 47 83 uint8_t cpu_key[0x10]; ··· 75 111 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 112 MessageBox(dialog_text_buffer); 77 113 114 + // launch xell 115 + //HypervisorExecute(0x800000001c040000, xell2f, sizeof(xell2f)); 116 + 78 117 DbgPrint("Writing syscall 0 backdoor...\n"); 79 118 // install the syscall 0 backdoor at a spare place in memory 80 119 WriteHypervisor(0x0000B564, freeboot_memcpy_bytecode, sizeof(freeboot_memcpy_bytecode)); ··· 84 123 DbgPrint("Writing memory protection patches...\n"); 85 124 // write the patched memory protection instructions 86 125 WriteHypervisor(0x0000154C, memory_protection_bytecode, sizeof(memory_protection_bytecode)); 87 - // jump to the above shellcode 126 + // jump to the above shellcode 88 127 WriteHypervisorUInt32(0x000011BC, 0x4800154E); 89 128 HypervisorClearCache(0x0000154C); 90 129 ··· 150 189 WriteHypervisorUInt64_RMCI(MmGetPhysicalAddress(pdwFunction), valTo); 151 190 HypervisorClearCache(MmGetPhysicalAddress(pdwFunction)); 152 191 } 153 - 192 + 154 193 DbgPrint("Done\n"); 155 194 156 195 Sleep(500);
+22
source/hv_funcs.c
··· 144 144 XPhysicalFree(shellcode_buf); 145 145 } 146 146 147 + void HypervisorExecute(uint64_t address, void *code, size_t length) 148 + { 149 + uint64_t hv_target = GetHVTargetAddress(address); 150 + // allocate a buffer for our write 151 + uint8_t *payload_buf = (uint8_t *)XPhysicalAlloc(0x40000, MAXULONG_PTR, 0, PAGE_READWRITE); 152 + uint64_t payload_addr = 0x8000000000000000 | MmGetPhysicalAddress(payload_buf); 153 + memcpy(payload_buf, code, length); 154 + { 155 + // allocate a buffer for our freeboot memcpy 156 + uint8_t *shellcode_buf = (uint8_t *)XPhysicalAlloc(0x1000, MAXULONG_PTR, 0, PAGE_READWRITE); 157 + uint64_t shellcode_addr = 0x8000000000000000 | MmGetPhysicalAddress(shellcode_buf); 158 + memcpy(shellcode_buf, freeboot_memcpy_bytecode, sizeof(freeboot_memcpy_bytecode)); 159 + // patch the freeboot memcpy to always have r4 as hv execute (4) and turn the beq after to a b 160 + *(uint32_t *)(shellcode_buf + 0x8) = LI(4, 4); 161 + *(uint16_t *)(shellcode_buf + 0xC) = 0x4800; 162 + // use the hvxpostoutput backdoor to perform the memcpy 163 + HvxPostOutputMemcpy(0x72627472, shellcode_addr, address, payload_addr, 0x40000); 164 + XPhysicalFree(shellcode_buf); 165 + } 166 + XPhysicalFree(payload_buf); 167 + } 168 + 147 169 void WriteHypervisorUInt32_RMCI(uint32_t address, uint32_t value) 148 170 { 149 171 uint64_t hv_target = GetHVTargetAddress(address);