Skip to content

Instantly share code, notes, and snippets.

Hacking the SX Core modchip

Background

On October 2nd 2020, CVE-2020-15808 was publicly announced, detailing an out-of-bounds memory read/write vulnerability in STM's microcontroller firmware. Any chip containing STM's USB CDC driver library contains the bugged code, which represents a large amount of products on the market. While bugged STM libraries may be bad enough, this problem is much more widespread. Several companies manufacture "clones" of STM chips which, due to mostly identical MMIO (Memory Mapped Input/Output) addresses, fully support the affected STM vendor code. Most clone manufacturers don't offer their own libraries, so developers must either write their own from scratch, or they can use the STM's existing libraries, and most clone manufacturers encourage this.

Armed with this information, I became interested in exploiting and dumping the flash on the "Team Xecuter" SX Core modchip for the Nintendo Switch. The MCU used on the ch

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
typedef struct __attribute__((packed)) uf2_block
#include <string.h>
#include <stdio.h>
#include <switch.h>
#define FUSE_PHYS_ADDR 0x7000F800
#define FUSE_ARRAY_SIZE 0x100
#define FUSE_CTRL ((*(volatile u32 *)fuse_virt_addr))
#define FUSE_REG_ADDR ((*(volatile u32 *)(fuse_virt_addr + 4)))
#define FUSE_REG_READ ((*(volatile u32 *)(fuse_virt_addr + 8)))
int32_t verify_cert_chain(int **certificate_chain,int type)
{
int32_t iVar1;
int iVar2;
char *type_str;
int **ppiVar3;
type_str = "XS";
if (type == 0x2) {
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
.n64 ; Set the architecture to N64
.open "00200f70.sta",0x807C0000 ; set the RAM address this file will be loaded to to 0x807C0000
start:
li $v0, 0xF82ED0AE ; set up out of range SKC 0xF82ED0AE. SK will use a flawed signed compare to be sure this is within the SKC table bounds.
; SK will check the bottom 5 bits, which, when a 1 is shifted left by the amount in the bottom 5 bits, has to correspond to a bit in the allowed SKC bitmask, or the call fails.
; then it does func_ptr = skc_num * 4 + 0x9FC0BDB0 (0x9FC0BDB0 being the skc func ptr table address) for a final result of 0x807C0068.
; The function pointer will be read from there.
li $t0, 0xA4300014
lw $t1, 0($t0)
.n64 ; Set the architecture to N64
.open "00200f70.sta",0x807C0000
start:
lui $v0, 0xF82E
ori $v0, $v0, 0xD0AE
lui $t0, 0xA430
ori $t0, $t0, 0x0014
lw $t1, 0($t0)
nop
.n64 ; Set the architecture to N64
.open "00200f70.sta",0x807C0000
start:
lui $v0, 0xF82E
ori $v0, $v0, 0xD0AE ; set up out of range SKC 0xF82ED0AE. SK will use a flawed signed compare to be sure this is within the SKC table bounds.
; SK will check the bottom 5 bits, which when shifted left have to correspond to a bit in the allowed SKC bitmask, or the call fails.
; then it does func_ptr = skc_num * 4 + 0x9FC0BDB0 (0x9FC0BDB0 being the skc func ptr table address) for a final result of 0x807C0068.
; The function pointer will be read from there.
lui $t0, 0xA430
RAM:9FC00534 skc_handler: # DATA XREF: sub_9FC00470+94↑o
RAM:9FC00534 # sub_BFC00470+94↓o
RAM:9FC00534
RAM:9FC00534 arg_18 = 0x18
RAM:9FC00534 arg_90 = 0x90
RAM:9FC00534 arg_98 = 0x98
RAM:9FC00534 arg_A0 = 0xA0
RAM:9FC00534 arg_A8 = 0xA8
RAM:9FC00534 arg_B0 = 0xB0
RAM:9FC00534 arg_B8 = 0xB8
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>