Address review comments

- all local vars to camelcase
- header include guards with lib name
- comments for preprocessor directives
- asm defs back to respective .inc files
- /lib/dsprot/tools/ merged to /tools/
- unprefixed globals prefixed
- sdk defs consolidated to sdk include
- lsf lib split to objects
This commit is contained in:
taxicat1 2025-11-09 02:59:34 -05:00
parent 6ed1d7eb09
commit 008118b6b3
54 changed files with 646 additions and 603 deletions

View File

@ -26,7 +26,7 @@ BANNER_SPEC := $(buildname)/banner.bsf
ICON_PNG := $(buildname)/icon.png
HEADER_TEMPLATE := $(buildname)/rom_header_template.sbin
.PHONY: main sub libsyscall sdk sdk9 sdk7
.PHONY: main sub dsprot libsyscall sdk sdk9 sdk7
.PRECIOUS: $(ROM)
MAKEFLAGS += --no-print-directory

View File

@ -213,3 +213,7 @@
.public ov01_02208BFC
.public ov02_0224F864
.public ov02_0224F8F4
.public DSProt_DetectFlashcart
.public DSProt_DetectDummy
.public DSProt_DetectNotFlashcart
.public DSProt_DetectNotEmulator

View File

@ -292,3 +292,6 @@
.public ov18_021F89D0
.public ov18_021F95AC
.public ov18_021F95F8
.public DSProt_DetectFlashcart
.public DSProt_DetectEmulator
.public DSProt_DetectNotDummy

View File

@ -164,3 +164,6 @@
.public ov27_0225C398
.public ov27_0225C418
.public ov27_0225C41C
.public DSProt_DetectFlashcart
.public DSProt_DetectNotEmulator
.public DSProt_DetectNotDummy

View File

@ -8,7 +8,6 @@
#include "constants/items.h"
#include "msgdata/msg/msg_0096_D31R0201.h"
#include "msgdata/msg/msg_0066_D23R0102.h"
#include "dsprot.h"
.include "asm/macros.inc"
.include "overlay_01_021E5900.inc"
.include "global.inc"

View File

@ -1,4 +1,3 @@
#include "dsprot.h"
.include "asm/macros.inc"
.include "overlay_18.inc"
.include "global.inc"

View File

@ -1,4 +1,3 @@
#include "dsprot.h"
.include "asm/macros.inc"
.include "overlay_27.inc"
.include "global.inc"

View File

@ -53,6 +53,7 @@ MSGENC := $(TOOLSDIR)/msgenc/msgenc$(EXE)
ASPATCH := $(TOOLSDIR)/mwasmarm_patcher/mwasmarm_patcher$(EXE)
CSV2BIN := $(TOOLSDIR)/csv2bin/csv2bin$(EXE)
MKFXCONST := $(TOOLSDIR)/gen_fx_consts/gen_fx_consts$(EXE)
ELFCODER := $(TOOLSDIR)/elfcoder/elfcoder$(EXE)
# Decompiled NitroSDK tools
COMPSTATIC := $(TOOLSDIR)/compstatic/compstatic$(EXE)
@ -70,7 +71,8 @@ NATIVE_TOOLS := \
$(ASPATCH) \
$(CSV2BIN) \
$(MKFXCONST) \
$(COMPSTATIC)
$(COMPSTATIC) \
$(ELFCODER)
TOOLDIRS := $(foreach tool,$(NATIVE_TOOLS),$(dir $(tool)))

View File

@ -1,8 +1 @@
**/build/**
tools/mwccarm/**
*.exe
*.dll
*.o
*.so
*.a
*.d

View File

@ -2,44 +2,36 @@
# See doc/BUILD_OVERVIEW.TXT for a clearer outline of this build process
# ===================================================================
MAKEFLAGS += --no-print-directory
# Need GLB_DEFINES and CLI_DEFINES from config
include ../../config.mk
# Undef this from config.mk so common.mk knows this is not building a linked elf
ELFNAME :=
MWCCVER := 2.0/sp2p3
# Relevant directories
BUILD_DIR := ./build
C_OBJ_DIR := $(BUILD_DIR)/src
SRC_DIR := ./src
INC_DIR := ./include
TOOL_DIR := ./tools
BUILD_DIR := ./build
C_OBJ_DIR := $(BUILD_DIR)/src
SRC_DIR := ./src
INC_DIR := ./include
SYSINC_DIR := ../include
include ../../common.mk
ifeq ($(NODEP),)
DEP_PARAM := -gccdep -MD
include $(wildcard $(C_OBJ_DIR)/*.d)
else
DEP_PARAM :=
endif
INSTALL_PREFIX ?= ./install
INSTALL_LIBDIR := $(INSTALL_PREFIX)/lib
ELFCODER_DIR := $(TOOL_DIR)/elfcoder
# Tools
ELFCODER := $(ELFCODER_DIR)/build/elfcoder$(EXE)
INSTALL_LIBDIR := $(INSTALL_PREFIX)/lib/dsprot
# C / ASM compilation parameters
CC_PARAM := -O4,p -enum int -proc arm946E -gccext,on -fp soft -lang c99 -char signed -inline on,noauto -Cpp_exceptions off -interworking -i $(INC_DIR) -c
ASM_PARAM := -proc arm5TE -i $(INC_DIR)
LIB_PARAM := -nostdlib -library
CC_PARAM := -O4,p -enum int -proc arm946E -gccext,on -fp soft -lang c99 -char signed -inline on,noauto -Cpp_exceptions off -interworking -gccinc -i $(INC_DIR) -I$(SYSINC_DIR) -c $(GLB_DEFINES) $(CLI_DEFINES)
CC_PARAM += -W all -W pedantic -W noimpl_signedunsigned -W noimplicitconv -W nounusedarg -W nomissingreturn -W error
# Output library file
LIBRARY_NAME := dsprot.a
LIBRARY := $(BUILD_DIR)/$(LIBRARY_NAME)
ASM_PARAM := -proc arm5TE -i $(INC_DIR)
# Files (in this specific order) that will go into the library
LIBRARY_FILES := \
@ -62,36 +54,24 @@ LIBRARY_FILES := \
$(BUILD_DIR)/rc4_encoded.o \
$(BUILD_DIR)/rc4_decoder.o
# Encryption keys
KEY_DSPROT_MAIN := 6AB2
KEY_INTEGRITY := 9785
KEY_CORE_TESTS := 0982
.PHONY: all clean tidy tools dsprot install
.DELETE_ON_ERROR:
.NOTPARALLEL:
.SECONDARY: none
all:
$(MAKE) tools
$(MAKE) dsprot
all: dsprot
clean:
$(MAKE) -C $(ELFCODER_DIR) clean
$(RM) -r $(BUILD_DIR)
tidy: clean
tools:
$(MAKE) -C $(ELFCODER_DIR)
dsprot: $(LIBRARY_FILES)
dsprot:
$(MAKE) $(LIBRARY)
install:
$(MAKE) all
install: all
$(shell mkdir -p $(INSTALL_LIBDIR))
cp $(LIBRARY) $(INSTALL_LIBDIR)
cp $(LIBRARY_FILES) $(INSTALL_LIBDIR)
# Assembly assembling
@ -105,65 +85,101 @@ $(C_OBJ_DIR)/%.o: $(SRC_DIR)/%.c
@$(call fixdep,$(@:.o=.d))
# Library output
$(LIBRARY): $(LIBRARY_FILES)
$(WINE) $(MWLD) $(LIB_PARAM) $^ -o $@
# Main module function encoding
KEY_DSPROT_MAIN := 6AB2
DSPROT_MAIN_ENCRYPTION_REPLACE_PREFIX := DSProtInternal_
DSPROT_MAIN_ENCRYPTION_PREFIX := DSProt_
DSPROT_MAIN_ENCRYPTED_FUNCTIONS := \
DSProtInternal_DetectFlashcart \
DSProtInternal_DetectNotFlashcart \
DSProtInternal_DetectEmulator \
DSProtInternal_DetectNotEmulator \
DSProtInternal_DetectDummy \
DSProtInternal_DetectNotDummy
DSPROT_MAIN_ADDED_REF := DSProt_Garbage
DSPROT_MAIN_ENCODED_FUNCTIONS := \
DSProt_DetectFlashcart \
DSProt_DetectNotFlashcart \
DSProt_DetectEmulator \
DSProt_DetectNotEmulator \
DSProt_DetectDummy \
DSProt_DetectNotDummy
$(BUILD_DIR)/dsprot_main_decrypter_encoded.o \
$(BUILD_DIR)/dsprot_main_decrypter_decoder.s: $(BUILD_DIR)/dsprot_main_decrypter.o $(ELFCODER)
cp $(BUILD_DIR)/dsprot_main_decrypter.o $(BUILD_DIR)/dsprot_main_decrypter_encoded.o
$(ELFCODER) -e -i $(BUILD_DIR)/dsprot_main_decrypter_encoded.o -o $(BUILD_DIR)/dsprot_main_decrypter_decoder.s -g Garbage -f \
DSProt_DetectFlashcart \
DSProt_DetectNotFlashcart \
DSProt_DetectEmulator \
DSProt_DetectNotEmulator \
DSProt_DetectDummy \
DSProt_DetectNotDummy
$(ELFCODER) -e -i $(BUILD_DIR)/dsprot_main_decrypter_encoded.o -o $(BUILD_DIR)/dsprot_main_decrypter_decoder.s -g $(DSPROT_MAIN_ADDED_REF) -f $(DSPROT_MAIN_ENCODED_FUNCTIONS)
$(BUILD_DIR)/dsprot_main_encrypted.o \
$(BUILD_DIR)/dsprot_main_decrypter.s: $(C_OBJ_DIR)/dsprot_main.o $(ELFCODER)
cp $(C_OBJ_DIR)/dsprot_main.o $(BUILD_DIR)/dsprot_main_encrypted.o
$(ELFCODER) -e -i $(BUILD_DIR)/dsprot_main_encrypted.o -o $(BUILD_DIR)/dsprot_main_decrypter.s -k $(KEY_DSPROT_MAIN) -p DSProt_ -f \
DetectFlashcart \
DetectNotFlashcart \
DetectEmulator \
DetectNotEmulator \
DetectDummy \
DetectNotDummy
$(ELFCODER) -e -i $(BUILD_DIR)/dsprot_main_encrypted.o -o $(BUILD_DIR)/dsprot_main_decrypter.s -k $(KEY_DSPROT_MAIN) -p $(DSPROT_MAIN_ENCRYPTION_PREFIX) -r $(DSPROT_MAIN_ENCRYPTION_REPLACE_PREFIX) -f $(DSPROT_MAIN_ENCRYPTED_FUNCTIONS)
# Integrity module function encoding
KEY_INTEGRITY := 9785
# Default prefix (RunEncrypted_)
INTEGRITY_ENCRYPTED_FUNCTIONS := \
Integrity_MACOwner_IsBad \
Integrity_MACOwner_IsGood \
Integrity_ROMTest_IsBad \
Integrity_ROMTest_IsGood
INTEGRITY_ENCODED_FUNCTIONS := \
RunEncrypted_Integrity_MACOwner_IsBad \
RunEncrypted_Integrity_MACOwner_IsGood \
RunEncrypted_Integrity_ROMTest_IsBad \
RunEncrypted_Integrity_ROMTest_IsGood
$(BUILD_DIR)/integrity_decrypter_encoded.o \
$(BUILD_DIR)/integrity_decrypter_decoder.s: $(BUILD_DIR)/integrity_decrypter.o $(ELFCODER)
cp $(BUILD_DIR)/integrity_decrypter.o $(BUILD_DIR)/integrity_decrypter_encoded.o
$(ELFCODER) -e -i $(BUILD_DIR)/integrity_decrypter_encoded.o -o $(BUILD_DIR)/integrity_decrypter_decoder.s -f \
RunEncrypted_Integrity_MACOwner_IsBad \
RunEncrypted_Integrity_MACOwner_IsGood \
RunEncrypted_Integrity_ROMTest_IsBad \
RunEncrypted_Integrity_ROMTest_IsGood
$(ELFCODER) -e -i $(BUILD_DIR)/integrity_decrypter_encoded.o -o $(BUILD_DIR)/integrity_decrypter_decoder.s -f $(INTEGRITY_ENCODED_FUNCTIONS)
$(BUILD_DIR)/integrity_encrypted.o \
$(BUILD_DIR)/integrity_decrypter.s: $(C_OBJ_DIR)/integrity.o $(ELFCODER)
cp $(C_OBJ_DIR)/integrity.o $(BUILD_DIR)/integrity_encrypted.o
$(ELFCODER) -e -i $(BUILD_DIR)/integrity_encrypted.o -o $(BUILD_DIR)/integrity_decrypter.s -k $(KEY_INTEGRITY) -f \
Integrity_MACOwner_IsBad \
Integrity_MACOwner_IsGood \
Integrity_ROMTest_IsBad \
Integrity_ROMTest_IsGood
$(ELFCODER) -e -i $(BUILD_DIR)/integrity_encrypted.o -o $(BUILD_DIR)/integrity_decrypter.s -k $(KEY_INTEGRITY) -f $(INTEGRITY_ENCRYPTED_FUNCTIONS)
# Encryptor module function encoding
ENCRYPTOR_ENCODED_FUNCTIONS := \
Encryptor_EncryptFunction \
Encryptor_DecryptFunction
$(BUILD_DIR)/encryptor_encoded.o \
$(BUILD_DIR)/encryptor_decoder.s: $(C_OBJ_DIR)/encryptor.o $(ELFCODER)
cp $(C_OBJ_DIR)/encryptor.o $(BUILD_DIR)/encryptor_encoded.o
$(ELFCODER) -e -i $(BUILD_DIR)/encryptor_encoded.o -o $(BUILD_DIR)/encryptor_decoder.s -f \
Encryptor_EncryptFunction \
Encryptor_DecryptFunction
$(ELFCODER) -e -i $(BUILD_DIR)/encryptor_encoded.o -o $(BUILD_DIR)/encryptor_decoder.s -f $(ENCRYPTOR_ENCODED_FUNCTIONS)
# Core tests module: MAC/Owner, ROM utilities, ROM tests function encoding
KEY_CORE_TESTS := 0982
# Default prefix (RunEncrypted_)
MACOWNER_ENCRYPTED_FUNCTIONS := \
MACOwner_IsBad \
MACOwner_IsGood
ROMUTIL_ENCRYPTED_FUNCTIONS := \
ROMUtil_Read \
ROMUtil_CRC32
ROMTEST_ENCRYPTED_FUNCTIONS := \
ROMTest_IsBad \
ROMTest_IsGood
CORETESTS_ENCODED_FUNCTIONS := \
RunEncrypted_ROMTest_IsBad \
RunEncrypted_ROMTest_IsGood \
RunEncrypted_MACOwner_IsBad \
RunEncrypted_MACOwner_IsGood \
RunEncrypted_ROMUtil_Read \
RunEncrypted_ROMUtil_CRC32
$(BUILD_DIR)/mac_owner_decrypter_encoded.o \
$(BUILD_DIR)/rom_util_decrypter_encoded.o \
$(BUILD_DIR)/rom_test_decrypter_encoded.o \
@ -171,45 +187,35 @@ $(BUILD_DIR)/coretests_decrypter_decoder.s: $(BUILD_DIR)/mac_owner_decrypter.o $
cp $(BUILD_DIR)/mac_owner_decrypter.o $(BUILD_DIR)/mac_owner_decrypter_encoded.o
cp $(BUILD_DIR)/rom_util_decrypter.o $(BUILD_DIR)/rom_util_decrypter_encoded.o
cp $(BUILD_DIR)/rom_test_decrypter.o $(BUILD_DIR)/rom_test_decrypter_encoded.o
$(ELFCODER) -e -i $(BUILD_DIR)/mac_owner_decrypter_encoded.o $(BUILD_DIR)/rom_util_decrypter_encoded.o $(BUILD_DIR)/rom_test_decrypter_encoded.o -o $(BUILD_DIR)/coretests_decrypter_decoder.s -f \
RunEncrypted_ROMTest_IsBad \
RunEncrypted_ROMTest_IsGood \
RunEncrypted_MACOwner_IsBad \
RunEncrypted_MACOwner_IsGood \
RunEncrypted_ROMUtil_Read \
RunEncrypted_ROMUtil_CRC32
$(ELFCODER) -e -i $(BUILD_DIR)/mac_owner_decrypter_encoded.o $(BUILD_DIR)/rom_util_decrypter_encoded.o $(BUILD_DIR)/rom_test_decrypter_encoded.o -o $(BUILD_DIR)/coretests_decrypter_decoder.s -f $(CORETESTS_ENCODED_FUNCTIONS)
$(BUILD_DIR)/mac_owner_encrypted.o \
$(BUILD_DIR)/mac_owner_decrypter.s: $(C_OBJ_DIR)/mac_owner.o $(ELFCODER)
cp $(C_OBJ_DIR)/mac_owner.o $(BUILD_DIR)/mac_owner_encrypted.o
$(ELFCODER) -e -i $(BUILD_DIR)/mac_owner_encrypted.o -o $(BUILD_DIR)/mac_owner_decrypter.s -k $(KEY_CORE_TESTS) -f \
MACOwner_IsBad \
MACOwner_IsGood
$(ELFCODER) -e -i $(BUILD_DIR)/mac_owner_encrypted.o -o $(BUILD_DIR)/mac_owner_decrypter.s -k $(KEY_CORE_TESTS) -f $(MACOWNER_ENCRYPTED_FUNCTIONS)
$(BUILD_DIR)/rom_util_encrypted.o \
$(BUILD_DIR)/rom_util_decrypter.s: $(C_OBJ_DIR)/rom_util.o $(ELFCODER)
cp $(C_OBJ_DIR)/rom_util.o $(BUILD_DIR)/rom_util_encrypted.o
$(ELFCODER) -e -i $(BUILD_DIR)/rom_util_encrypted.o -o $(BUILD_DIR)/rom_util_decrypter.s -k $(KEY_CORE_TESTS) -f \
ROMUtil_Read \
ROMUtil_CRC32
$(ELFCODER) -e -i $(BUILD_DIR)/rom_util_encrypted.o -o $(BUILD_DIR)/rom_util_decrypter.s -k $(KEY_CORE_TESTS) -f $(ROMUTIL_ENCRYPTED_FUNCTIONS)
$(BUILD_DIR)/rom_test_encrypted.o \
$(BUILD_DIR)/rom_test_decrypter.s: $(C_OBJ_DIR)/rom_test.o $(ELFCODER)
cp $(C_OBJ_DIR)/rom_test.o $(BUILD_DIR)/rom_test_encrypted.o
$(ELFCODER) -e -i $(BUILD_DIR)/rom_test_encrypted.o -o $(BUILD_DIR)/rom_test_decrypter.s -k $(KEY_CORE_TESTS) -f \
ROMTest_IsBad \
ROMTest_IsGood
$(ELFCODER) -e -i $(BUILD_DIR)/rom_test_encrypted.o -o $(BUILD_DIR)/rom_test_decrypter.s -k $(KEY_CORE_TESTS) -f $(ROMTEST_ENCRYPTED_FUNCTIONS)
# RC4 module function encoding
RC4_ENCODED_FUNCTIONS := \
RC4_Init \
RC4_Byte \
RC4_InitSBox \
RC4_EncryptInstructions \
RC4_DecryptInstructions \
RC4_InitAndEncryptInstructions \
RC4_InitAndDecryptInstructions
$(BUILD_DIR)/rc4_encoded.o \
$(BUILD_DIR)/rc4_decoder.s: $(C_OBJ_DIR)/rc4.o $(ELFCODER)
cp $(C_OBJ_DIR)/rc4.o $(BUILD_DIR)/rc4_encoded.o
$(ELFCODER) -e -i $(BUILD_DIR)/rc4_encoded.o -o $(BUILD_DIR)/rc4_decoder.s -f \
RC4_Init \
RC4_Byte \
RC4_InitSBox \
RC4_EncryptInstructions \
RC4_DecryptInstructions \
RC4_InitAndEncryptInstructions \
RC4_InitAndDecryptInstructions
$(ELFCODER) -e -i $(BUILD_DIR)/rc4_encoded.o -o $(BUILD_DIR)/rc4_decoder.s -f $(RC4_ENCODED_FUNCTIONS)

View File

@ -1,19 +1,19 @@
Module 1 (main):
Functions:
DetectFlashcart
DetectNotFlashcart
DetectEmulator
DetectNotEmulator
DetectDummy
DetectNotDummy
DSProtInternal_DetectFlashcart
DSProtInternal_DetectNotFlashcart
DSProtInternal_DetectEmulator
DSProtInternal_DetectNotEmulator
DSProtInternal_DetectDummy
DSProtInternal_DetectNotDummy
Encrypt and create decryption wrappers (key=0x6AB2, prefix=DSProt_):
DetectFlashcart
DetectNotFlashcart
DetectEmulator
DetectNotEmulator
DetectDummy
DetectNotDummy
Encrypt and create decryption wrappers (key=0x6AB2, replace_prefix=DSProtInternal_, prefix=DSProt_):
DSProtInternal_DetectFlashcart
DSProtInternal_DetectNotFlashcart
DSProtInternal_DetectEmulator
DSProtInternal_DetectNotEmulator
DSProtInternal_DetectDummy
DSProtInternal_DetectNotDummy
Encode and create decoder function:
DSProt_DetectFlashcart

View File

@ -19,7 +19,15 @@
.endm
.public BSS
.macro sinit sinit_func
.type NitroStaticInit_, @object
NitroStaticInit_:
.word \sinit_func
.size NitroStaticInit_, .-NitroStaticInit_
.endm
.public DSProt_BSS
.public Encryptor_DecryptFunction
.public Encryptor_EncryptFunction
@ -51,11 +59,11 @@
str pc, storage_\@ ; Store `pc` in its place, presumably just to overwrite the return address.
bx lr ; Return with return value from inner function.
storage_\@:
.word BSS + 1
.word DSProt_BSS + 1
length_\@:
.word BSS + \length + ENC_VAL_1
.word DSProt_BSS + \length + ENC_VAL_1
key_\@:
.word BSS + \key + ENC_VAL_1
.word DSProt_BSS + \key + ENC_VAL_1
func_\@:
.word \func + ENC_VAL_1
.endm
@ -71,7 +79,7 @@ func_\@:
.endm
.macro func_table_entry func, size
.word \func + ENC_VAL_1, BSS + \size + ENC_VAL_1
.word \func + ENC_VAL_1, DSProt_BSS + \size + ENC_VAL_1
.endm
.macro func_table_end

View File

@ -1,8 +1,8 @@
#ifndef BSS_H
#define BSS_H
#ifndef DSPROT_BSS_H
#define DSPROT_BSS_H
#include "nitro_types.h"
#include "sdk.h"
extern u8 BSS[4];
extern u8 DSProt_BSS[4];
#endif
#endif // DSPROT_BSS_H

View File

@ -0,0 +1,14 @@
#ifndef DSPROT_MAIN_H
#define DSPROT_MAIN_H
#include "sdk.h"
// Functions to be encrypted (cannot be called directly)
u32 DSProtInternal_DetectFlashcart(void *callback);
u32 DSProtInternal_DetectNotFlashcart(void *callback);
u32 DSProtInternal_DetectEmulator(void *callback);
u32 DSProtInternal_DetectNotEmulator(void *callback);
u32 DSProtInternal_DetectDummy(void *callback);
u32 DSProtInternal_DetectNotDummy(void *callback);
#endif // DSPROT_MAIN_H

View File

@ -1,12 +1,14 @@
#ifndef ENCODING_CONSTANTS_H
#define ENCODING_CONSTANTS_H
#ifndef DSPROT_ENCODING_CONSTANTS_H
#define DSPROT_ENCODING_CONSTANTS_H
#define INS_OPCODE_LINKBIT (0x01)
#define INS_OPCODE_MASK (0xFF000000)
#define INS_OPCODE_SHIFT (24)
#define INS_OPERANDS_MASK (0x00FFFFFF)
#ifndef SDK_ASM
#define ADDR_PLUS_ADDEND(ref, addend) ((u32)(&ref + ((addend) / sizeof(ref))))
#endif // SDK_ASM
#define ENC_VAL_1 (0x1300)
#define ENC_VAL_2 ((ENC_VAL_1 >> 2) + 2)
@ -18,4 +20,4 @@
#define ENC_SBOX_XOR (0x01)
#endif
#endif // DSPROT_ENCODING_CONSTANTS_H

View File

@ -1,23 +1,23 @@
#ifndef ENCRYPTOR_H
#define ENCRYPTOR_H
#ifndef DSPROT_ENCRYPTOR_H
#define DSPROT_ENCRYPTOR_H
#include "nitro_types.h"
#include "sdk.h"
typedef struct {
u32 obfs_addr;
u32 obfs_size;
typedef struct FuncInfo {
u32 obfsAddr;
u32 obfsSize;
} FuncInfo;
enum {
typedef enum InsType {
INS_TYPE_OTHER = 0,
INS_TYPE_BLXIMM,
INS_TYPE_BL,
INS_TYPE_B
};
} InsType;
u32 Encryptor_CategorizeInstruction(u32 instruction);
InsType Encryptor_CategorizeInstruction(u32 instruction);
void Encryptor_DecodeFunctionTable(FuncInfo *functions);
void *Encryptor_DecryptFunction(u32 key, u32 func_addr, u32 size);
u32 Encryptor_EncryptFunction(u32 key, u32 func_addr, u32 size);
void *Encryptor_DecryptFunction(u32 key, u32 funcAddr, u32 size);
u32 Encryptor_EncryptFunction(u32 key, u32 funcAddr, u32 size);
#endif
#endif // DSPROT_ENCRYPTOR_H

View File

@ -1,8 +1,8 @@
#ifndef GARBAGE_H
#define GARBAGE_H
#ifndef DSPROT_GARBAGE_H
#define DSPROT_GARBAGE_H
#include "nitro_types.h"
#include "sdk.h"
extern const u32 Garbage[6];
extern const u32 DSProt_Garbage[6];
#endif
#endif // DSPROT_GARBAGE_H

View File

@ -1,7 +1,13 @@
#ifndef INTEGRITY_H
#define INTEGRITY_H
#ifndef DSPROT_INTEGRITY_H
#define DSPROT_INTEGRITY_H
#include "nitro_types.h"
#include "sdk.h"
// Functions to be encrypted (cannot be called directly)
u32 Integrity_MACOwner_IsBad(void);
u32 Integrity_MACOwner_IsGood(void);
u32 Integrity_ROMTest_IsBad(void);
u32 Integrity_ROMTest_IsGood(void);
// Assembly decryption wrappers
extern u32 RunEncrypted_Integrity_MACOwner_IsBad(void);
@ -9,4 +15,4 @@ extern u32 RunEncrypted_Integrity_MACOwner_IsGood(void);
extern u32 RunEncrypted_Integrity_ROMTest_IsBad(void);
extern u32 RunEncrypted_Integrity_ROMTest_IsGood(void);
#endif
#endif // DSPROT_INTEGRITY_H

View File

@ -1,10 +1,14 @@
#ifndef MAC_OWNER_H
#define MAC_OWNER_H
#ifndef DSPROT_MAC_OWNER_H
#define DSPROT_MAC_OWNER_H
#include "nitro_types.h"
#include "sdk.h"
// Functions to be encrypted (cannot be called directly)
u32 MACOwner_IsBad(void);
u32 MACOwner_IsGood(void);
// Assembly decryption wrappers
extern u32 RunEncrypted_MACOwner_IsBad(void);
extern u32 RunEncrypted_MACOwner_IsGood(void);
#endif
#endif // DSPROT_MAC_OWNER_H

View File

@ -1,24 +0,0 @@
#ifndef NITRO_CARD_H
#define NITRO_CARD_H
#include "nitro_types.h"
// <nitro/card.h>
#define CARD_ROM_PAGE_SIZE (0x200)
extern void CARD_LockRom(u16 lock_id);
extern void CARD_UnlockRom(u16 lock_id);
// Not available in all Nitro versions
#define CARDMST_ENABLE (0x80)
#define CARD_DATA_READY (0x00800000)
#define CARD_COMMAND_PAGE (0x01000000)
#define CARD_COMMAND_MASK (0x07000000)
#define CARD_RESET_HI (0x20000000)
#define CARD_READ_MODE (0x00000000)
#define CARD_START (0x80000000)
#define MROMOP_G_READ_PAGE (0xB7000000)
#endif

View File

@ -1,19 +0,0 @@
#ifndef NITRO_IO_REG_H
#define NITRO_IO_REG_H
#include "nitro_types.h"
// <nitro/hw/io_reg.h>
#define HW_REG_BASE (0x04000000)
#define REG_EXMEMCNT_OFFSET (0x204)
#define reg_MI_EXMEMCNT (*(REGType16v *)(HW_REG_BASE + REG_EXMEMCNT_OFFSET))
#define REG_MI_EXMEMCNT_MP_MASK (0x800)
#define REG_MI_EXMEMCNT_MP_SHIFT (11)
#define REG_A9ROM_OFFSET (0x4000)
#define REG_SCFG_A9ROM_SEC_MASK (0x01)
#define MI_PROCESSOR_ARM9 (0)
#endif

View File

@ -1,27 +0,0 @@
#ifndef NITRO_OS_H
#define NITRO_OS_H
#include "nitro_types.h"
// <nitro/os.h>
typedef struct {
u8 language;
u8 favoriteColor;
struct {
u8 month;
u8 day;
} birthday;
u16 nickName[11];
u16 nickNameLength;
u16 comment[27];
u16 commentLength;
} OSOwnerInfo;
extern s32 OS_GetLockID(void);
extern void OS_ReleaseLockID(u16 lock_id);
extern void OS_GetMacAddress(u8 *mac_addr);
extern void OS_GetOwnerInfo(OSOwnerInfo *info);
extern void DC_FlushRange(const void *start_addr, u32 num_bytes);
extern void IC_InvalidateRange(void *start_addr, u32 num_bytes);
#endif

View File

@ -1,41 +0,0 @@
#ifndef NITRO_TYPES_H
#define NITRO_TYPES_H
// <nitro/types.h>
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned long u32;
typedef unsigned long long int u64;
typedef signed char s8;
typedef signed short int s16;
typedef signed long s32;
typedef signed long long int s64;
typedef float f32;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;
typedef volatile u64 vu64;
typedef volatile s8 vs8;
typedef volatile s16 vs16;
typedef volatile s32 vs32;
typedef volatile s64 vs64;
typedef volatile f32 vf32;
typedef u8 REGType8;
typedef u16 REGType16;
typedef u32 REGType32;
typedef u64 REGType64;
typedef vu8 REGType8v;
typedef vu16 REGType16v;
typedef vu32 REGType32v;
typedef vu64 REGType64v;
typedef int BOOL;
#define TRUE (1)
#define FALSE (0)
#define NULL ((void *)0)
#endif

View File

@ -1,9 +1,20 @@
#ifndef RC4_H
#define RC4_H
#ifndef DSPROT_RC4_H
#define DSPROT_RC4_H
#include "nitro_types.h"
#include "sdk.h"
#define RC4_KEY_SIZE (16)
typedef struct RC4_Ctx RC4_Ctx;
// Functions to be encoded (cannot be static)
void RC4_Init(RC4_Ctx *ctx, const void *key, u32 keyLen);
u8 RC4_Byte(RC4_Ctx *ctx);
u32 RC4_InitSBox(u8 *sbox);
u32 RC4_EncryptInstructions(RC4_Ctx *ctx, void *src, void *dst, u32 size);
u32 RC4_DecryptInstructions(RC4_Ctx *ctx, void *src, void *dst, u32 size);
u32 RC4_InitAndEncryptInstructions(void *key, void *dst, void *src, u32 size);
u32 RC4_InitAndDecryptInstructions(void *key, void *dst, void *src, u32 size);
#endif
#endif // DSPROT_RC4_H

View File

@ -1,10 +1,14 @@
#ifndef ROM_TEST_H
#define ROM_TEST_H
#ifndef DSPROT_ROM_TEST_H
#define DSPROT_ROM_TEST_H
#include "nitro_types.h"
#include "sdk.h"
// Functions to be encrypted (cannot be called directly)
u32 ROMTest_IsBad(void);
u32 ROMTest_IsGood(void);
// Assembly decryption wrappers
extern u32 RunEncrypted_ROMTest_IsBad(void);
extern u32 RunEncrypted_ROMTest_IsGood(void);
#endif
#endif // DSPROT_ROM_TEST_H

View File

@ -1,10 +1,14 @@
#ifndef ROM_UTIL_H
#define ROM_UTIL_H
#ifndef DSPROT_ROM_UTIL_H
#define DSPROT_ROM_UTIL_H
#include "nitro_types.h"
#include "sdk.h"
// Functions to be encrypted (cannot be called directly)
void ROMUtil_Read(void *dest, u32 addr, s32 numBytes);
u32 ROMUtil_CRC32(void *buf, u32 size);
// Assembly decryption wrappers
extern void RunEncrypted_ROMUtil_Read(void *dest, u32 addr, s32 num_bytes);
extern void RunEncrypted_ROMUtil_Read(void *dest, u32 addr, s32 numBytes);
extern u32 RunEncrypted_ROMUtil_CRC32(void *buf, u32 size);
#endif
#endif // DSPROT_ROM_UTIL_H

60
lib/dsprot/include/sdk.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef DSPROT_SDK_H
#define DSPROT_SDK_H
#ifdef SDK_TWL
// Use Twl SDK if available
#include <twl.h>
#else // SDK_TWL
// Else use Nitro and add back in the needed Twl SDK defs
#include <nitro.h>
// Twl SDK only
#ifndef REG_A9ROM_OFFSET
#define REG_A9ROM_OFFSET (0x4000)
#endif // REG_A9ROM_OFFSET
#ifndef REG_SCFG_A9ROM_SEC_MASK
#define REG_SCFG_A9ROM_SEC_MASK (0x01)
#endif // REG_SCFG_A9ROM_SEC_MASK
#endif // SDK_TWL
// Not included in all SDK versions, regardless of Nitro/Twl
// Ensure they are defined
#ifndef CARDMST_ENABLE
#define CARDMST_ENABLE (0x80)
#endif // CARDMST_ENABLE
#ifndef CARD_DATA_READY
#define CARD_DATA_READY (0x00800000)
#endif // CARD_DATA_READY
#ifndef CARD_COMMAND_PAGE
#define CARD_COMMAND_PAGE (0x01000000)
#endif // CARD_COMMAND_PAGE
#ifndef CARD_COMMAND_MASK
#define CARD_COMMAND_MASK (0x07000000)
#endif // CARD_COMMAND_MASK
#ifndef CARD_RESET_HI
#define CARD_RESET_HI (0x20000000)
#endif // CARD_RESET_HI
#ifndef CARD_READ_MODE
#define CARD_READ_MODE (0x00000000)
#endif // CARD_READ_MODE
#ifndef CARD_START
#define CARD_START (0x80000000)
#endif // CARD_START
#ifndef MROMOP_G_READ_PAGE
#define MROMOP_G_READ_PAGE (0xB7000000)
#endif // MROMOP_G_READ_PAGE
#endif // DSPROT_SDK_H

View File

@ -1,19 +1,10 @@
/* No dedicated header */
#include "dsprot_main.h"
#include "encoding_constants.h"
#include "integrity.h"
#include "mac_owner.h"
#include "nitro_types.h"
#include "rom_test.h"
// Functions to be encrypted (cannot be called directly)
u32 DetectFlashcart(void *callback);
u32 DetectNotFlashcart(void *callback);
u32 DetectEmulator(void *callback);
u32 DetectNotEmulator(void *callback);
u32 DetectDummy(void *callback);
u32 DetectNotDummy(void *callback);
#define DSP_OBFS_OFFSET (0x320)
#define FUNC_QUEUE_END (0)
@ -21,33 +12,33 @@ u32 DetectNotDummy(void *callback);
typedef u32 (*TaskFunc)(void);
typedef void (*CallbackFunc)(void);
enum {
typedef enum ExpectedResult {
EXPECT_FALSE,
EXPECT_TRUE
};
} ExpectedResult;
// This was likely not originally an inline, but an inline is able to match here nicely
static inline u32 dsprotMain(u32 *func_queue, int expected_result, void *callback) {
static inline u32 dsprotMain(u32 *funcQueue, ExpectedResult expectedResult, void *callback) {
// These two bit arrays must be signed to match
s32 compare_sum = 0;
s32 compareSum = 0;
u32 i;
s32 func_result_sum = 0;
s32 funcResultSum = 0;
for (i = 0; func_queue[i] != FUNC_QUEUE_END; i++) {
BOOL func_result = ((TaskFunc)(func_queue[i] - ENC_VAL_1 - DSP_OBFS_OFFSET))() != 0;
for (i = 0; funcQueue[i] != FUNC_QUEUE_END; i++) {
BOOL funcResult = ((TaskFunc)(funcQueue[i] - ENC_VAL_1 - DSP_OBFS_OFFSET))() != 0;
func_result_sum += func_result;
func_result_sum <<= 1;
funcResultSum += funcResult;
funcResultSum <<= 1;
compare_sum += TRUE;
compare_sum <<= 1;
compareSum += TRUE;
compareSum <<= 1;
}
BOOL ret;
if (expected_result == EXPECT_TRUE) {
ret = (func_result_sum >> 1) == (compare_sum >> 1);
if (expectedResult == EXPECT_TRUE) {
ret = (funcResultSum >> 1) == (compareSum >> 1);
} else {
ret = ((func_result_sum & compare_sum) >> 1) != 0;
ret = ((funcResultSum & compareSum) >> 1) != 0;
}
if (callback != NULL && ret) {
@ -57,60 +48,60 @@ static inline u32 dsprotMain(u32 *func_queue, int expected_result, void *callbac
return (u32)ret;
}
u32 DetectFlashcart(void *callback) {
u32 func_queue[32];
u32 DSProtInternal_DetectFlashcart(void *callback) {
u32 funcQueue[32];
func_queue[2] = FUNC_QUEUE_END;
func_queue[0] = ADDR_PLUS_ADDEND(RunEncrypted_ROMTest_IsBad, ENC_VAL_1) + DSP_OBFS_OFFSET;
func_queue[1] = ADDR_PLUS_ADDEND(RunEncrypted_Integrity_ROMTest_IsBad, ENC_VAL_1) + DSP_OBFS_OFFSET;
funcQueue[2] = FUNC_QUEUE_END;
funcQueue[0] = ADDR_PLUS_ADDEND(RunEncrypted_ROMTest_IsBad, ENC_VAL_1) + DSP_OBFS_OFFSET;
funcQueue[1] = ADDR_PLUS_ADDEND(RunEncrypted_Integrity_ROMTest_IsBad, ENC_VAL_1) + DSP_OBFS_OFFSET;
return dsprotMain(&func_queue[0], EXPECT_FALSE, callback);
return dsprotMain(&funcQueue[0], EXPECT_FALSE, callback);
}
u32 DetectNotFlashcart(void *callback) {
u32 func_queue[32];
u32 DSProtInternal_DetectNotFlashcart(void *callback) {
u32 funcQueue[32];
func_queue[2] = FUNC_QUEUE_END;
func_queue[0] = ADDR_PLUS_ADDEND(RunEncrypted_ROMTest_IsGood, ENC_VAL_1) + DSP_OBFS_OFFSET;
func_queue[1] = ADDR_PLUS_ADDEND(RunEncrypted_Integrity_ROMTest_IsGood, ENC_VAL_1) + DSP_OBFS_OFFSET;
funcQueue[2] = FUNC_QUEUE_END;
funcQueue[0] = ADDR_PLUS_ADDEND(RunEncrypted_ROMTest_IsGood, ENC_VAL_1) + DSP_OBFS_OFFSET;
funcQueue[1] = ADDR_PLUS_ADDEND(RunEncrypted_Integrity_ROMTest_IsGood, ENC_VAL_1) + DSP_OBFS_OFFSET;
return dsprotMain(&func_queue[0], EXPECT_TRUE, callback);
return dsprotMain(&funcQueue[0], EXPECT_TRUE, callback);
}
u32 DetectEmulator(void *callback) {
u32 func_queue[32];
u32 DSProtInternal_DetectEmulator(void *callback) {
u32 funcQueue[32];
func_queue[2] = FUNC_QUEUE_END;
func_queue[0] = ADDR_PLUS_ADDEND(RunEncrypted_MACOwner_IsBad, ENC_VAL_1) + DSP_OBFS_OFFSET;
func_queue[1] = ADDR_PLUS_ADDEND(RunEncrypted_Integrity_MACOwner_IsBad, ENC_VAL_1) + DSP_OBFS_OFFSET;
funcQueue[2] = FUNC_QUEUE_END;
funcQueue[0] = ADDR_PLUS_ADDEND(RunEncrypted_MACOwner_IsBad, ENC_VAL_1) + DSP_OBFS_OFFSET;
funcQueue[1] = ADDR_PLUS_ADDEND(RunEncrypted_Integrity_MACOwner_IsBad, ENC_VAL_1) + DSP_OBFS_OFFSET;
return dsprotMain(&func_queue[0], EXPECT_FALSE, callback);
return dsprotMain(&funcQueue[0], EXPECT_FALSE, callback);
}
u32 DetectNotEmulator(void *callback) {
u32 func_queue[32];
u32 DSProtInternal_DetectNotEmulator(void *callback) {
u32 funcQueue[32];
func_queue[2] = FUNC_QUEUE_END;
func_queue[0] = ADDR_PLUS_ADDEND(RunEncrypted_MACOwner_IsGood, ENC_VAL_1) + DSP_OBFS_OFFSET;
func_queue[1] = ADDR_PLUS_ADDEND(RunEncrypted_Integrity_MACOwner_IsGood, ENC_VAL_1) + DSP_OBFS_OFFSET;
funcQueue[2] = FUNC_QUEUE_END;
funcQueue[0] = ADDR_PLUS_ADDEND(RunEncrypted_MACOwner_IsGood, ENC_VAL_1) + DSP_OBFS_OFFSET;
funcQueue[1] = ADDR_PLUS_ADDEND(RunEncrypted_Integrity_MACOwner_IsGood, ENC_VAL_1) + DSP_OBFS_OFFSET;
return dsprotMain(&func_queue[0], EXPECT_TRUE, callback);
return dsprotMain(&funcQueue[0], EXPECT_TRUE, callback);
}
u32 DetectDummy(void *callback) {
u32 func_queue[32];
u32 DSProtInternal_DetectDummy(void *callback) {
u32 funcQueue[32];
// Prevent optimization of the function queue processing
*(u32 *)&func_queue[0] = FUNC_QUEUE_END;
*(u32 *)&funcQueue[0] = FUNC_QUEUE_END;
return dsprotMain(&func_queue[0], EXPECT_FALSE, callback);
return dsprotMain(&funcQueue[0], EXPECT_FALSE, callback);
}
u32 DetectNotDummy(void *callback) {
u32 func_queue[32];
u32 DSProtInternal_DetectNotDummy(void *callback) {
u32 funcQueue[32];
// Prevent optimization of the function queue processing
*(u32 *)&func_queue[0] = FUNC_QUEUE_END;
*(u32 *)&funcQueue[0] = FUNC_QUEUE_END;
return dsprotMain(&func_queue[0], EXPECT_TRUE, callback);
return dsprotMain(&funcQueue[0], EXPECT_TRUE, callback);
}

View File

@ -2,19 +2,18 @@
#include "bss.h"
#include "encoding_constants.h"
#include "nitro_os.h"
#include "rc4.h"
#define ROTL(x, a) ((a) == 0 ? (x) : (((x) << (a)) | ((x) >> (32 - (a)))))
static void clearDataAndInstructionCache(void *start_addr, u32 num_bytes);
static void clearDataAndInstructionCache(void *startAddr, u32 numBytes);
static void clearDataAndInstructionCache(void *start_addr, u32 num_bytes) {
DC_FlushRange(start_addr, num_bytes);
IC_InvalidateRange(start_addr, num_bytes);
static void clearDataAndInstructionCache(void *startAddr, u32 numBytes) {
DC_FlushRange(startAddr, numBytes);
IC_InvalidateRange(startAddr, numBytes);
}
u32 Encryptor_CategorizeInstruction(u32 instruction) {
InsType Encryptor_CategorizeInstruction(u32 instruction) {
u8 opcode = instruction >> INS_OPCODE_SHIFT;
// Branch instruction
@ -40,18 +39,18 @@ void Encryptor_DecodeFunctionTable(FuncInfo *functions) {
return;
}
for (; functions->obfs_addr != 0; functions++) {
u32 *addr = (u32 *)functions->obfs_addr;
u32 size = functions->obfs_size - (u32)&BSS - ENC_VAL_1;
for (; functions->obfsAddr != 0; functions++) {
u32 *addr = (u32 *)functions->obfsAddr;
u32 size = functions->obfsSize - (u32)&DSProt_BSS - ENC_VAL_1;
if (addr == NULL) {
break;
}
addr = (void *)addr - ENC_VAL_1;
u32 *end_addr = addr + (size / 4);
u32 *endAddr = addr + (size / 4);
for (; addr < end_addr; addr++) {
for (; addr < endAddr; addr++) {
switch (Encryptor_CategorizeInstruction(*addr)) {
case INS_TYPE_BLXIMM:
case INS_TYPE_BL: {
@ -59,67 +58,70 @@ void Encryptor_DecodeFunctionTable(FuncInfo *functions) {
u32 operands = ((*addr & INS_OPERANDS_MASK) - ENC_VAL_1) & INS_OPERANDS_MASK;
*addr = opcode | operands;
} break;
}
break;
case INS_TYPE_B: {
u32 opcode = (*addr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*addr & INS_OPERANDS_MASK) - ENC_VAL_2) & INS_OPERANDS_MASK;
*addr = opcode | operands;
} break;
}
break;
default: {
u8 *addr_bytes = (u8 *)addr;
*addr = (addr_bytes[0] ^ ENC_BYTE_A) | ((addr_bytes[1] ^ ENC_BYTE_B) << 8) | ((addr_bytes[2] ^ ENC_BYTE_C) << 16) | ((addr_bytes[3] ^ ENC_BYTE_D) << 24);
} break;
u8 *addrBytes = (u8 *)addr;
*addr = (addrBytes[0] ^ ENC_BYTE_A) | ((addrBytes[1] ^ ENC_BYTE_B) << 8) | ((addrBytes[2] ^ ENC_BYTE_C) << 16) | ((addrBytes[3] ^ ENC_BYTE_D) << 24);
}
break;
}
}
clearDataAndInstructionCache((void *)(functions->obfs_addr - ENC_VAL_1), size);
clearDataAndInstructionCache((void *)(functions->obfsAddr - ENC_VAL_1), size);
}
}
static inline void expandRC4Key(u32 seed_key, u32 size, u32 *expanded_key) {
expanded_key[0] = ROTL(seed_key, 0) ^ size;
expanded_key[1] = ROTL(seed_key, 8) ^ size;
expanded_key[2] = ROTL(seed_key, 16) ^ size;
expanded_key[3] = ROTL(seed_key, 24) ^ size;
static inline void expandRC4Key(u32 seedKey, u32 size, u32 *expandedKey) {
expandedKey[0] = ROTL(seedKey, 0) ^ size;
expandedKey[1] = ROTL(seedKey, 8) ^ size;
expandedKey[2] = ROTL(seedKey, 16) ^ size;
expandedKey[3] = ROTL(seedKey, 24) ^ size;
}
void *Encryptor_DecryptFunction(u32 key, u32 func_addr, u32 size) {
void *Encryptor_DecryptFunction(u32 key, u32 funcAddr, u32 size) {
// Deobfuscate arguments
size -= (u32)&BSS + ENC_VAL_1;
size -= (u32)&DSProt_BSS + ENC_VAL_1;
key -= (u32)&BSS + ENC_VAL_1;
key -= (u32)&DSProt_BSS + ENC_VAL_1;
void *func_ptr = (void *)func_addr;
func_ptr -= ENC_VAL_1;
void *funcPtr = (void *)funcAddr;
funcPtr -= ENC_VAL_1;
u32 expanded_key[4];
expandRC4Key(key, size, &expanded_key[0]);
RC4_InitAndDecryptInstructions(&expanded_key[0], func_ptr, func_ptr, size);
clearDataAndInstructionCache(func_ptr, size);
u32 expandedKey[4];
expandRC4Key(key, size, &expandedKey[0]);
RC4_InitAndDecryptInstructions(&expandedKey[0], funcPtr, funcPtr, size);
clearDataAndInstructionCache(funcPtr, size);
return func_ptr;
return funcPtr;
}
u32 Encryptor_EncryptFunction(u32 key, u32 func_addr, u32 size) {
u32 Encryptor_EncryptFunction(u32 key, u32 funcAddr, u32 size) {
// Deobfuscate arguments and change key
size -= (u32)&BSS + ENC_VAL_1;
size -= (u32)&DSProt_BSS + ENC_VAL_1;
key -= (u32)&BSS + ENC_VAL_1;
key += func_addr >> 20;
key -= (u32)&DSProt_BSS + ENC_VAL_1;
key += funcAddr >> 20;
void *func_ptr = (void *)func_addr;
func_ptr -= ENC_VAL_1;
void *funcPtr = (void *)funcAddr;
funcPtr -= ENC_VAL_1;
u32 expanded_key[4];
expandRC4Key(key, size, &expanded_key[0]);
RC4_InitAndEncryptInstructions(&expanded_key[0], func_ptr, func_ptr, size);
clearDataAndInstructionCache(func_ptr, size);
u32 expandedKey[4];
expandRC4Key(key, size, &expandedKey[0]);
RC4_InitAndEncryptInstructions(&expandedKey[0], funcPtr, funcPtr, size);
clearDataAndInstructionCache(funcPtr, size);
// Re-obfuscate key
key += (u32)&BSS + ENC_VAL_1;
key += (u32)&DSProt_BSS + ENC_VAL_1;
return key;
}

View File

@ -1,9 +1,9 @@
#include "bss.h"
#include "garbage.h"
u8 BSS[4];
u8 DSProt_BSS[4];
const u32 Garbage[6] = {
const u32 DSProt_Garbage[6] = {
0xEBAA0113,
0xE4064EC7,
0xEF013596,

View File

@ -4,16 +4,10 @@
#include "mac_owner.h"
#include "rom_test.h"
// Functions to be encrypted (cannot be called directly)
u32 Integrity_MACOwner_IsBad(void);
u32 Integrity_MACOwner_IsGood(void);
u32 Integrity_ROMTest_IsBad(void);
u32 Integrity_ROMTest_IsGood(void);
#define INTEGRITY_OBFS_OFFSET (ENC_VAL_1 & ~0xFFF)
// This was likely not originally an inline, but an inline is able to match here nicely
static inline u32 checkDecryptionWrapper(u8 *addr, u32 match_ret, u32 mismatch_ret) {
static inline u32 checkDecryptionWrapper(u8 *addr, u32 matchRet, u32 mismatchRet) {
addr += INTEGRITY_OBFS_OFFSET;
u32 offset = ENC_VAL_1 - INTEGRITY_OBFS_OFFSET;
@ -23,58 +17,58 @@ static inline u32 checkDecryptionWrapper(u8 *addr, u32 match_ret, u32 mismatch_r
// e8bd00f0 ldmfd sp!, {r4-r7}
// e59f103c ldr r1, [pc, #60]
if (addr[offset++] != 0xF0) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0x00) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0x2D) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0xE9) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0x0F) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0x00) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0x2D) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0xE9) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0xF0) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0x00) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0xBD) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0xE8) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0x60) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0x10) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0x9F) {
return mismatch_ret;
return mismatchRet;
}
if (addr[offset++] != 0xE5) {
return mismatch_ret;
return mismatchRet;
}
return match_ret;
return matchRet;
}
u32 Integrity_MACOwner_IsBad(void) {

View File

@ -1,16 +1,10 @@
#include "mac_owner.h"
#include "nitro_os.h"
// Functions to be encrypted (cannot be called directly)
u32 MACOwner_IsBad(void);
u32 MACOwner_IsGood(void);
#define MAC_ADDR_SIZE (6)
#define ENC_MAC_ADDR_BYTE (0xFF)
static const u8 bad_mac_addr[MAC_ADDR_SIZE] = {
static const u8 badMacAddr[MAC_ADDR_SIZE] = {
0x00 ^ ENC_MAC_ADDR_BYTE,
0x09 ^ ENC_MAC_ADDR_BYTE,
0xBF ^ ENC_MAC_ADDR_BYTE,
@ -19,34 +13,34 @@ static const u8 bad_mac_addr[MAC_ADDR_SIZE] = {
0x31 ^ ENC_MAC_ADDR_BYTE
};
static inline u32 testMACOwner(u32 pass_ret, u32 fail_ret) {
u8 mac_addr[MAC_ADDR_SIZE];
OS_GetMacAddress(&mac_addr[0]);
static inline u32 testMACOwner(u32 passRet, u32 failRet) {
u8 macAddr[MAC_ADDR_SIZE];
OS_GetMacAddress(&macAddr[0]);
s32 i;
for (i = 0; i < MAC_ADDR_SIZE; i++) {
if (bad_mac_addr[i] != (mac_addr[i] ^ ENC_MAC_ADDR_BYTE)) {
if (badMacAddr[i] != (macAddr[i] ^ ENC_MAC_ADDR_BYTE)) {
break;
}
}
OSOwnerInfo owner_info;
OS_GetOwnerInfo(&owner_info);
OSOwnerInfo ownerInfo;
OS_GetOwnerInfo(&ownerInfo);
u32 ret;
if (i == MAC_ADDR_SIZE && owner_info.birthday.month == 1 && owner_info.birthday.day == 1 && owner_info.nickNameLength == 0) {
ret = fail_ret;
if (i == MAC_ADDR_SIZE && ownerInfo.birthday.month == 1 && ownerInfo.birthday.day == 1 && ownerInfo.nickNameLength == 0) {
ret = failRet;
goto EXIT;
}
for (i = 0; i < MAC_ADDR_SIZE; i++) {
if (mac_addr[i] != 0x00) {
ret = pass_ret;
if (macAddr[i] != 0x00) {
ret = passRet;
goto EXIT;
}
}
ret = fail_ret;
ret = failRet;
EXIT:
return ret;

View File

@ -3,22 +3,13 @@
#include "encoding_constants.h"
#include "encryptor.h"
#define RC4_KEY_SIZE (16)
typedef struct {
struct RC4_Ctx {
int i;
int j;
u8 S[256];
} RC4_Ctx;
};
// Functions to be encoded (cannot be static)
void RC4_Init(RC4_Ctx *ctx, const void *key, u32 key_len);
u8 RC4_Byte(RC4_Ctx *ctx);
u32 RC4_InitSBox(u8 *sbox);
u32 RC4_EncryptInstructions(RC4_Ctx *ctx, void *src, void *dst, u32 size);
u32 RC4_DecryptInstructions(RC4_Ctx *ctx, void *src, void *dst, u32 size);
void RC4_Init(RC4_Ctx *ctx, const void *key, u32 key_len) {
void RC4_Init(RC4_Ctx *ctx, const void *key, u32 keyLen) {
s32 Ki = 0;
u8 Si = 0;
@ -41,7 +32,7 @@ void RC4_Init(RC4_Ctx *ctx, const void *key, u32 key_len) {
ctx->S[i] = tmp2;
Ki++;
if (Ki >= key_len) {
if (Ki >= keyLen) {
Ki = 0;
}
}
@ -75,44 +66,46 @@ u32 RC4_EncryptInstructions(RC4_Ctx *ctx, void *src, void *dst, u32 size) {
return -1;
}
u8 *src_bytes = (u8 *)src;
u8 *dst_bytes = (u8 *)dst;
u8 *srcBytes = (u8 *)src;
u8 *dstBytes = (u8 *)dst;
u8 sbox[256];
RC4_InitSBox(&sbox[0]);
for (u32 offset = 0; offset < size; offset += 4) {
switch (Encryptor_CategorizeInstruction(*(u32 *)(src_bytes + offset))) {
switch (Encryptor_CategorizeInstruction(*(u32 *)(srcBytes + offset))) {
case INS_TYPE_BLXIMM:
case INS_TYPE_BL: {
u32 *src_addr = (u32 *)(src_bytes + offset);
u32 *dst_addr = (u32 *)(dst_bytes + offset);
u32 *srcAddr = (u32 *)(srcBytes + offset);
u32 *dstAddr = (u32 *)(dstBytes + offset);
*dst_addr = *src_addr;
*dstAddr = *srcAddr;
u32 opcode = (*dst_addr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*dst_addr & INS_OPERANDS_MASK) + ENC_VAL_2) & INS_OPERANDS_MASK;
u32 opcode = (*dstAddr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*dstAddr & INS_OPERANDS_MASK) + ENC_VAL_2) & INS_OPERANDS_MASK;
*dst_addr = opcode | operands;
} break;
*dstAddr = opcode | operands;
}
break;
case INS_TYPE_B: {
u32 *src_addr = (u32 *)(src_bytes + offset);
u32 *dst_addr = (u32 *)(dst_bytes + offset);
u32 *srcAddr = (u32 *)(srcBytes + offset);
u32 *dstAddr = (u32 *)(dstBytes + offset);
*dst_addr = *src_addr;
*dstAddr = *srcAddr;
u32 opcode = (*dst_addr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*dst_addr & INS_OPERANDS_MASK) + ENC_VAL_1) & INS_OPERANDS_MASK;
u32 opcode = (*dstAddr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*dstAddr & INS_OPERANDS_MASK) + ENC_VAL_1) & INS_OPERANDS_MASK;
*dst_addr = opcode | operands;
} break;
*dstAddr = opcode | operands;
}
break;
default:
dst_bytes[offset] = src_bytes[offset] ^ RC4_Byte(ctx);
dst_bytes[offset + 1] = src_bytes[offset + 1] ^ RC4_Byte(ctx);
dst_bytes[offset + 2] = sbox[src_bytes[offset + 2]];
dst_bytes[offset + 3] = src_bytes[offset + 3];
dstBytes[offset] = srcBytes[offset] ^ RC4_Byte(ctx);
dstBytes[offset + 1] = srcBytes[offset + 1] ^ RC4_Byte(ctx);
dstBytes[offset + 2] = sbox[srcBytes[offset + 2]];
dstBytes[offset + 3] = srcBytes[offset + 3];
break;
}
}
@ -125,44 +118,46 @@ u32 RC4_DecryptInstructions(RC4_Ctx *ctx, void *src, void *dst, u32 size) {
return -1;
}
u8 *src_bytes = (u8 *)src;
u8 *dst_bytes = (u8 *)dst;
u8 *srcBytes = (u8 *)src;
u8 *dstBytes = (u8 *)dst;
u8 sbox[256];
RC4_InitSBox(&sbox[0]);
for (u32 offset = 0; offset < size; offset += 4) {
switch (Encryptor_CategorizeInstruction(*(u32 *)(src_bytes + offset))) {
switch (Encryptor_CategorizeInstruction(*(u32 *)(srcBytes + offset))) {
case INS_TYPE_BLXIMM:
case INS_TYPE_BL: {
u32 *src_addr = (u32 *)(src_bytes + offset);
u32 *dst_addr = (u32 *)(dst_bytes + offset);
u32 *srcAddr = (u32 *)(srcBytes + offset);
u32 *dstAddr = (u32 *)(dstBytes + offset);
*dst_addr = *src_addr;
*dstAddr = *srcAddr;
u32 opcode = (*dst_addr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*dst_addr & INS_OPERANDS_MASK) - ENC_VAL_1) & INS_OPERANDS_MASK;
u32 opcode = (*dstAddr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*dstAddr & INS_OPERANDS_MASK) - ENC_VAL_1) & INS_OPERANDS_MASK;
*dst_addr = opcode | operands;
} break;
*dstAddr = opcode | operands;
}
break;
case INS_TYPE_B: {
u32 *src_addr = (u32 *)(src_bytes + offset);
u32 *dst_addr = (u32 *)(dst_bytes + offset);
u32 *srcAddr = (u32 *)(srcBytes + offset);
u32 *dstAddr = (u32 *)(dstBytes + offset);
*dst_addr = *src_addr;
*dstAddr = *srcAddr;
u32 opcode = (*dst_addr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*dst_addr & INS_OPERANDS_MASK) - ENC_VAL_2) & INS_OPERANDS_MASK;
u32 opcode = (*dstAddr & INS_OPCODE_MASK) ^ (INS_OPCODE_LINKBIT << INS_OPCODE_SHIFT);
u32 operands = ((*dstAddr & INS_OPERANDS_MASK) - ENC_VAL_2) & INS_OPERANDS_MASK;
*dst_addr = opcode | operands;
} break;
*dstAddr = opcode | operands;
}
break;
default:
dst_bytes[offset] = src_bytes[offset] ^ RC4_Byte(ctx);
dst_bytes[offset + 1] = src_bytes[offset + 1] ^ RC4_Byte(ctx);
dst_bytes[offset + 2] = sbox[src_bytes[offset + 2]];
dst_bytes[offset + 3] = src_bytes[offset + 3];
dstBytes[offset] = srcBytes[offset] ^ RC4_Byte(ctx);
dstBytes[offset + 1] = srcBytes[offset + 1] ^ RC4_Byte(ctx);
dstBytes[offset + 2] = sbox[srcBytes[offset + 2]];
dstBytes[offset + 3] = srcBytes[offset + 3];
break;
}
}

View File

@ -1,32 +1,27 @@
#include "rom_test.h"
#include "nitro_card.h"
#include "rom_util.h"
// Functions to be encrypted (cannot be called directly)
u32 ROMTest_IsBad(void);
u32 ROMTest_IsGood(void);
#define ROM_BLOCK_SIZE CARD_ROM_PAGE_SIZE
static inline u32 testROM(u32 pass_ret, u32 fail_ret) {
static inline u32 testROM(u32 passRet, u32 failRet) {
// Extra CRC entry is required to match
u32 crcs[7];
u8 rom_buf[ROM_BLOCK_SIZE];
u8 romBuf[ROM_BLOCK_SIZE];
s32 i;
u32 rom_addr = 0x1000;
u32 romAddr = 0x1000;
for (i = 0; i < 6; i++) {
RunEncrypted_ROMUtil_Read(&rom_buf[0], rom_addr, ROM_BLOCK_SIZE);
crcs[i] = RunEncrypted_ROMUtil_CRC32(&rom_buf[0], ROM_BLOCK_SIZE);
RunEncrypted_ROMUtil_Read(&romBuf[0], romAddr, ROM_BLOCK_SIZE);
crcs[i] = RunEncrypted_ROMUtil_CRC32(&romBuf[0], ROM_BLOCK_SIZE);
if (i == 2) {
// Has to be like this to match
rom_addr = 1;
rom_addr <<= 15;
romAddr = 1;
romAddr <<= 15;
} else {
rom_addr += ROM_BLOCK_SIZE;
romAddr += ROM_BLOCK_SIZE;
}
}
@ -37,22 +32,22 @@ static inline u32 testROM(u32 pass_ret, u32 fail_ret) {
u32 ret;
for (i = 0; i < 3; i++) {
if (crcs[i] != crcs[3]) {
ret = fail_ret;
ret = failRet;
goto EXIT;
}
}
if (crcs[3] == crcs[4] && crcs[3] == crcs[5]) {
ret = fail_ret;
ret = failRet;
} else {
ret = pass_ret;
ret = passRet;
}
EXIT:
// Erasing read buffer
u8 *buf_ptr = &rom_buf[0];
u8 *bufPtr = &romBuf[0];
for (i = 0; i < ROM_BLOCK_SIZE; i++) {
*buf_ptr++ = 0;
*bufPtr++ = 0;
}
return ret;

View File

@ -1,20 +1,12 @@
#include "rom_util.h"
#include "nitro_card.h"
#include "nitro_io_reg.h"
#include "nitro_os.h"
// Custom defs not provided by Nitro
// Custom defs not provided by SDK
#define REG_CARD_MASTER_CNT_OFFSET (0x1A1)
#define REG_CARDCNT_OFFSET (0x1A4)
#define REG_CARD_CMD_OFFSET (0x1A8)
#define REG_CARD_DATA_OFFSET (0x100010)
// Functions to be encrypted (cannot be called directly)
void ROMUtil_Read(void *dest, u32 addr, s32 num_bytes);
u32 ROMUtil_CRC32(void *buf, u32 size);
void ROMUtil_Read(void *dest, u32 addr, s32 num_bytes) {
void ROMUtil_Read(void *dest, u32 addr, s32 numBytes) {
// This function is executing an obfuscated manual cartridge ROM read.
// Nitro SDK usually does this for you with CARD_ReadRom* and friends.
//
@ -24,105 +16,105 @@ void ROMUtil_Read(void *dest, u32 addr, s32 num_bytes) {
// Some of the comment documentation may be inaccurate here.
u8 buffer[8];
u8 *buf_ptr;
u8 *bufPtr;
REGType8v *vnull;
u32 register_base_1;
REGType8v *register_base_2;
u32 card_ctrl_13;
s32 addr_offset;
u16 lock_id;
u16 ext_mem_register_val_original;
u32 registerBase1;
REGType8v *registerBase2;
u32 cardCtrl13;
s32 addrOffset;
u16 lockID;
u16 extMemRegisterValOriginal;
u32 output;
s32 card_ctrl_cmd;
s32 cardCtrlCmd;
s32 i;
lock_id = OS_GetLockID();
CARD_LockRom(lock_id);
lockID = OS_GetLockID();
CARD_LockRom(lockID);
// Alias for volatile null pointer
vnull = (REGType8v *)NULL;
// Alias for register base (0x04000000)
register_base_1 = 1;
register_base_1 <<= 26;
registerBase1 = 1;
registerBase1 <<= 26;
// Another alias for register base (0x04000000)
register_base_2 = (REGType8v *)HW_REG_BASE;
registerBase2 = (REGType8v *)HW_REG_BASE;
// External memory control register (0x04000204)
// Save value to rewrite later
ext_mem_register_val_original = reg_MI_EXMEMCNT;
extMemRegisterValOriginal = reg_MI_EXMEMCNT;
// Set current processor accessing the gamecard bus to the ARM9
reg_MI_EXMEMCNT = (reg_MI_EXMEMCNT & ~REG_MI_EXMEMCNT_MP_MASK) | (MI_PROCESSOR_ARM9 << REG_MI_EXMEMCNT_MP_SHIFT);
// Obfuscated, create address 0x027FFE60
// This is an address in the ROM header: port 0x040001A4 / setting for normal commands
card_ctrl_13 = 5;
card_ctrl_13 <<= 18;
card_ctrl_13 -= 13;
cardCtrl13 = 5;
cardCtrl13 <<= 18;
cardCtrl13 -= 13;
// Detect if the system is in DSi mode. If so, change the address to 0x02FFFE60
if (*(REGType8v *)(register_base_1 + REG_A9ROM_OFFSET) & REG_SCFG_A9ROM_SEC_MASK) {
card_ctrl_13 |= 0x40000;
if (*(REGType8v *)(registerBase1 + REG_A9ROM_OFFSET) & REG_SCFG_A9ROM_SEC_MASK) {
cardCtrl13 |= 0x40000;
}
card_ctrl_13 <<= 5;
cardCtrl13 <<= 5;
// Read port setting and set page read flags
card_ctrl_cmd = (*(vs32 *)card_ctrl_13 & ~CARD_COMMAND_MASK) | (CARD_COMMAND_PAGE | CARD_READ_MODE | CARD_START | CARD_RESET_HI);
cardCtrlCmd = (*(vs32 *)cardCtrl13 & ~CARD_COMMAND_MASK) | (CARD_COMMAND_PAGE | CARD_READ_MODE | CARD_START | CARD_RESET_HI);
// Calculate offset to round back to nearest 0x200-byte block.
// E.G. if we want to read starting from 0x1208, we actually need to
// request the block at 0x1200 and then ignore the first 8 bytes of the result.
// This would set `addr_offset` to -8.
addr_offset = 0 - (addr & (CARD_ROM_PAGE_SIZE - 1));
// This would set `addrOffset` to -8.
addrOffset = 0 - (addr & (CARD_ROM_PAGE_SIZE - 1));
// Wait for card to not be busy
while (*(REGType32v *)(register_base_1 + REG_CARDCNT_OFFSET) & CARD_START) {
while (*(REGType32v *)(registerBase1 + REG_CARDCNT_OFFSET) & CARD_START) {
continue;
}
// Write enable flag to card ROM and SPI control register
*(REGType8v *)(register_base_1 + REG_CARD_MASTER_CNT_OFFSET) = CARDMST_ENABLE;
*(REGType8v *)(registerBase1 + REG_CARD_MASTER_CNT_OFFSET) = CARDMST_ENABLE;
// Read 8-byte command out from gamecard bus, write this back later
buf_ptr = &buffer[0];
bufPtr = &buffer[0];
for (i = 0; i < 8; i++) {
*buf_ptr++ = *(vnull + HW_REG_BASE + REG_CARD_CMD_OFFSET + i);
*bufPtr++ = *(vnull + HW_REG_BASE + REG_CARD_CMD_OFFSET + i);
}
addr += addr_offset;
addr += addrOffset;
while (addr_offset < num_bytes) {
while (addrOffset < numBytes) {
// Read a 0x200-byte data block from ROM
// Write 8-byte command to registers
// B7XXXXXXXX000000 -> 0x200-byte encrypted data read from address XXXXXXXX
register_base_2[REG_CARD_CMD_OFFSET + 0] = MROMOP_G_READ_PAGE >> 24;
register_base_2[REG_CARD_CMD_OFFSET + 1] = addr >> 24;
register_base_2[REG_CARD_CMD_OFFSET + 2] = addr >> 16;
register_base_2[REG_CARD_CMD_OFFSET + 3] = addr >> 8;
register_base_2[REG_CARD_CMD_OFFSET + 4] = addr;
register_base_2[REG_CARD_CMD_OFFSET + 5] = 0x00;
register_base_2[REG_CARD_CMD_OFFSET + 6] = 0x00;
register_base_2[REG_CARD_CMD_OFFSET + 7] = 0x00;
registerBase2[REG_CARD_CMD_OFFSET + 0] = MROMOP_G_READ_PAGE >> 24;
registerBase2[REG_CARD_CMD_OFFSET + 1] = addr >> 24;
registerBase2[REG_CARD_CMD_OFFSET + 2] = addr >> 16;
registerBase2[REG_CARD_CMD_OFFSET + 3] = addr >> 8;
registerBase2[REG_CARD_CMD_OFFSET + 4] = addr;
registerBase2[REG_CARD_CMD_OFFSET + 5] = 0x00;
registerBase2[REG_CARD_CMD_OFFSET + 6] = 0x00;
registerBase2[REG_CARD_CMD_OFFSET + 7] = 0x00;
// Submit command
*(REGType32v *)(register_base_1 + REG_CARDCNT_OFFSET) = card_ctrl_cmd;
*(REGType32v *)(registerBase1 + REG_CARDCNT_OFFSET) = cardCtrlCmd;
// Copy the output into the destination buffer, within the bounds of num_bytes
// Copy the output into the destination buffer, within the bounds of numBytes
// (Must read the output out of the I/O register regardless)
do {
if (*(REGType32v *)(register_base_1 + REG_CARDCNT_OFFSET) & CARD_DATA_READY) {
output = *(REGType32v *)(register_base_1 + REG_CARD_DATA_OFFSET);
if (addr_offset >= 0 && addr_offset < num_bytes) {
*(u32 *)(dest + addr_offset) = output;
if (*(REGType32v *)(registerBase1 + REG_CARDCNT_OFFSET) & CARD_DATA_READY) {
output = *(REGType32v *)(registerBase1 + REG_CARD_DATA_OFFSET);
if (addrOffset >= 0 && addrOffset < numBytes) {
*(u32 *)(dest + addrOffset) = output;
}
addr_offset += 4;
addrOffset += 4;
}
} while (*(REGType32v *)(register_base_1 + REG_CARDCNT_OFFSET) & CARD_START);
} while (*(REGType32v *)(registerBase1 + REG_CARDCNT_OFFSET) & CARD_START);
// Advance address to next block
addr += CARD_ROM_PAGE_SIZE;
@ -131,25 +123,25 @@ void ROMUtil_Read(void *dest, u32 addr, s32 num_bytes) {
// Done reading, restore everything how it was before
// Write original command back to gamecard bus
buf_ptr = &buffer[0];
bufPtr = &buffer[0];
for (i = 0; i < 8; i++) {
*(vnull + HW_REG_BASE + REG_CARD_CMD_OFFSET + i) = *buf_ptr++;
*(vnull + HW_REG_BASE + REG_CARD_CMD_OFFSET + i) = *bufPtr++;
}
// Write original value back to to external memory control register
*(REGType16v *)(register_base_1 + REG_EXMEMCNT_OFFSET) = ext_mem_register_val_original;
*(REGType16v *)(registerBase1 + REG_EXMEMCNT_OFFSET) = extMemRegisterValOriginal;
CARD_UnlockRom(lock_id);
OS_ReleaseLockID(lock_id);
CARD_UnlockRom(lockID);
OS_ReleaseLockID(lockID);
}
u32 ROMUtil_CRC32(void *buf, u32 size) {
s32 i;
u8 *byte_ptr = (u8 *)buf;
u8 *bytePtr = (u8 *)buf;
u32 crc = 0xFFFFFFFF;
u32 poly = 0xEDB88320;
while (size-- != 0) {
crc ^= *byte_ptr++;
crc ^= *bytePtr++;
for (i = 0; i < 8; i++) {
if (crc & 1) {
crc = (crc >> 1);

View File

@ -1,18 +0,0 @@
SRC_DIR := ./src
INC_DIR := ./include
BUILD_DIR := ./build
$(shell mkdir -p $(BUILD_DIR))
CFLAGS := -O3 -Wno-unused-result -I $(INC_DIR)
C_FILES := $(wildcard $(SRC_DIR)/*.c)
H_FILES := $(wildcard $(INC_DIR)/*.h)
.PHONY: clean
$(BUILD_DIR)/elfcoder: $(C_FILES) $(H_FILES)
$(CC) $(CFLAGS) $(C_FILES) -o $(BUILD_DIR)/elfcoder
clean:
$(RM) $(BUILD_DIR)/elfcoder

View File

@ -8,13 +8,11 @@
* Version 1.23
*/
#ifndef SDK_ASM
#include <nitro/types.h> // For u32
#ifdef __cplusplus
extern "C" {
#endif
#endif // __cplusplus
/*
* u32 DSProt_DetectFlashcart(void *callback)
@ -84,17 +82,6 @@ extern u32 DSProt_DetectNotDummy(void *callback);
#ifdef __cplusplus
}
#endif
#endif // __cplusplus
#else /* SDK_ASM */
.public DSProt_DetectFlashcart
.public DSProt_DetectNotFlashcart
.public DSProt_DetectEmulator
.public DSProt_DetectNotEmulator
.public DSProt_DetectDummy
.public DSProt_DetectNotDummy
#endif /* SDK_ASM */
#endif /* DSPROT_H */
#endif // DSPROT_H

View File

@ -1303,7 +1303,24 @@ Overlay voltorb_flip
Overlay ds_protect
{
After OVY_31
Library dsprot.a
Object lib/dsprot/dsprot_main_encrypted.o
Object lib/dsprot/dsprot_main_decrypter_encoded.o
Object lib/dsprot/dsprot_main_decrypter_decoder.o
Object lib/dsprot/extra.o
Object lib/dsprot/integrity_encrypted.o
Object lib/dsprot/integrity_decrypter_encoded.o
Object lib/dsprot/integrity_decrypter_decoder.o
Object lib/dsprot/encryptor_encoded.o
Object lib/dsprot/encryptor_decoder.o
Object lib/dsprot/mac_owner_encrypted.o
Object lib/dsprot/mac_owner_decrypter_encoded.o
Object lib/dsprot/rom_util_encrypted.o
Object lib/dsprot/rom_util_decrypter_encoded.o
Object lib/dsprot/rom_test_encrypted.o
Object lib/dsprot/rom_test_decrypter_encoded.o
Object lib/dsprot/coretests_decrypter_decoder.o
Object lib/dsprot/rc4_encoded.o
Object lib/dsprot/rc4_decoder.o
}
Overlay OVY_124
{

17
tools/elfcoder/Makefile Normal file
View File

@ -0,0 +1,17 @@
CC := gcc
CFLAGS := -O3 -Wno-unused-result
C_FILES := $(wildcard *.c)
H_FILES := $(wildcard *.h)
.PHONY: all clean
all: elfcoder
@:
elfcoder: $(C_FILES) $(H_FILES)
$(CC) $(CFLAGS) $(C_FILES) -o elfcoder
clean:
$(RM) elfcoder

View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include "asmwriter.h"
#include "encoder.h"
static int parseKey(const char *key_text, uint32_t *out_key) {
@ -50,6 +51,7 @@ static void printUsage(const char *self_name) {
" -f, --functions [func1, [func2, [ ... ]]] List of functions to encode/decode.\n"
" -k, --key [key] Optional encryption key. \n"
" -p, --prefix [prefix = RunEncrypted_] Prefix for decryption wrappers. \n"
" -r, --replace-prefix [prefix] Remove prefix from input functions.\n"
" -g --garbage [symbol] Optional added garbage reference. \n"
" -v, --verbose Print encoding progress. \n",
self_name);
@ -73,6 +75,7 @@ int ArgParse_CreateTask(EncodingTask *task, char **argv) {
task->key_mode = MODE_UNKEYED;
task->symbols = NULL;
task->wrapper_prefix = NULL;
task->replace_prefix = NULL;
task->garbage = NULL;
task->key = 0;
task->verbose = 0;
@ -199,6 +202,25 @@ int ArgParse_CreateTask(EncodingTask *task, char **argv) {
task->wrapper_prefix = next_arg;
arg_idx++;
} else if (argCompare(curr_arg, 'r', "--replace-prefix")) {
if (next_arg == NULL || next_arg[0] == '-') {
printf("Error: %s but no prefix string provided\n", curr_arg);
return 1;
}
if (task->replace_prefix != NULL) {
printf("Error: multiple prefix strings provided\n");
return 1;
}
if (!isValidIdentifier(next_arg)) {
printf("Error: invalid identifier: %s\n", next_arg);
return 1;
}
task->replace_prefix = next_arg;
arg_idx++;
} else if (argCompare(curr_arg, 'g', "--garbage")) {
if (next_arg == NULL || next_arg[0] == '-') {
printf("Error: %s but no reference provided\n", curr_arg);
@ -291,6 +313,14 @@ int ArgParse_CreateTask(EncodingTask *task, char **argv) {
return 1;
}
if (task->replace_prefix != NULL && task->encoding_type == ENC_ENCODE && task->key_mode == MODE_KEYED) {
if ((task->wrapper_prefix == NULL && strcmp(task->replace_prefix, DEFAULT_ADDED_PREFIX) == 0) ||
(task->wrapper_prefix != NULL && strcmp(task->wrapper_prefix, task->replace_prefix) == 0)) {
printf("Error: replaced prefix and added prefix cannot be the same\n");
return 1;
}
}
if (task->output_fname != NULL && task->encoding_type == ENC_DECODE) {
printf("Warning: output file name provided, but no output will be generated for decoding\n");
task->output_fname = NULL;
@ -301,6 +331,11 @@ int ArgParse_CreateTask(EncodingTask *task, char **argv) {
task->wrapper_prefix = NULL;
}
if (task->replace_prefix != NULL && !(task->encoding_type == ENC_ENCODE && task->key_mode == MODE_KEYED)) {
printf("Warning: replaced prefix provided, but will not be used unless encoding with key\n");
task->replace_prefix = NULL;
}
if (task->garbage != NULL && task->encoding_type == ENC_DECODE) {
printf("Warning: garbage reference provided, but will not be used for decoding\n");
task->garbage = NULL;

View File

@ -3,10 +3,6 @@
#include <stdlib.h>
#include <string.h>
#define ASM_COMMON_INCLUDE "asm_macro.inc"
char *default_prefix = "RunEncrypted_";
static int *allocSizeArray(char **first_symbol) {
int symbol_count = 0;
while (*first_symbol++ != NULL) {
@ -56,7 +52,21 @@ static void writeAssembly(ASMWriter_Ctx *asmw, FILE *output) {
"\n");
if (asmw->key_mode == MODE_KEYED) {
int replace_prefix_len = 0;
if (asmw->replace_prefix != NULL) {
replace_prefix_len = strlen(asmw->replace_prefix);
}
for (int symbol_idx = 0; asmw->symbols[symbol_idx] != NULL; symbol_idx++) {
int prefix_skip = 0;
// Skip over replace prefix, if the base symbol name starts with it
if (asmw->replace_prefix != NULL) {
if (strncmp(asmw->symbols[symbol_idx], asmw->replace_prefix, replace_prefix_len) == 0) {
prefix_skip = replace_prefix_len;
}
}
fprintf(output,
"\tarm_func_start %s%s\n"
"%s%s:\n"
@ -64,14 +74,14 @@ static void writeAssembly(ASMWriter_Ctx *asmw, FILE *output) {
"\tarm_func_end %s%s\n"
"\n",
asmw->wrapper_prefix,
asmw->symbols[symbol_idx],
asmw->symbols[symbol_idx] + prefix_skip,
asmw->wrapper_prefix,
asmw->symbols[symbol_idx],
asmw->symbols[symbol_idx] + prefix_skip,
asmw->symbols[symbol_idx],
asmw->symbol_sizes[symbol_idx],
asmw->key,
asmw->wrapper_prefix,
asmw->symbols[symbol_idx]);
asmw->symbols[symbol_idx] + prefix_skip);
}
if (asmw->garbage != NULL) {
@ -109,7 +119,7 @@ static void writeAssembly(ASMWriter_Ctx *asmw, FILE *output) {
fprintf(output,
"\t.section .sinit, 4\n"
"\t.word NitroStaticInit\n"
"\tsinit NitroStaticInit\n"
"\n");
}
}
@ -118,12 +128,13 @@ void ASMWriter_Init(ASMWriter_Ctx *asmw, EncodingTask *task) {
asmw->key = task->key;
asmw->key_mode = task->key_mode;
asmw->output_fname = task->output_fname;
asmw->replace_prefix = task->replace_prefix;
asmw->symbols = task->symbols;
asmw->garbage = task->garbage;
asmw->valid = 1;
if (task->wrapper_prefix == NULL) {
asmw->wrapper_prefix = default_prefix;
asmw->wrapper_prefix = DEFAULT_ADDED_PREFIX;
} else {
asmw->wrapper_prefix = task->wrapper_prefix;
}

View File

@ -5,10 +5,15 @@
#include "encoder.h"
#define ASM_COMMON_INCLUDE "asm_macro.inc"
#define DEFAULT_ADDED_PREFIX "RunEncrypted_"
typedef struct {
char *output_fname;
char **symbols;
char *wrapper_prefix;
char *replace_prefix;
char *garbage;
int *symbol_sizes;
int key_mode;

View File

@ -7,7 +7,22 @@
// S[i] = i ^ 1
// Incredibly secure S-Box.
static const uint8_t SBox[256] = {
0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x09, 0x08, 0x0B, 0x0A, 0x0D, 0x0C, 0x0F, 0x0E, 0x11, 0x10, 0x13, 0x12, 0x15, 0x14, 0x17, 0x16, 0x19, 0x18, 0x1B, 0x1A, 0x1D, 0x1C, 0x1F, 0x1E, 0x21, 0x20, 0x23, 0x22, 0x25, 0x24, 0x27, 0x26, 0x29, 0x28, 0x2B, 0x2A, 0x2D, 0x2C, 0x2F, 0x2E, 0x31, 0x30, 0x33, 0x32, 0x35, 0x34, 0x37, 0x36, 0x39, 0x38, 0x3B, 0x3A, 0x3D, 0x3C, 0x3F, 0x3E, 0x41, 0x40, 0x43, 0x42, 0x45, 0x44, 0x47, 0x46, 0x49, 0x48, 0x4B, 0x4A, 0x4D, 0x4C, 0x4F, 0x4E, 0x51, 0x50, 0x53, 0x52, 0x55, 0x54, 0x57, 0x56, 0x59, 0x58, 0x5B, 0x5A, 0x5D, 0x5C, 0x5F, 0x5E, 0x61, 0x60, 0x63, 0x62, 0x65, 0x64, 0x67, 0x66, 0x69, 0x68, 0x6B, 0x6A, 0x6D, 0x6C, 0x6F, 0x6E, 0x71, 0x70, 0x73, 0x72, 0x75, 0x74, 0x77, 0x76, 0x79, 0x78, 0x7B, 0x7A, 0x7D, 0x7C, 0x7F, 0x7E, 0x81, 0x80, 0x83, 0x82, 0x85, 0x84, 0x87, 0x86, 0x89, 0x88, 0x8B, 0x8A, 0x8D, 0x8C, 0x8F, 0x8E, 0x91, 0x90, 0x93, 0x92, 0x95, 0x94, 0x97, 0x96, 0x99, 0x98, 0x9B, 0x9A, 0x9D, 0x9C, 0x9F, 0x9E, 0xA1, 0xA0, 0xA3, 0xA2, 0xA5, 0xA4, 0xA7, 0xA6, 0xA9, 0xA8, 0xAB, 0xAA, 0xAD, 0xAC, 0xAF, 0xAE, 0xB1, 0xB0, 0xB3, 0xB2, 0xB5, 0xB4, 0xB7, 0xB6, 0xB9, 0xB8, 0xBB, 0xBA, 0xBD, 0xBC, 0xBF, 0xBE, 0xC1, 0xC0, 0xC3, 0xC2, 0xC5, 0xC4, 0xC7, 0xC6, 0xC9, 0xC8, 0xCB, 0xCA, 0xCD, 0xCC, 0xCF, 0xCE, 0xD1, 0xD0, 0xD3, 0xD2, 0xD5, 0xD4, 0xD7, 0xD6, 0xD9, 0xD8, 0xDB, 0xDA, 0xDD, 0xDC, 0xDF, 0xDE, 0xE1, 0xE0, 0xE3, 0xE2, 0xE5, 0xE4, 0xE7, 0xE6, 0xE9, 0xE8, 0xEB, 0xEA, 0xED, 0xEC, 0xEF, 0xEE, 0xF1, 0xF0, 0xF3, 0xF2, 0xF5, 0xF4, 0xF7, 0xF6, 0xF9, 0xF8, 0xFB, 0xFA, 0xFD, 0xFC, 0xFF, 0xFE
0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x09, 0x08, 0x0B, 0x0A, 0x0D, 0x0C, 0x0F, 0x0E,
0x11, 0x10, 0x13, 0x12, 0x15, 0x14, 0x17, 0x16, 0x19, 0x18, 0x1B, 0x1A, 0x1D, 0x1C, 0x1F, 0x1E,
0x21, 0x20, 0x23, 0x22, 0x25, 0x24, 0x27, 0x26, 0x29, 0x28, 0x2B, 0x2A, 0x2D, 0x2C, 0x2F, 0x2E,
0x31, 0x30, 0x33, 0x32, 0x35, 0x34, 0x37, 0x36, 0x39, 0x38, 0x3B, 0x3A, 0x3D, 0x3C, 0x3F, 0x3E,
0x41, 0x40, 0x43, 0x42, 0x45, 0x44, 0x47, 0x46, 0x49, 0x48, 0x4B, 0x4A, 0x4D, 0x4C, 0x4F, 0x4E,
0x51, 0x50, 0x53, 0x52, 0x55, 0x54, 0x57, 0x56, 0x59, 0x58, 0x5B, 0x5A, 0x5D, 0x5C, 0x5F, 0x5E,
0x61, 0x60, 0x63, 0x62, 0x65, 0x64, 0x67, 0x66, 0x69, 0x68, 0x6B, 0x6A, 0x6D, 0x6C, 0x6F, 0x6E,
0x71, 0x70, 0x73, 0x72, 0x75, 0x74, 0x77, 0x76, 0x79, 0x78, 0x7B, 0x7A, 0x7D, 0x7C, 0x7F, 0x7E,
0x81, 0x80, 0x83, 0x82, 0x85, 0x84, 0x87, 0x86, 0x89, 0x88, 0x8B, 0x8A, 0x8D, 0x8C, 0x8F, 0x8E,
0x91, 0x90, 0x93, 0x92, 0x95, 0x94, 0x97, 0x96, 0x99, 0x98, 0x9B, 0x9A, 0x9D, 0x9C, 0x9F, 0x9E,
0xA1, 0xA0, 0xA3, 0xA2, 0xA5, 0xA4, 0xA7, 0xA6, 0xA9, 0xA8, 0xAB, 0xAA, 0xAD, 0xAC, 0xAF, 0xAE,
0xB1, 0xB0, 0xB3, 0xB2, 0xB5, 0xB4, 0xB7, 0xB6, 0xB9, 0xB8, 0xBB, 0xBA, 0xBD, 0xBC, 0xBF, 0xBE,
0xC1, 0xC0, 0xC3, 0xC2, 0xC5, 0xC4, 0xC7, 0xC6, 0xC9, 0xC8, 0xCB, 0xCA, 0xCD, 0xCC, 0xCF, 0xCE,
0xD1, 0xD0, 0xD3, 0xD2, 0xD5, 0xD4, 0xD7, 0xD6, 0xD9, 0xD8, 0xDB, 0xDA, 0xDD, 0xDC, 0xDF, 0xDE,
0xE1, 0xE0, 0xE3, 0xE2, 0xE5, 0xE4, 0xE7, 0xE6, 0xE9, 0xE8, 0xEB, 0xEA, 0xED, 0xEC, 0xEF, 0xEE,
0xF1, 0xF0, 0xF3, 0xF2, 0xF5, 0xF4, 0xF7, 0xF6, 0xF9, 0xF8, 0xFB, 0xFA, 0xFD, 0xFC, 0xFF, 0xFE
};
enum {

View File

@ -26,6 +26,7 @@ typedef struct {
int key_mode;
char **symbols;
char *wrapper_prefix;
char *replace_prefix;
char *garbage;
uint32_t key;
int verbose;