+9
.gitignore
+9
.gitignore
+19
.vscode/c_cpp_properties.json
+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
+6
.vscode/settings.json
+67
Makefile
+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
+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
+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
+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
+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
+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
+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
+
}