Got rid of sysnand mode, add key gen code, new splash screen, autoboot, update fatfs, removed ninjhax/mset folder for CakeBrah/CakeHax, lots of minor changes.
This commit is contained in:
parent
42df009858
commit
6a2c30503d
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,7 +1,8 @@
|
|||||||
build.bat
|
build.bat
|
||||||
data/firmware.bin
|
data/firmware.bin
|
||||||
out
|
out
|
||||||
mset
|
CakeHax
|
||||||
|
CakeBrah
|
||||||
rnInstaller
|
rnInstaller
|
||||||
build
|
build
|
||||||
*.bin
|
*.bin
|
||||||
|
9
.gitmodules
vendored
9
.gitmodules
vendored
@ -1,3 +1,6 @@
|
|||||||
[submodule "mset"]
|
[submodule "CakeBrah"]
|
||||||
path = mset
|
path = CakeBrah
|
||||||
url = https://github.com/Reisyukaku/mset
|
url = https://github.com/mid-kid/CakeBrah
|
||||||
|
[submodule "CakeHax"]
|
||||||
|
path = CakeHax
|
||||||
|
url = https://github.com/mid-kid/CakeHax
|
||||||
|
1
CakeBrah
Submodule
1
CakeBrah
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit aca4aa7d3b3d2d195788c0b2555b307fbac63a7f
|
1
CakeHax
Submodule
1
CakeHax
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 6b8fca0b37a370a605f76b34b133da91a0b40f5e
|
28
Makefile
28
Makefile
@ -12,18 +12,20 @@ ifneq ($(PYTHON_VER_MAJOR), 3)
|
|||||||
PYTHON3 := py -3
|
PYTHON3 := py -3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
name := ReiNand
|
||||||
|
|
||||||
dir_source := source
|
dir_source := source
|
||||||
dir_data := data
|
dir_data := data
|
||||||
dir_build := build
|
dir_build := build
|
||||||
dir_mset := mset
|
dir_mset := CakeHax
|
||||||
dir_out := out
|
dir_out := out
|
||||||
dir_emu := emunand
|
dir_emu := emunand
|
||||||
dir_thread := thread
|
dir_thread := thread
|
||||||
dir_ninjhax := ninjhax
|
dir_ninjhax := CakeBrah
|
||||||
|
|
||||||
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
||||||
CFLAGS := -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main
|
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main
|
||||||
FLAGS := dir_out=$(abspath $(dir_out))
|
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) --no-print-directory
|
||||||
|
|
||||||
objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||||
@ -34,7 +36,7 @@ objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
|||||||
all: launcher emunand thread ninjhax
|
all: launcher emunand thread ninjhax
|
||||||
|
|
||||||
.PHONY: launcher
|
.PHONY: launcher
|
||||||
launcher: $(dir_out)/ReiNand.dat
|
launcher: $(dir_out)/$(name).dat
|
||||||
|
|
||||||
.PHONY: emunand
|
.PHONY: emunand
|
||||||
emunand: $(dir_out)/rei/emunand/emunand.bin
|
emunand: $(dir_out)/rei/emunand/emunand.bin
|
||||||
@ -43,7 +45,7 @@ emunand: $(dir_out)/rei/emunand/emunand.bin
|
|||||||
thread: $(dir_out)/rei/thread/arm9.bin
|
thread: $(dir_out)/rei/thread/arm9.bin
|
||||||
|
|
||||||
.PHONY: ninjhax
|
.PHONY: ninjhax
|
||||||
ninjhax: $(dir_out)/3ds/ReiNand
|
ninjhax: $(dir_out)/3ds/$(name)
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@ -51,16 +53,16 @@ clean:
|
|||||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
||||||
rm -rf $(dir_out) $(dir_build)
|
rm -rf $(dir_out) $(dir_build)
|
||||||
|
|
||||||
.PHONY: $(dir_out)/ReiNand.dat
|
.PHONY: $(dir_out)/$(name).dat
|
||||||
$(dir_out)/ReiNand.dat: $(dir_build)/main.bin $(dir_out)/rei/
|
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)/rei/
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
|
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
|
||||||
dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
|
dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
|
||||||
|
|
||||||
$(dir_out)/3ds/ReiNand:
|
$(dir_out)/3ds/$(name):
|
||||||
@mkdir -p "$(dir_out)/3ds/ReiNand"
|
@mkdir -p "$(dir_out)/3ds/$(name)"
|
||||||
@$(MAKE) -C $(dir_ninjhax)
|
@$(MAKE) $(FLAGS) -C $(dir_ninjhax)
|
||||||
@cp -av $(dir_ninjhax)/ReiNand.3dsx $@
|
@mv $(dir_out)/$(name).3dsx $@
|
||||||
@cp -av $(dir_ninjhax)/ReiNand.smdh $@
|
@mv $(dir_out)/$(name).smdh $@
|
||||||
|
|
||||||
$(dir_out)/rei/: $(dir_data)/firmware.bin $(dir_data)/splash.bin
|
$(dir_out)/rei/: $(dir_data)/firmware.bin $(dir_data)/splash.bin
|
||||||
@mkdir -p "$(dir_out)/rei"
|
@mkdir -p "$(dir_out)/rei"
|
||||||
|
@ -37,4 +37,6 @@ Pre-compiled version can still be found on my [pastebin](http://pastebin.com/c5A
|
|||||||
Normmatt for sdmmc.c and generally being helpful!
|
Normmatt for sdmmc.c and generally being helpful!
|
||||||
|
|
||||||
Me (Rei) for coding everything else.
|
Me (Rei) for coding everything else.
|
||||||
|
|
||||||
|
The community for your support and help!
|
||||||
|
|
BIN
data/splash.bin
BIN
data/splash.bin
Binary file not shown.
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
1
mset
1
mset
@ -1 +0,0 @@
|
|||||||
Subproject commit 1a62ee6dea17b0fb88224259d420ca7026bd636d
|
|
6
ninjhax/.gitignore
vendored
6
ninjhax/.gitignore
vendored
@ -1,6 +0,0 @@
|
|||||||
*.elf
|
|
||||||
*.3dsx
|
|
||||||
*.smdh
|
|
||||||
|
|
||||||
build
|
|
||||||
output
|
|
3
ninjhax/.gitmodules
vendored
3
ninjhax/.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "source/libkhax"]
|
|
||||||
path = source/libkhax
|
|
||||||
url = git://github.com/Myriachan/libkhax
|
|
179
ninjhax/Makefile
179
ninjhax/Makefile
@ -1,179 +0,0 @@
|
|||||||
#---------------------------------------------------------------------------------
|
|
||||||
.SUFFIXES:
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
ifeq ($(strip $(DEVKITARM)),)
|
|
||||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
|
||||||
endif
|
|
||||||
|
|
||||||
TOPDIR ?= $(CURDIR)
|
|
||||||
include $(DEVKITARM)/3ds_rules
|
|
||||||
|
|
||||||
# This should be set externally
|
|
||||||
name ?= reiNand.dat
|
|
||||||
filepath ?=
|
|
||||||
dir_out ?= $(CURDIR)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# TARGET is the name of the output
|
|
||||||
# BUILD is the directory where object files & intermediate files will be placed
|
|
||||||
# SOURCES is a list of directories containing source code
|
|
||||||
# DATA is a list of directories containing data files
|
|
||||||
# INCLUDES is a list of directories containing header files
|
|
||||||
#
|
|
||||||
# NO_SMDH: if set to anything, no SMDH file is generated.
|
|
||||||
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
|
|
||||||
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
|
|
||||||
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
|
|
||||||
# ICON is the filename of the icon (.png), relative to the project folder.
|
|
||||||
# If not set, it attempts to use one of the following (in this order):
|
|
||||||
# - <Project name>.png
|
|
||||||
# - icon.png
|
|
||||||
# - <libctru folder>/default_icon.png
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
TARGET := $(name:.dat=)
|
|
||||||
BUILD := build
|
|
||||||
SOURCES := source source/libkhax
|
|
||||||
DATA := data
|
|
||||||
INCLUDES := include
|
|
||||||
APP_TITLE ?= $(name:.dat=)
|
|
||||||
APP_DESCRIPTION ?= Privileged ARM11/ARM9 Code Execution
|
|
||||||
APP_AUTHOR ?= patois
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# options for code generation
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
|
||||||
|
|
||||||
CFLAGS := -g -Wall -Wextra -O3 -mword-relocations \
|
|
||||||
-fomit-frame-pointer -ffast-math \
|
|
||||||
$(ARCH)
|
|
||||||
|
|
||||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS -DARM_ARCH -DLAUNCHER_PATH='"$(filepath)$(name)"'
|
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
|
||||||
|
|
||||||
ASFLAGS := -g $(ARCH)
|
|
||||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
|
||||||
|
|
||||||
LIBS := -lctru -lm
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# list of directories containing libraries, this must be the top level containing
|
|
||||||
# include and lib
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
LIBDIRS := $(CTRULIB)
|
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# no real need to edit anything past this point unless you need to add additional
|
|
||||||
# rules for different file extensions
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
export OUTPUT := $(dir_out)/$(TARGET)
|
|
||||||
export TOPDIR := $(CURDIR)
|
|
||||||
|
|
||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
|
||||||
|
|
||||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
|
||||||
|
|
||||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
|
||||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
|
||||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ifeq ($(strip $(CPPFILES)),)
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
export LD := $(CC)
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
else
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
export LD := $(CXX)
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
endif
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
|
||||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
|
||||||
|
|
||||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
|
||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
|
||||||
-I$(CURDIR)/$(BUILD)
|
|
||||||
|
|
||||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
|
||||||
|
|
||||||
ifeq ($(strip $(ICON)),)
|
|
||||||
icons := $(wildcard *.png)
|
|
||||||
ifneq (,$(findstring $(TARGET).png,$(icons)))
|
|
||||||
export APP_ICON := $(TOPDIR)/$(TARGET).png
|
|
||||||
else
|
|
||||||
ifneq (,$(findstring icon.png,$(icons)))
|
|
||||||
export APP_ICON := $(TOPDIR)/icon.png
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
export APP_ICON := $(ICON)
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: $(BUILD) clean all
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
all: $(BUILD)
|
|
||||||
|
|
||||||
$(BUILD):
|
|
||||||
@echo $(SFILES)
|
|
||||||
@[ -d $@ ] || mkdir -p $@
|
|
||||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
clean:
|
|
||||||
@echo clean ...
|
|
||||||
@rm -fr $(BUILD) $(OUTPUT).3dsx $(OUTPUT).smdh
|
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
else
|
|
||||||
|
|
||||||
DEPENDS := $(OFILES:.o=.d)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# main targets
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ifeq ($(strip $(NO_SMDH)),)
|
|
||||||
.PHONY: all
|
|
||||||
all : $(OUTPUT).3dsx $(OUTPUT).smdh
|
|
||||||
endif
|
|
||||||
cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label
|
|
||||||
$(OUTPUT).3dsx : $(OFILES)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# you need a rule like this for each extension you use as binary data
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.bin.o : %.bin
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@$(bin2o)
|
|
||||||
|
|
||||||
# WARNING: This is not the right way to do this! TODO: Do it right!
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.vsh.o : %.vsh
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
|
|
||||||
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
|
|
||||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
|
|
||||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
|
||||||
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
|
||||||
@rm ../$(notdir $<).shbin
|
|
||||||
|
|
||||||
-include $(DEPENDS)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------------
|
|
||||||
endif
|
|
||||||
#---------------------------------------------------------------------------------------
|
|
@ -1,121 +0,0 @@
|
|||||||
Brahma - Privilege elevation exploit for the Nintendo 3DS
|
|
||||||
=========================================================
|
|
||||||
|
|
||||||
WTF is 'Brahma'?
|
|
||||||
----------------
|
|
||||||
Brahma is a development tool for the Nintendo 3DS platform that enables
|
|
||||||
privileged code execution on the ARM9 processor of the Nintendo 3DS platform.
|
|
||||||
It does so by exploiting two vulnerabilities in order to elevate its
|
|
||||||
privileges.
|
|
||||||
|
|
||||||
The exploits utilized by Brahma are based on "commercial" exploits that
|
|
||||||
have been reverse engineered. Brahma has been developed with the goal of
|
|
||||||
understanding and documenting the nature of the exploits in mind and has
|
|
||||||
been put further effort into during its development process in order to
|
|
||||||
achieve reliable exploitation and stability.
|
|
||||||
|
|
||||||
Brahma comes with full source code that is based on libctru and requires
|
|
||||||
existing user mode code execution privileges (Ninjhax), and can then be
|
|
||||||
used to further elevate privileges to ARM9 pre-kernel / SVC mode.
|
|
||||||
|
|
||||||
Also, "Brahma, the creator" is a god in hinduism that is often portrayed
|
|
||||||
with four heads and arms (heh... so funny :\).
|
|
||||||
|
|
||||||
How to build:
|
|
||||||
-------------
|
|
||||||
- Download and install devkitARM (http://devkitpro.org/wiki/Getting_Started)
|
|
||||||
- Open a shell and run make
|
|
||||||
|
|
||||||
How to use:
|
|
||||||
-----------
|
|
||||||
- Prebuilt binary releases are available at
|
|
||||||
https://github.com/patois/Brahma/releases
|
|
||||||
- Run brahma.3dsx (using homebrew launcher)
|
|
||||||
- By default, the exploit will attempt to gain ARM11 kernel privileges before
|
|
||||||
finally gaining ARM9 pre-kernel privileges (by performing a "firmlaunch")
|
|
||||||
|
|
||||||
"Hotkeys" (press and hold during startup of BRAHMA):
|
|
||||||
----------------------------------------------------
|
|
||||||
|
|
||||||
* LEFT : Loads 'arm9payload.bin' from the root folder of the 3DS' SD card
|
|
||||||
and executes it
|
|
||||||
|
|
||||||
* RIGHT : Performs a reboot / firm launch of the 3DS system
|
|
||||||
|
|
||||||
* NONE : Displays a menu which allows payload files to be received via
|
|
||||||
a WiFi network connection or loaded from the '/brahma' folder
|
|
||||||
located in the root folder of the SD card
|
|
||||||
|
|
||||||
In order to send payload files to the 3DS via a network connection,
|
|
||||||
the Python script '/tools/client.py' can be used. Alternatively, netcat
|
|
||||||
does the job as well.
|
|
||||||
|
|
||||||
Syntax:
|
|
||||||
-------
|
|
||||||
client.py: 'python client.py <3DS ip> <filename>'
|
|
||||||
netcat: 'nc <3DS ip> 80 < <filename>'
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
---------
|
|
||||||
client.py: 'python client.py 10.0.0.5 payload.bin'
|
|
||||||
netcat: 'nc 10.0.0.5 80 < payload.bin'
|
|
||||||
|
|
||||||
Example programs that run in privileged ARM9 mode can be downloaded from
|
|
||||||
https://github.com/patois/3DSProjects/tree/master/Brahma/
|
|
||||||
|
|
||||||
A memory dumper (3DSDevTools) for Brahma is available at
|
|
||||||
https://github.com/patois/3DSDevTools/releases
|
|
||||||
|
|
||||||
There is also a port of Decrypt9 by archshift which can be loaded using
|
|
||||||
bootstrap or Brahma (use 'make' to build the project, then use one of the
|
|
||||||
methods supported by Brahma to load the Decrypt9 payload). Decrypt9 can be
|
|
||||||
downloaded from https://github.com/archshift/Decrypt9/tree/bootstrap
|
|
||||||
|
|
||||||
Developers:
|
|
||||||
-----------
|
|
||||||
Brahma and its exploits which enable privileged ARM9 code execution
|
|
||||||
on the Nintendo 3DS may also be used as a "library" (#include "brahma.h")
|
|
||||||
|
|
||||||
- call brahma_init() - initializes Brahma
|
|
||||||
- call load_arm9_payload() - loads a payload binary from disk
|
|
||||||
- call firm_reboot() - executes a payload binary (privileged ARM9 code)
|
|
||||||
- (please check the source code for more features and options)
|
|
||||||
|
|
||||||
ARM9 payload must consist of valid ARM9 executable code and will be
|
|
||||||
mapped to physical address 0x23F00000 during run-time. Its code should begin
|
|
||||||
with a branch instruction at offset 0 and a 'placeholder' for a u32
|
|
||||||
variable at offset 4, which will be filled by Brahma with a backup of
|
|
||||||
the original ARM9 entry point of the FIRM header during runtime.
|
|
||||||
|
|
||||||
Brahma is written in a way that allows developers of payload binaries
|
|
||||||
to easily return control to the 3DS' firmware by simply returning from
|
|
||||||
the main() function of the payload.
|
|
||||||
|
|
||||||
This allows reading and altering of memory contents, such as the mapped
|
|
||||||
Nintendo firmware (including ARM9 kernel, Process9, ARM11 kernel and several
|
|
||||||
processes running on the ARM11 core), for testing purposes, without requiring
|
|
||||||
any changes on the file system level.
|
|
||||||
|
|
||||||
Credits:
|
|
||||||
--------
|
|
||||||
- To 3dbrew.org and all its contributors for being such a great resource
|
|
||||||
- To whomever initially found the vulnerabilities and wrote the publicly
|
|
||||||
available exploit code
|
|
||||||
- To everybody who's been working on porting this exploit and its various
|
|
||||||
"bootstrap" branches to newer firmware versions and improving its stability
|
|
||||||
(in particular yifanlu, yuriks and shinyquagsire23)
|
|
||||||
- To everybody involved in creating libctru, Ninjhax and the Homebrew Menu
|
|
||||||
|
|
||||||
Disclaimer:
|
|
||||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
|
||||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS
|
|
||||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
(c) 2015, patois
|
|
@ -1,23 +0,0 @@
|
|||||||
CakeBrah
|
|
||||||
========
|
|
||||||
|
|
||||||
This is a fork of Brahma, that loads CakeHax payloads in the environment they expect.
|
|
||||||
This means mostly setting the framebuffer offsets and mode right.
|
|
||||||
|
|
||||||
How to use this in your project
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
Look at [CakeHax](https://github.com/mid-kid/CakeHax) for this. It's pretty much the same.
|
|
||||||
No injection with dd is needed, as it loads the payload from your .dat file.
|
|
||||||
The different configuration flags are detailed below.
|
|
||||||
|
|
||||||
### Makefile options
|
|
||||||
|
|
||||||
Name |Default |Description
|
|
||||||
----------------|------------------------------------|-----------
|
|
||||||
dir\_out |$(CURDIR) |Where the output files should be placed (3dsx and smdh).
|
|
||||||
name |Cakes.dat |The name of the .dat file from which the payload will be loaded.
|
|
||||||
filepath | |Path in the SD card where the .dat file is located.
|
|
||||||
APP\_TITLE |Cakes |The title of the app shown in the Homebrew Menu.
|
|
||||||
APP\_DESCRIPTION|Privileged ARM11/ARM9 Code Execution|The description of the app shown in the Homebrew Menu.
|
|
||||||
APP\_AUTHOR |patois |The author of the app shown in the Homebrew Menu.
|
|
@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "exploitdata.h"
|
|
||||||
|
|
||||||
u32 brahma_init (void);
|
|
||||||
u32 brahma_exit (void);
|
|
||||||
s32 load_arm9_payload_offset (char *filename, u32 offset, u32 max_psize);
|
|
||||||
s32 load_arm9_payload_from_mem (u8* data, u32 dsize);
|
|
||||||
void redirect_codeflow (u32 *dst_addr, u32 *src_addr);
|
|
||||||
s32 map_arm9_payload (void);
|
|
||||||
s32 map_arm11_payload (void);
|
|
||||||
void exploit_arm9_race_condition (void);
|
|
||||||
s32 get_exploit_data (struct exploit_data *data);
|
|
||||||
s32 firm_reboot ();
|
|
||||||
|
|
||||||
#define load_arm9_payload(filename) load_arm9_payload_offset(filename, 0, 0)
|
|
||||||
|
|
||||||
#define BRAHMA_NETWORK_PORT 80
|
|
||||||
|
|
||||||
#define ARM_JUMPOUT 0xE51FF004 // LDR PC, [PC, -#04]
|
|
||||||
#define ARM_RET 0xE12FFF1E // BX LR
|
|
||||||
#define ARM_NOP 0xE1A00000 // NOP
|
|
||||||
|
|
||||||
extern void *arm11_start;
|
|
||||||
extern void *arm11_end;
|
|
||||||
extern void *arm9_start;
|
|
||||||
extern void *arm9_end;
|
|
@ -1,189 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define SYS_MODEL_NONE 0
|
|
||||||
#define SYS_MODEL_OLD_3DS 1
|
|
||||||
#define SYS_MODEL_NEW_3DS 2
|
|
||||||
|
|
||||||
#define PA_EXC_HANDLER_BASE 0x1FFF4000
|
|
||||||
#define PA_FCRAM_BASE 0x20000000
|
|
||||||
#define OFFS_FCRAM_MAPPED_FIRM 0x04000000
|
|
||||||
#define OFFS_FCRAM_ARM9_PAYLOAD 0x03F00000
|
|
||||||
#define OFFS_EXC_HANDLER_UNUSED 0xC80
|
|
||||||
#if OFFS_FCRAM_ARM9_PAYLOAD >= OFFS_FCRAM_MAPPED_FIRM
|
|
||||||
#error ERRROR: Invalid ARM9 payload offset
|
|
||||||
#endif
|
|
||||||
#define ARM9_PAYLOAD_MAX_SIZE (OFFS_FCRAM_MAPPED_FIRM - OFFS_FCRAM_ARM9_PAYLOAD)
|
|
||||||
|
|
||||||
/* any changes to this structure must also be applied to
|
|
||||||
the data structure following the 'arm11_globals_start'
|
|
||||||
label of arm11.s */
|
|
||||||
struct arm11_shared_data {
|
|
||||||
u32 va_pdn_regs;
|
|
||||||
u32 va_pxi_regs;
|
|
||||||
u32 va_hook1_ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exploit_data {
|
|
||||||
|
|
||||||
u32 firm_version;
|
|
||||||
u32 sys_model; // mask
|
|
||||||
|
|
||||||
u32 va_patch_hook1;
|
|
||||||
u32 va_patch_hook2;
|
|
||||||
u32 va_hook1_ret;
|
|
||||||
|
|
||||||
u32 va_fcram_base;
|
|
||||||
u32 va_exc_handler_base_W;
|
|
||||||
u32 va_exc_handler_base_X;
|
|
||||||
u32 va_kernelsetstate;
|
|
||||||
|
|
||||||
u32 va_pdn_regs;
|
|
||||||
u32 va_pxi_regs;
|
|
||||||
};
|
|
||||||
|
|
||||||
// add all vulnerable systems below
|
|
||||||
static const struct exploit_data supported_systems[] = {
|
|
||||||
{
|
|
||||||
0x022E0000, // FIRM version
|
|
||||||
SYS_MODEL_NEW_3DS, // model
|
|
||||||
0xDFFE7A50, // VA of 1st hook for firmlaunch
|
|
||||||
0xDFFF4994, // VA of 2nd hook for firmlaunch
|
|
||||||
0xFFF28A58, // VA of return address from 1st hook
|
|
||||||
0xE0000000, // VA of FCRAM
|
|
||||||
0xDFFF4000, // VA of lower mapped exception handler base
|
|
||||||
0xFFFF0000, // VA of upper mapped exception handler base
|
|
||||||
0xFFF158F8, // VA of the KernelSetState syscall (upper mirror)
|
|
||||||
0xFFFBE000, // VA PDN registers
|
|
||||||
0xFFFC0000 // VA PXI registers
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x022C0600, // FIRM version
|
|
||||||
SYS_MODEL_NEW_3DS, // model
|
|
||||||
0xDFFE7A50, // VA of 1st hook for firmlaunch
|
|
||||||
0xDFFF4994, // VA of 2nd hook for firmlaunch
|
|
||||||
0xFFF28A58, // VA of return address from 1st hook
|
|
||||||
0xE0000000, // VA of FCRAM
|
|
||||||
0xDFFF4000, // VA of lower mapped exception handler base
|
|
||||||
0xFFFF0000, // VA of upper mapped exception handler base
|
|
||||||
0xFFF158F8, // VA of the KernelSetState syscall (upper mirror)
|
|
||||||
0xFFFBE000, // VA PDN registers
|
|
||||||
0xFFFC0000 // VA PXI registers
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x02220000,
|
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
|
||||||
0xEFFE4DD4,
|
|
||||||
0xEFFF497C,
|
|
||||||
0xFFF84DDC,
|
|
||||||
0xF0000000,
|
|
||||||
0xEFFF4000,
|
|
||||||
0xFFFF0000,
|
|
||||||
0xFFF748C4,
|
|
||||||
0xFFFD0000,
|
|
||||||
0xFFFD2000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x02230600,
|
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
|
||||||
0xEFFE55BC,
|
|
||||||
0xEFFF4978,
|
|
||||||
0xFFF765C4,
|
|
||||||
0xF0000000,
|
|
||||||
0xEFFF4000,
|
|
||||||
0xFFFF0000,
|
|
||||||
0xFFF64B94,
|
|
||||||
0xFFFD0000,
|
|
||||||
0xFFFD2000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x022E0000,
|
|
||||||
SYS_MODEL_OLD_3DS,
|
|
||||||
0xDFFE59D0,
|
|
||||||
0xDFFF4974,
|
|
||||||
0xFFF279D8,
|
|
||||||
0xE0000000,
|
|
||||||
0xDFFF4000,
|
|
||||||
0xFFFF0000,
|
|
||||||
0xFFF151C0,
|
|
||||||
0xFFFC2000,
|
|
||||||
0xFFFC4000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x022C0600,
|
|
||||||
SYS_MODEL_OLD_3DS,
|
|
||||||
0xDFFE4F28,
|
|
||||||
0xDFFF4974,
|
|
||||||
0xFFF66F30,
|
|
||||||
0xE0000000,
|
|
||||||
0xDFFF4000,
|
|
||||||
0xFFFF0000,
|
|
||||||
0xFFF54BAC,
|
|
||||||
0xFFFBE000,
|
|
||||||
0xFFFC0000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x02280000,
|
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
|
||||||
0xEFFE5B30,
|
|
||||||
0xEFFF4978,
|
|
||||||
0xFFF76B38,
|
|
||||||
0xF0000000,
|
|
||||||
0xEFFF4000,
|
|
||||||
0xFFFF0000,
|
|
||||||
0xFFF64AAC,
|
|
||||||
0xFFFD0000,
|
|
||||||
0xFFFD2000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x02270400,
|
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
|
||||||
0xEFFE5B34,
|
|
||||||
0xEFFF4978,
|
|
||||||
0xFFF76B3C,
|
|
||||||
0xF0000000,
|
|
||||||
0xEFFF4000,
|
|
||||||
0xFFFF0000,
|
|
||||||
0xFFF64AB0,
|
|
||||||
0xFFFD0000,
|
|
||||||
0xFFFD2000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x02250000,
|
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
|
||||||
0xEFFE5AE8,
|
|
||||||
0xEFFF4978,
|
|
||||||
0xFFF76AF0,
|
|
||||||
0xF0000000,
|
|
||||||
0xEFFF4000,
|
|
||||||
0xFFFF0000,
|
|
||||||
0xFFF64A78,
|
|
||||||
0xFFFD0000,
|
|
||||||
0xFFFD2000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x02260000,
|
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
|
||||||
0xEFFE5AE8,
|
|
||||||
0xEFFF4978,
|
|
||||||
0xFFF76AF0,
|
|
||||||
0xF0000000,
|
|
||||||
0xEFFF4000,
|
|
||||||
0xFFFF0000,
|
|
||||||
0xFFF64A78,
|
|
||||||
0xFFFD0000,
|
|
||||||
0xFFFD2000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0x02240000,
|
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
|
||||||
0xEFFE55B8,
|
|
||||||
0xEFFF4978,
|
|
||||||
0xFFF765C0,
|
|
||||||
0xF0000000,
|
|
||||||
0xEFFF4000,
|
|
||||||
0xFFFF0000,
|
|
||||||
0xFFF64B90,
|
|
||||||
0xFFFD0000,
|
|
||||||
0xFFFD2000
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,4 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
u32 wait_key (void);
|
|
||||||
void wait_any_key (void);
|
|
@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
void InvalidateEntireInstructionCache (void);
|
|
||||||
void CleanEntireDataCache (void);
|
|
||||||
void dsb(void);
|
|
||||||
void DisableInterrupts (void);
|
|
||||||
void EnableInterrupts (void);
|
|
||||||
void InvalidateEntireDataCache (void);
|
|
@ -1,173 +0,0 @@
|
|||||||
.arm
|
|
||||||
.align 4
|
|
||||||
.code 32
|
|
||||||
.text
|
|
||||||
|
|
||||||
.global arm11_start
|
|
||||||
arm11_start:
|
|
||||||
B hook1
|
|
||||||
B hook2
|
|
||||||
|
|
||||||
hook1:
|
|
||||||
STMFD SP!, {R0-R12,LR}
|
|
||||||
|
|
||||||
MOV R0, #64
|
|
||||||
BL delay
|
|
||||||
|
|
||||||
MOV R0, #0
|
|
||||||
BL pxi_send
|
|
||||||
|
|
||||||
BL pxi_sync
|
|
||||||
|
|
||||||
MOV R0, #0x10000
|
|
||||||
BL pxi_send
|
|
||||||
|
|
||||||
BL pxi_recv
|
|
||||||
BL pxi_recv
|
|
||||||
BL pxi_recv
|
|
||||||
|
|
||||||
MOV R0, #2
|
|
||||||
BL pdn_send
|
|
||||||
|
|
||||||
MOV R0, #0
|
|
||||||
BL pdn_send
|
|
||||||
|
|
||||||
LDMFD SP!, {R0-R12,LR}
|
|
||||||
|
|
||||||
LDR R0, var_44836
|
|
||||||
STR R0, [R1]
|
|
||||||
LDR PC, va_hook1_ret
|
|
||||||
|
|
||||||
var_44836: .long 0x44836
|
|
||||||
|
|
||||||
@ copy hijack_arm9 routine and execute
|
|
||||||
hook2:
|
|
||||||
ADR R0, hijack_arm9
|
|
||||||
ADR R1, hijack_arm9_end
|
|
||||||
LDR R2, pa_hijack_arm9_dst
|
|
||||||
MOV R4, R2
|
|
||||||
BL copy_mem
|
|
||||||
MOV r0, #0
|
|
||||||
MCR p15, 0, r0, c7, c10, 0 @ Clean data cache
|
|
||||||
MCR p15, 0, r0, c7, c10, 4 @ Drain write buffer
|
|
||||||
MCR p15, 0, r0, c7, c5, 0 @ Flush instruction cache
|
|
||||||
BX R4
|
|
||||||
|
|
||||||
@ exploits a race condition in order
|
|
||||||
@ to take control over the arm9 core
|
|
||||||
hijack_arm9:
|
|
||||||
@ init
|
|
||||||
LDR R0, pa_arm11_code
|
|
||||||
MOV R1, #0
|
|
||||||
STR R1, [R0]
|
|
||||||
|
|
||||||
@ load physical addresses
|
|
||||||
LDR R10, pa_firm_header
|
|
||||||
LDR R9, pa_arm9_payload
|
|
||||||
LDR R8, pa_io_mem
|
|
||||||
|
|
||||||
@ send pxi cmd 0x44846
|
|
||||||
LDR R1, pa_pxi_regs
|
|
||||||
LDR R2, some_pxi_cmd
|
|
||||||
STR R2, [R1, #8]
|
|
||||||
|
|
||||||
wait_arm9_loop:
|
|
||||||
LDRB R0, [R8]
|
|
||||||
ANDS R0, R0, #1
|
|
||||||
BNE wait_arm9_loop
|
|
||||||
|
|
||||||
@ overwrite orig entry point with FCRAM addr
|
|
||||||
@ this exploits the race condition bug
|
|
||||||
STR R9, [R10, #0x0C]
|
|
||||||
|
|
||||||
LDR R0, pa_arm11_code
|
|
||||||
wait_arm11_loop:
|
|
||||||
LDR R1, [r0]
|
|
||||||
CMP R1, #0
|
|
||||||
BEQ wait_arm11_loop
|
|
||||||
BX R1
|
|
||||||
|
|
||||||
pa_hijack_arm9_dst: .long 0x1FFFFC00
|
|
||||||
pa_arm11_code: .long 0x1FFFFFF8
|
|
||||||
pa_pxi_regs: .long 0x10163000
|
|
||||||
some_pxi_cmd: .long 0x44846
|
|
||||||
pa_firm_header: .long 0x24000000
|
|
||||||
pa_arm9_payload: .long 0x23F00000
|
|
||||||
pa_io_mem: .long 0x10140000
|
|
||||||
hijack_arm9_end:
|
|
||||||
|
|
||||||
copy_mem:
|
|
||||||
SUB R3, R1, R0
|
|
||||||
MOV R1, R3,ASR#2
|
|
||||||
CMP R1, #0
|
|
||||||
BLE locret_FFFF0AC0
|
|
||||||
MOVS R1, R3,LSL#29
|
|
||||||
SUB R0, R0, #4
|
|
||||||
SUB R1, R2, #4
|
|
||||||
BPL loc_FFFF0AA0
|
|
||||||
LDR R2, [R0,#4]!
|
|
||||||
STR R2, [R1,#4]!
|
|
||||||
loc_FFFF0AA0:
|
|
||||||
MOVS R2, R3,ASR#3
|
|
||||||
BEQ locret_FFFF0AC0
|
|
||||||
loc_FFFF0AA8:
|
|
||||||
LDR R3, [R0,#4]
|
|
||||||
SUBS R2, R2, #1
|
|
||||||
STR R3, [R1,#4]
|
|
||||||
LDR R3, [R0,#8]!
|
|
||||||
STR R3, [R1,#8]!
|
|
||||||
BNE loc_FFFF0AA8
|
|
||||||
locret_FFFF0AC0:
|
|
||||||
BX LR
|
|
||||||
|
|
||||||
pdn_send:
|
|
||||||
LDR R1, va_pdn_regs
|
|
||||||
STRB R0, [R1, #0x230]
|
|
||||||
BX LR
|
|
||||||
|
|
||||||
pxi_send:
|
|
||||||
LDR R1, va_pxi_regs
|
|
||||||
loc_1020D0:
|
|
||||||
LDRH R2, [R1,#4]
|
|
||||||
TST R2, #2
|
|
||||||
BNE loc_1020D0
|
|
||||||
STR R0, [R1,#8]
|
|
||||||
|
|
||||||
MOV R0, #4
|
|
||||||
delay:
|
|
||||||
MOV R1, #0
|
|
||||||
MCR p15, 0, r1, c7, c10, 0
|
|
||||||
MCR p15, 0, r1, c7, c10, 4
|
|
||||||
loop:
|
|
||||||
SUBS R0, #1
|
|
||||||
BGT loop
|
|
||||||
BX LR
|
|
||||||
|
|
||||||
pxi_recv:
|
|
||||||
LDR R0, va_pxi_regs
|
|
||||||
loc_1020FC:
|
|
||||||
LDRH R1, [R0,#4]
|
|
||||||
TST R1, #0x100
|
|
||||||
BNE loc_1020FC
|
|
||||||
LDR R0, [R0,#0xC]
|
|
||||||
BX LR
|
|
||||||
|
|
||||||
pxi_sync:
|
|
||||||
LDR R0, va_pxi_regs
|
|
||||||
LDRB R1, [R0,#3]
|
|
||||||
ORR R1, R1, #0x40
|
|
||||||
STRB R1, [R0,#3]
|
|
||||||
BX LR
|
|
||||||
|
|
||||||
.global arm11_end
|
|
||||||
arm11_end:
|
|
||||||
|
|
||||||
.global arm11_globals_start
|
|
||||||
arm11_globals_start:
|
|
||||||
|
|
||||||
va_pdn_regs: .long 0
|
|
||||||
va_pxi_regs: .long 0
|
|
||||||
va_hook1_ret: .long 0
|
|
||||||
|
|
||||||
.global arm11_globals_end
|
|
||||||
arm11_globals_end:
|
|
@ -1,380 +0,0 @@
|
|||||||
#include <3ds.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/_default_fcntl.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include "brahma.h"
|
|
||||||
#include "exploitdata.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "libkhax/khax.h"
|
|
||||||
|
|
||||||
static u8 *g_ext_arm9_buf;
|
|
||||||
static u32 g_ext_arm9_size = 0;
|
|
||||||
static s32 g_ext_arm9_loaded = 0;
|
|
||||||
static struct exploit_data g_expdata;
|
|
||||||
static struct arm11_shared_data g_arm11shared;
|
|
||||||
u32 frameBufferData[3];
|
|
||||||
|
|
||||||
/* should be the very first call. allocates heap buffer
|
|
||||||
for ARM9 payload */
|
|
||||||
u32 brahma_init (void) {
|
|
||||||
g_ext_arm9_buf = memalign(0x1000, ARM9_PAYLOAD_MAX_SIZE);
|
|
||||||
return (g_ext_arm9_buf != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* call upon exit */
|
|
||||||
u32 brahma_exit (void) {
|
|
||||||
if (g_ext_arm9_buf) {
|
|
||||||
free(g_ext_arm9_buf);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* overwrites two instructions (8 bytes in total) at src_addr
|
|
||||||
with code that redirects execution to dst_addr */
|
|
||||||
void redirect_codeflow (u32 *dst_addr, u32 *src_addr) {
|
|
||||||
*(src_addr + 1) = (u32)dst_addr;
|
|
||||||
*src_addr = ARM_JUMPOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fills exploit_data structure with information that is specific
|
|
||||||
to 3DS model and firmware version
|
|
||||||
returns: 0 on failure, 1 on success */
|
|
||||||
s32 get_exploit_data (struct exploit_data *data) {
|
|
||||||
u32 fversion = 0;
|
|
||||||
u8 isN3DS = 0;
|
|
||||||
u32 i;
|
|
||||||
s32 result = 0;
|
|
||||||
u32 sysmodel = SYS_MODEL_NONE;
|
|
||||||
|
|
||||||
if(!data)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
fversion = osGetFirmVersion();
|
|
||||||
APT_CheckNew3DS(&isN3DS);
|
|
||||||
sysmodel = isN3DS ? SYS_MODEL_NEW_3DS : SYS_MODEL_OLD_3DS;
|
|
||||||
|
|
||||||
/* copy platform and firmware dependent data */
|
|
||||||
for(i = 0; i < sizeof(supported_systems) / sizeof(supported_systems[0]); i++) {
|
|
||||||
if (supported_systems[i].firm_version == fversion &&
|
|
||||||
supported_systems[i].sys_model & sysmodel) {
|
|
||||||
memcpy(data, &supported_systems[i], sizeof(struct exploit_data));
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get system dependent data and set up ARM11 structures */
|
|
||||||
s32 setup_exploit_data (void) {
|
|
||||||
s32 result = 0;
|
|
||||||
|
|
||||||
if (get_exploit_data(&g_expdata)) {
|
|
||||||
/* copy data required by code running in ARM11 svc mode */
|
|
||||||
g_arm11shared.va_hook1_ret = g_expdata.va_hook1_ret;
|
|
||||||
g_arm11shared.va_pdn_regs = g_expdata.va_pdn_regs;
|
|
||||||
g_arm11shared.va_pxi_regs = g_expdata.va_pxi_regs;
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: network code might be moved somewhere else */
|
|
||||||
s32 recv_arm9_payload (void) {
|
|
||||||
s32 sockfd;
|
|
||||||
struct sockaddr_in sa;
|
|
||||||
u32 kDown, old_kDown;
|
|
||||||
s32 clientfd;
|
|
||||||
struct sockaddr_in client_addr;
|
|
||||||
u32 addrlen = sizeof(client_addr);
|
|
||||||
s32 sflags = 0;
|
|
||||||
|
|
||||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
||||||
printf("[!] Error: socket()\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bzero(&sa, sizeof(sa));
|
|
||||||
sa.sin_family = AF_INET;
|
|
||||||
sa.sin_port = htons(BRAHMA_NETWORK_PORT);
|
|
||||||
sa.sin_addr.s_addr = gethostid();
|
|
||||||
|
|
||||||
if (bind(sockfd, (struct sockaddr*)&sa, sizeof(sa)) != 0) {
|
|
||||||
printf("[!] Error: bind()\n");
|
|
||||||
close(sockfd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listen(sockfd, 1) != 0) {
|
|
||||||
printf("[!] Error: listen()\n");
|
|
||||||
close(sockfd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("[x] IP %s:%d\n", inet_ntoa(sa.sin_addr), BRAHMA_NETWORK_PORT);
|
|
||||||
|
|
||||||
g_ext_arm9_size = 0;
|
|
||||||
g_ext_arm9_loaded = 0;
|
|
||||||
|
|
||||||
sflags = fcntl(sockfd, F_GETFL);
|
|
||||||
if (sflags == -1) {
|
|
||||||
printf("[!] Error: fcntl() (1)\n");
|
|
||||||
close(sockfd);
|
|
||||||
}
|
|
||||||
fcntl(sockfd, F_SETFL, sflags | O_NONBLOCK);
|
|
||||||
|
|
||||||
hidScanInput();
|
|
||||||
old_kDown = hidKeysDown();
|
|
||||||
while (1) {
|
|
||||||
hidScanInput();
|
|
||||||
kDown = hidKeysDown();
|
|
||||||
if (kDown != old_kDown) {
|
|
||||||
printf("[!] Aborted\n");
|
|
||||||
close(sockfd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);
|
|
||||||
svcSleepThread(100000000);
|
|
||||||
if (clientfd > 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("[x] Connection from %s:%d\n\n", inet_ntoa(client_addr.sin_addr),
|
|
||||||
ntohs(client_addr.sin_port));
|
|
||||||
|
|
||||||
s32 recvd;
|
|
||||||
u32 total = 0;
|
|
||||||
s32 overflow = 0;
|
|
||||||
while ((recvd = recv(clientfd, g_ext_arm9_buf + total,
|
|
||||||
ARM9_PAYLOAD_MAX_SIZE - total, 0)) != 0) {
|
|
||||||
if (recvd != -1) {
|
|
||||||
total += recvd;
|
|
||||||
printf(".");
|
|
||||||
}
|
|
||||||
if (total >= ARM9_PAYLOAD_MAX_SIZE) {
|
|
||||||
overflow = 1;
|
|
||||||
printf("[!] Error: invalid payload size\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fcntl(sockfd, F_SETFL, sflags & ~O_NONBLOCK);
|
|
||||||
|
|
||||||
printf("\n\n[x] Received %u bytes in total\n", (unsigned int)total);
|
|
||||||
g_ext_arm9_size = overflow ? 0 : total;
|
|
||||||
g_ext_arm9_loaded = (g_ext_arm9_size != 0);
|
|
||||||
|
|
||||||
close(clientfd);
|
|
||||||
close(sockfd);
|
|
||||||
|
|
||||||
return g_ext_arm9_loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reads ARM9 payload from a given path.
|
|
||||||
filename: full path of payload
|
|
||||||
offset: offset of the payload in the file
|
|
||||||
max_psize: the maximum size of the payload that should be loaded (if 0, ARM9_MAX_PAYLOAD_SIZE. Should be smaller than ARM9_MAX_PAYLOAD_SIZE)
|
|
||||||
returns: 0 on failure, 1 on success */
|
|
||||||
s32 load_arm9_payload_offset (char *filename, u32 offset, u32 max_psize) {
|
|
||||||
s32 result = 0;
|
|
||||||
u32 fsize = 0;
|
|
||||||
u32 psize = 0;
|
|
||||||
|
|
||||||
if (max_psize == 0 || max_psize > ARM9_PAYLOAD_MAX_SIZE)
|
|
||||||
max_psize = ARM9_PAYLOAD_MAX_SIZE;
|
|
||||||
|
|
||||||
if (!filename)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
FILE *f = fopen(filename, "rb");
|
|
||||||
if (f) {
|
|
||||||
fseek(f , 0, SEEK_END);
|
|
||||||
fsize = ftell(f);
|
|
||||||
|
|
||||||
if (offset < fsize) {
|
|
||||||
psize = fsize - offset;
|
|
||||||
if (psize > max_psize)
|
|
||||||
psize = max_psize;
|
|
||||||
|
|
||||||
g_ext_arm9_size = psize;
|
|
||||||
|
|
||||||
fseek(f, offset, SEEK_SET);
|
|
||||||
if (psize >= 8) {
|
|
||||||
u32 bytes_read = fread(g_ext_arm9_buf, 1, psize, f);
|
|
||||||
result = (g_ext_arm9_loaded = (bytes_read == psize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reads ARM9 payload from memory.
|
|
||||||
data: array of u8 containing the payload
|
|
||||||
dsize: size of the data array
|
|
||||||
returns: 0 on failure, 1 on success */
|
|
||||||
s32 load_arm9_payload_from_mem (u8* data, u32 dsize) {
|
|
||||||
s32 result = 0;
|
|
||||||
|
|
||||||
if ((data != NULL) && (dsize >= 8) && (dsize <= ARM9_PAYLOAD_MAX_SIZE)) {
|
|
||||||
g_ext_arm9_size = dsize;
|
|
||||||
memcpy(g_ext_arm9_buf, data, dsize);
|
|
||||||
result = g_ext_arm9_loaded = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copies ARM9 payload to FCRAM
|
|
||||||
- before overwriting it in memory, Brahma creates a backup copy of
|
|
||||||
the mapped firm binary's ARM9 entry point. The copy will be stored
|
|
||||||
into offset 4 of the ARM9 payload during run-time.
|
|
||||||
This allows the ARM9 payload to resume booting the Nintendo firmware
|
|
||||||
code.
|
|
||||||
Thus, the format of ARM9 payload written for Brahma is the following:
|
|
||||||
- a branch instruction at offset 0 and
|
|
||||||
- a placeholder (u32) at offset 4 (=ARM9 entrypoint) */
|
|
||||||
s32 map_arm9_payload (void) {
|
|
||||||
void *src;
|
|
||||||
volatile void *dst;
|
|
||||||
|
|
||||||
u32 size = 0;
|
|
||||||
s32 result = 0;
|
|
||||||
|
|
||||||
dst = (void *)(g_expdata.va_fcram_base + OFFS_FCRAM_ARM9_PAYLOAD);
|
|
||||||
|
|
||||||
if (!g_ext_arm9_loaded) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// external ARM9 payload
|
|
||||||
src = g_ext_arm9_buf;
|
|
||||||
size = g_ext_arm9_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size <= ARM9_PAYLOAD_MAX_SIZE) {
|
|
||||||
memcpy((void *)dst, src, size);
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 map_arm11_payload (void) {
|
|
||||||
void *src;
|
|
||||||
volatile void *dst;
|
|
||||||
u32 size = 0;
|
|
||||||
u32 offs;
|
|
||||||
s32 result_a = 0;
|
|
||||||
s32 result_b = 0;
|
|
||||||
|
|
||||||
src = &arm11_start;
|
|
||||||
dst = (void *)(g_expdata.va_exc_handler_base_W + OFFS_EXC_HANDLER_UNUSED);
|
|
||||||
size = (u8 *)&arm11_end - (u8 *)&arm11_start;
|
|
||||||
|
|
||||||
// TODO: sanitize 'size'
|
|
||||||
if (size) {
|
|
||||||
memcpy((void *)dst, src, size);
|
|
||||||
result_a = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
offs = size;
|
|
||||||
src = &g_arm11shared;
|
|
||||||
size = sizeof(g_arm11shared);
|
|
||||||
|
|
||||||
dst = (u8 *)(g_expdata.va_exc_handler_base_W +
|
|
||||||
OFFS_EXC_HANDLER_UNUSED + offs);
|
|
||||||
|
|
||||||
// TODO sanitize 'size'
|
|
||||||
if (result_a && size) {
|
|
||||||
memcpy((void *)dst, src, size);
|
|
||||||
result_b = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result_a && result_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void exploit_arm9_race_condition (void) {
|
|
||||||
|
|
||||||
s32 (* const _KernelSetState)(u32, u32, u32, u32) =
|
|
||||||
(void *)g_expdata.va_kernelsetstate;
|
|
||||||
|
|
||||||
asm volatile ("clrex");
|
|
||||||
|
|
||||||
/* copy ARM11 payload and console specific data */
|
|
||||||
if (map_arm11_payload() &&
|
|
||||||
/* copy ARM9 payload to FCRAM */
|
|
||||||
map_arm9_payload()) {
|
|
||||||
|
|
||||||
/* patch ARM11 kernel to force it to execute
|
|
||||||
our code (hook1 and hook2) as soon as a
|
|
||||||
"firmlaunch" is triggered */
|
|
||||||
redirect_codeflow((u32 *)(g_expdata.va_exc_handler_base_X +
|
|
||||||
OFFS_EXC_HANDLER_UNUSED),
|
|
||||||
(u32 *)g_expdata.va_patch_hook1);
|
|
||||||
|
|
||||||
redirect_codeflow((u32 *)(PA_EXC_HANDLER_BASE +
|
|
||||||
OFFS_EXC_HANDLER_UNUSED + 4),
|
|
||||||
(u32 *)g_expdata.va_patch_hook2);
|
|
||||||
|
|
||||||
CleanEntireDataCache();
|
|
||||||
dsb();
|
|
||||||
InvalidateEntireInstructionCache();
|
|
||||||
|
|
||||||
// trigger ARM9 code execution through "firmlaunch"
|
|
||||||
_KernelSetState(0, 0, 2, 0);
|
|
||||||
// prev call shouldn't ever return
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* restore svcCreateThread code (not really required,
|
|
||||||
but just to be on the safe side) */
|
|
||||||
s32 priv_firm_reboot (void) {
|
|
||||||
__asm__ volatile ("cpsid aif");
|
|
||||||
|
|
||||||
// Save the framebuffers for arm9,
|
|
||||||
u32 *save = (u32 *)(g_expdata.va_fcram_base + 0x3FFFE00);
|
|
||||||
memcpy(save, frameBufferData, sizeof(u32) * sizeof(frameBufferData));
|
|
||||||
|
|
||||||
exploit_arm9_race_condition();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* perform firmlaunch. load ARM9 payload before calling this
|
|
||||||
function. otherwise, calling this function simply reboots
|
|
||||||
the handheld */
|
|
||||||
s32 firm_reboot (void) {
|
|
||||||
s32 fail_stage = 0;
|
|
||||||
|
|
||||||
// Make sure gfx is initialized
|
|
||||||
gfxInitDefault();
|
|
||||||
|
|
||||||
// Save the framebuffers for arm11.
|
|
||||||
frameBufferData[0] = (u32)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL) + 0xC000000;
|
|
||||||
frameBufferData[1] = (u32)gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL) + 0xC000000;
|
|
||||||
frameBufferData[2] = (u32)gfxGetFramebuffer(GFX_BOTTOM, 0, NULL, NULL) + 0xC000000;
|
|
||||||
gfxSwapBuffers();
|
|
||||||
|
|
||||||
fail_stage++; /* platform or firmware not supported, ARM11 exploit failure */
|
|
||||||
if (setup_exploit_data()) {
|
|
||||||
fail_stage++; /* failure while trying to corrupt svcCreateThread() */
|
|
||||||
if (khaxInit() == 0) {
|
|
||||||
fail_stage++; /* Firmlaunch failure, ARM9 exploit failure*/
|
|
||||||
svcBackdoor(priv_firm_reboot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we do not intend to return ... */
|
|
||||||
return fail_stage;
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
#include <3ds.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
/* loop until key is pressed */
|
|
||||||
void wait_key (void) {
|
|
||||||
hidScanInput();
|
|
||||||
u32 old_kDown, kDown;
|
|
||||||
old_kDown = hidKeysDown();
|
|
||||||
|
|
||||||
while (aptMainLoop()) {
|
|
||||||
gspWaitForVBlank();
|
|
||||||
|
|
||||||
hidScanInput();
|
|
||||||
kDown = hidKeysDown();
|
|
||||||
if (kDown != old_kDown)
|
|
||||||
break;
|
|
||||||
|
|
||||||
gfxFlushBuffers();
|
|
||||||
gfxSwapBuffers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convenience function */
|
|
||||||
void wait_any_key (void) {
|
|
||||||
printf("\n\nPress key to continue\n");
|
|
||||||
wait_key();
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2015 Myriachan
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
@ -1,177 +0,0 @@
|
|||||||
#---------------------------------------------------------------------------------
|
|
||||||
.SUFFIXES:
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
ifeq ($(strip $(DEVKITARM)),)
|
|
||||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
|
||||||
endif
|
|
||||||
|
|
||||||
TOPDIR ?= $(CURDIR)
|
|
||||||
include $(DEVKITARM)/3ds_rules
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# TARGET is the name of the output
|
|
||||||
# BUILD is the directory where object files & intermediate files will be placed
|
|
||||||
# SOURCES is a list of directories containing source code
|
|
||||||
# DATA is a list of directories containing data files
|
|
||||||
# INCLUDES is a list of directories containing header files
|
|
||||||
#
|
|
||||||
# NO_SMDH: if set to anything, no SMDH file is generated.
|
|
||||||
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
|
|
||||||
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
|
|
||||||
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
|
|
||||||
# ICON is the filename of the icon (.png), relative to the project folder.
|
|
||||||
# If not set, it attempts to use one of the following (in this order):
|
|
||||||
# - <Project name>.png
|
|
||||||
# - icon.png
|
|
||||||
# - <libctru folder>/default_icon.png
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
TARGET := $(notdir $(CURDIR))
|
|
||||||
BUILD := build
|
|
||||||
SOURCES := . ../
|
|
||||||
DATA := data
|
|
||||||
INCLUDES := include
|
|
||||||
APP_TITLE := khax
|
|
||||||
APP_DESCRIPTION := ARM11 KernelHax
|
|
||||||
APP_AUTHOR := Myria
|
|
||||||
ICON := logo.png
|
|
||||||
NO_SMDH := 1
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# options for code generation
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
|
||||||
|
|
||||||
CFLAGS := -g -Wall -O3 -mword-relocations \
|
|
||||||
-fomit-frame-pointer -ffast-math \
|
|
||||||
$(ARCH)
|
|
||||||
|
|
||||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS -DARM_ARCH -DKHAX_DEBUG
|
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
|
||||||
|
|
||||||
ASFLAGS := -g $(ARCH)
|
|
||||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
|
||||||
|
|
||||||
LIBS := -lctru -lm
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# list of directories containing libraries, this must be the top level containing
|
|
||||||
# include and lib
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
LIBDIRS := $(CTRULIB)
|
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# no real need to edit anything past this point unless you need to add additional
|
|
||||||
# rules for different file extensions
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
|
||||||
export TOPDIR := $(CURDIR)
|
|
||||||
|
|
||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
|
||||||
|
|
||||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
|
||||||
|
|
||||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
|
||||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
|
||||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ifeq ($(strip $(CPPFILES)),)
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
export LD := $(CC)
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
else
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
export LD := $(CXX)
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
endif
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
|
||||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
|
||||||
|
|
||||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
|
||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
|
||||||
-I$(CURDIR)/$(BUILD)
|
|
||||||
|
|
||||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
|
||||||
|
|
||||||
ifeq ($(strip $(ICON)),)
|
|
||||||
icons := $(wildcard *.png)
|
|
||||||
ifneq (,$(findstring $(TARGET).png,$(icons)))
|
|
||||||
export APP_ICON := $(TOPDIR)/$(TARGET).png
|
|
||||||
else
|
|
||||||
ifneq (,$(findstring icon.png,$(icons)))
|
|
||||||
export APP_ICON := $(TOPDIR)/icon.png
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: $(BUILD) clean all
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
all: $(BUILD)
|
|
||||||
|
|
||||||
$(BUILD):
|
|
||||||
@echo $(SFILES)
|
|
||||||
@[ -d $@ ] || mkdir -p $@
|
|
||||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
clean:
|
|
||||||
@echo clean ...
|
|
||||||
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
|
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
else
|
|
||||||
|
|
||||||
DEPENDS := $(OFILES:.o=.d)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# main targets
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ifeq ($(strip $(NO_SMDH)),)
|
|
||||||
.PHONY: all
|
|
||||||
all : $(OUTPUT).3dsx $(OUTPUT).smdh
|
|
||||||
endif
|
|
||||||
cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label
|
|
||||||
$(OUTPUT).3dsx : $(OUTPUT).elf
|
|
||||||
$(OUTPUT).elf : $(OFILES)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# you need a rule like this for each extension you use as binary data
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.bin.o : %.bin
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@$(bin2o)
|
|
||||||
|
|
||||||
# WARNING: This is not the right way to do this! TODO: Do it right!
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.vsh.o : %.vsh
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
|
|
||||||
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
|
|
||||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
|
|
||||||
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
|
||||||
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
|
||||||
@rm ../$(notdir $<).shbin
|
|
||||||
|
|
||||||
-include $(DEPENDS)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------------
|
|
||||||
endif
|
|
||||||
#---------------------------------------------------------------------------------------
|
|
@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 2013
|
|
||||||
VisualStudioVersion = 12.0.31101.0
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ctrklib", "ctrklib.vcxproj", "{80EE495D-0A84-4089-A93E-2B9E2BC38F94}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Win32 = Debug|Win32
|
|
||||||
Release|Win32 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{80EE495D-0A84-4089-A93E-2B9E2BC38F94}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{80EE495D-0A84-4089-A93E-2B9E2BC38F94}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{80EE495D-0A84-4089-A93E-2B9E2BC38F94}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{80EE495D-0A84-4089-A93E-2B9E2BC38F94}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
@ -1,82 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>{80EE495D-0A84-4089-A93E-2B9E2BC38F94}</ProjectGuid>
|
|
||||||
<RootNamespace>ctrklib</RootNamespace>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v120</PlatformToolset>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v120</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup />
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<AdditionalIncludeDirectories>C:\3DS\devkitPro\libctru\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
|
||||||
<AdditionalIncludeDirectories>C:\3DS\devkitPro\libctru\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="../khaxinit.cpp" />
|
|
||||||
<ClCompile Include="main.c" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Makefile" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="../khax.h" />
|
|
||||||
<ClInclude Include="../khaxinternal.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="Source Files">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Header Files">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="Resource Files">
|
|
||||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
|
||||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="main.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="../khaxinit.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Makefile" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="../khaxinternal.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="../khax.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -1,139 +0,0 @@
|
|||||||
#ifndef LIBKHAX_AS_LIB
|
|
||||||
|
|
||||||
#include <3ds.h>
|
|
||||||
#include <3ds/services/am.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include "../khax.h"
|
|
||||||
|
|
||||||
#define KHAX_lengthof(...) (sizeof(__VA_ARGS__) / sizeof((__VA_ARGS__)[0]))
|
|
||||||
|
|
||||||
s32 g_backdoorResult = -1;
|
|
||||||
|
|
||||||
s32 dump_chunk_wrapper()
|
|
||||||
{
|
|
||||||
__asm__ volatile("cpsid aif");
|
|
||||||
g_backdoorResult = 0x6666abcd;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test access to "am" service, which we shouldn't have access to, unless khax succeeds.
|
|
||||||
Result test_am_access_inner(char *productCode)
|
|
||||||
{
|
|
||||||
// Title IDs of "mset" in the six regions
|
|
||||||
static const u64 s_msetTitleIDs[] =
|
|
||||||
{
|
|
||||||
0x0004001000020000, 0x0004001000021000, 0x0004001000022000,
|
|
||||||
0x0004001000026000, 0x0004001000027000, 0x0004001000028000
|
|
||||||
};
|
|
||||||
Result result;
|
|
||||||
char productCodeTemp[16 + 1];
|
|
||||||
unsigned x;
|
|
||||||
|
|
||||||
// Initialize "am"
|
|
||||||
result = amInit();
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for the existence of the title IDs.
|
|
||||||
for (x = 0; x < KHAX_lengthof(s_msetTitleIDs); ++x)
|
|
||||||
{
|
|
||||||
result = AM_GetTitleProductCode(0, s_msetTitleIDs[x], productCodeTemp);
|
|
||||||
if (result == 0)
|
|
||||||
{
|
|
||||||
memcpy(productCode, productCodeTemp, sizeof(productCodeTemp));
|
|
||||||
amExit();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
amExit();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Self-contained test.
|
|
||||||
void test_am_access_outer(int testNumber)
|
|
||||||
{
|
|
||||||
char productCode[16 + 1];
|
|
||||||
Result result = test_am_access_inner(productCode);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
productCode[0] = '\0';
|
|
||||||
}
|
|
||||||
printf("amtest%d:%08lx %s\n", testNumber, result, productCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
// Initialize services
|
|
||||||
/* srvInit(); // mandatory
|
|
||||||
aptInit(); // mandatory
|
|
||||||
hidInit(NULL); // input (buttons, screen)*/
|
|
||||||
gfxInitDefault(); // graphics
|
|
||||||
/* fsInit();
|
|
||||||
sdmcInit();
|
|
||||||
hbInit();
|
|
||||||
qtmInit();*/
|
|
||||||
|
|
||||||
consoleInit(GFX_BOTTOM, NULL);
|
|
||||||
|
|
||||||
consoleClear();
|
|
||||||
|
|
||||||
test_am_access_outer(1); // test before libkhax
|
|
||||||
|
|
||||||
Result result = khaxInit();
|
|
||||||
printf("khaxInit returned %08lx\n", result);
|
|
||||||
|
|
||||||
printf("backdoor returned %08lx\n", (svcBackdoor(dump_chunk_wrapper), g_backdoorResult));
|
|
||||||
|
|
||||||
test_am_access_outer(2); // test after libkhax
|
|
||||||
|
|
||||||
printf("khax demo main finished\n");
|
|
||||||
printf("Press X to exit\n");
|
|
||||||
|
|
||||||
khaxExit();
|
|
||||||
|
|
||||||
while (aptMainLoop())
|
|
||||||
{
|
|
||||||
// Wait next screen refresh
|
|
||||||
gspWaitForVBlank();
|
|
||||||
|
|
||||||
// Read which buttons are currently pressed
|
|
||||||
hidScanInput();
|
|
||||||
u32 kDown = hidKeysDown();
|
|
||||||
(void) kDown;
|
|
||||||
u32 kHeld = hidKeysHeld();
|
|
||||||
(void) kHeld;
|
|
||||||
|
|
||||||
// If START is pressed, break loop and quit
|
|
||||||
if (kDown & KEY_X){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//consoleClear();
|
|
||||||
|
|
||||||
// Flush and swap framebuffers
|
|
||||||
gfxFlushBuffers();
|
|
||||||
gfxSwapBuffers();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit services
|
|
||||||
/* qtmExit();
|
|
||||||
hbExit();
|
|
||||||
sdmcExit();
|
|
||||||
fsExit();*/
|
|
||||||
gfxExit();
|
|
||||||
/* hidExit();
|
|
||||||
aptExit();
|
|
||||||
srvExit();*/
|
|
||||||
|
|
||||||
// Return to hbmenu
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // LIBKHAX_AS_LIB
|
|
@ -1,16 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <3ds.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Initialize and do the initial pwning of the ARM11 kernel.
|
|
||||||
Result khaxInit();
|
|
||||||
// Shut down libkhax
|
|
||||||
Result khaxExit();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
@ -1,337 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef KHAX_DEBUG
|
|
||||||
#define KHAX_printf(...) printf(__VA_ARGS__), gspWaitForVBlank(), gfxFlushBuffers(), gfxSwapBuffers()
|
|
||||||
#else
|
|
||||||
#define KHAX_printf(...) gspWaitForVBlank(), gfxFlushBuffers(), gfxSwapBuffers()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Shut up IntelliSense warnings when using MSVC as an IDE, even though MSVC will obviously never
|
|
||||||
// actually compile this program.
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#undef ALIGN
|
|
||||||
#define ALIGN(x) __declspec(align(x))
|
|
||||||
#if _MSC_VER < 1900
|
|
||||||
#define alignof __alignof
|
|
||||||
#endif
|
|
||||||
#define KHAX_ATTRIBUTE(...)
|
|
||||||
#else
|
|
||||||
#define KHAX_ATTRIBUTE(...) __VA_ARGS__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define KHAX_lengthof(...) (sizeof(__VA_ARGS__) / sizeof((__VA_ARGS__)[0]))
|
|
||||||
#define KHAX_UNUSED(...) static_cast<void>(__VA_ARGS__)
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
namespace KHAX
|
|
||||||
{
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// This code uses offsetof illegally (i.e. on polymorphic classes).
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// General linked list node kernel object.
|
|
||||||
struct KLinkedListNode
|
|
||||||
{
|
|
||||||
KLinkedListNode *next;
|
|
||||||
KLinkedListNode *prev;
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(KLinkedListNode) == 0x00C, "KLinkedListNode isn't the expected size.");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// Base class of reference-counted kernel objects.
|
|
||||||
class KAutoObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
u32 m_refCount; // +004
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~KAutoObject() {}
|
|
||||||
};
|
|
||||||
static_assert(sizeof(KAutoObject) == 0x008, "KAutoObject isn't the expected size.");
|
|
||||||
static_assert(offsetof(KAutoObject, m_refCount) == 0x004, "KAutoObject isn't the expected layout.");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// Base class of synchronizable objects.
|
|
||||||
class KSynchronizationObject : public KAutoObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
u32 m_threadSyncCount; // +008
|
|
||||||
KLinkedListNode *m_threadSyncFirst; // +00C
|
|
||||||
KLinkedListNode *m_threadSyncLast; // +010
|
|
||||||
};
|
|
||||||
static_assert(sizeof(KSynchronizationObject) == 0x014, "KSynchronizationObject isn't the expected size.");
|
|
||||||
static_assert(offsetof(KSynchronizationObject, m_threadSyncCount) == 0x008,
|
|
||||||
"KSynchronizationObject isn't the expected layout.");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
struct KDebugThread;
|
|
||||||
struct KThreadLocalPage;
|
|
||||||
class KCodeSet;
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// Unofficial name
|
|
||||||
typedef u8 KSVCACL[0x80 / 8];
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// ARM VFP register
|
|
||||||
union KHAX_ATTRIBUTE(__attribute__((__aligned__(4))) __attribute__((__packed__))) VFPRegister
|
|
||||||
{
|
|
||||||
float m_single[2];
|
|
||||||
double m_double;
|
|
||||||
};
|
|
||||||
static_assert(alignof(VFPRegister) == 0x004,
|
|
||||||
"VFPRegister isn't the expected alignment.");
|
|
||||||
static_assert(sizeof(VFPRegister) == 0x008,
|
|
||||||
"VFPRegister isn't the expected size.");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// SVC-mode register save area.
|
|
||||||
// http://3dbrew.org/wiki/Memory_layout#0xFF4XX000
|
|
||||||
struct SVCRegisterState
|
|
||||||
{
|
|
||||||
u32 m_r4; // +000
|
|
||||||
u32 m_r5; // +004
|
|
||||||
u32 m_r6; // +008
|
|
||||||
u32 m_r7; // +00C
|
|
||||||
u32 m_r8; // +010
|
|
||||||
u32 m_r9; // +014
|
|
||||||
u32 m_sl; // +018
|
|
||||||
u32 m_fp; // +01C
|
|
||||||
u32 m_sp; // +020
|
|
||||||
u32 m_lr; // +024
|
|
||||||
};
|
|
||||||
static_assert(sizeof(SVCRegisterState) == 0x028,
|
|
||||||
"SVCRegisterState isn't the expected size.");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// SVC-mode thread state structure. This is the last part of the per-
|
|
||||||
// thread page allocated in 0xFF4XX000.
|
|
||||||
// http://3dbrew.org/wiki/Memory_layout#0xFF4XX000
|
|
||||||
struct SVCThreadArea
|
|
||||||
{
|
|
||||||
KSVCACL m_svcAccessControl; // +000
|
|
||||||
u32 m_unknown010; // +010
|
|
||||||
u32 m_unknown014; // +014
|
|
||||||
SVCRegisterState m_svcRegisterState; // +018
|
|
||||||
VFPRegister m_vfpRegisters[16]; // +040
|
|
||||||
u32 m_unknown0C4; // +0C0
|
|
||||||
u32 m_fpexc; // +0C4
|
|
||||||
};
|
|
||||||
static_assert(offsetof(SVCThreadArea, m_svcRegisterState) == 0x018,
|
|
||||||
"ThreadSVCArea isn't the expected layout.");
|
|
||||||
static_assert(sizeof(SVCThreadArea) == 0x0C8,
|
|
||||||
"ThreadSVCArea isn't the expected size.");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// Kernel's internal structure of a thread object.
|
|
||||||
class KThread : public KSynchronizationObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
u32 m_unknown014; // +014
|
|
||||||
u32 m_unknown018; // +018
|
|
||||||
u32 m_unknown01C; // +01C
|
|
||||||
u32 m_unknown020; // +020
|
|
||||||
u32 m_unknown024; // +024
|
|
||||||
u32 m_unknown028; // +028
|
|
||||||
u32 m_unknown02C; // +02C
|
|
||||||
u32 m_unknown030; // +030
|
|
||||||
u32 m_unknown034; // +034
|
|
||||||
KDebugThread *m_debugThread; // +038
|
|
||||||
s32 m_threadPriority; // +03C
|
|
||||||
void *m_waitingOnObject; // +040
|
|
||||||
u32 m_unknown044; // +044
|
|
||||||
KThread **m_schedulerUnknown048; // +048
|
|
||||||
void *m_arbitrationAddress; // +04C
|
|
||||||
u32 m_unknown050; // +050
|
|
||||||
u32 m_unknown054; // +054
|
|
||||||
u32 m_unknown058; // +058
|
|
||||||
KLinkedListNode *m_waitingOnList; // +05C
|
|
||||||
u32 m_unknownListCount; // +060
|
|
||||||
KLinkedListNode *m_unknownListHead; // +064
|
|
||||||
KLinkedListNode *m_unknownListTail; // +068
|
|
||||||
s32 m_threadPriority2; // +06C
|
|
||||||
s32 m_creatingProcessor; // +070
|
|
||||||
u32 m_unknown074; // +074
|
|
||||||
u32 m_unknown078; // +078
|
|
||||||
u16 m_unknown07C; // +07C
|
|
||||||
u8 m_threadType; // +07E
|
|
||||||
u8 m_padding07F; // +07F
|
|
||||||
void *m_process; // +080
|
|
||||||
u32 m_threadID; // +084
|
|
||||||
SVCRegisterState *m_svcRegisterState; // +088
|
|
||||||
void *m_svcPageEnd; // +08C
|
|
||||||
s32 m_idealProcessor; // +090
|
|
||||||
void *m_tlsUserMode; // +094
|
|
||||||
void *m_tlsKernelMode; // +098
|
|
||||||
u32 m_unknown09C; // +09C
|
|
||||||
KThread *m_prev; // +0A0
|
|
||||||
KThread *m_next; // +0A4
|
|
||||||
KThread **m_temporaryLinkedList; // +0A8
|
|
||||||
u32 m_unknown0AC; // +0B0
|
|
||||||
};
|
|
||||||
static_assert(sizeof(KThread) == 0x0B0,
|
|
||||||
"KThread isn't the expected size.");
|
|
||||||
static_assert(offsetof(KThread, m_svcRegisterState) == 0x088,
|
|
||||||
"KThread isn't the expected layout.");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// Kernel's internal structure of a process object.
|
|
||||||
// Version 1.0.0(?) - 7.2.0
|
|
||||||
class KProcess_1_0_0_Old : public KSynchronizationObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
u32 m_unknown014; // +014
|
|
||||||
u32 m_unknown018; // +018
|
|
||||||
KThread *volatile m_interactingThread; // +01C
|
|
||||||
u16 m_unknown020; // +020
|
|
||||||
u16 m_unknown022; // +022
|
|
||||||
u32 m_unknown024; // +024
|
|
||||||
u32 m_unknown028; // +028
|
|
||||||
u32 m_memoryBlockCount; // +02C
|
|
||||||
KLinkedListNode *m_memoryBlockFirst; // +030
|
|
||||||
KLinkedListNode *m_memoryBlockLast; // +034
|
|
||||||
u32 m_unknown038; // +038
|
|
||||||
u32 m_unknown03C; // +03C
|
|
||||||
void *m_translationTableBase; // +040
|
|
||||||
u8 m_contextID; // +044
|
|
||||||
u32 m_unknown048; // +048
|
|
||||||
u32 m_unknown04C; // +04C
|
|
||||||
u32 m_mmuTableSize; // +050
|
|
||||||
void *m_mmuTableAddress; // +054
|
|
||||||
u32 m_threadContextPagesSize; // +058
|
|
||||||
u32 m_threadLocalPageCount; // +05C
|
|
||||||
KLinkedListNode *m_threadLocalPageFirst; // +060
|
|
||||||
KLinkedListNode *m_threadLocalPageLast; // +064
|
|
||||||
u32 m_unknown068; // +068
|
|
||||||
s32 m_idealProcessor; // +06C
|
|
||||||
u32 m_unknown070; // +070
|
|
||||||
void *m_resourceLimits; // +074
|
|
||||||
u8 m_unknown078; // +078
|
|
||||||
u8 m_affinityMask; // +079
|
|
||||||
u32 m_threadCount; // +07C
|
|
||||||
KSVCACL m_svcAccessControl; // +080
|
|
||||||
u32 m_interruptFlags[0x80 / 32]; // +090
|
|
||||||
u32 m_kernelFlags; // +0A0
|
|
||||||
u16 m_handleTableSize; // +0A4
|
|
||||||
u16 m_kernelReleaseVersion; // +0A6
|
|
||||||
KCodeSet *m_codeSet; // +0A8
|
|
||||||
u32 m_processID; // +0AC
|
|
||||||
u32 m_kernelFlags2; // +0B0
|
|
||||||
u32 m_unknown0B4; // +0B4
|
|
||||||
KThread *m_mainThread; // +0B8
|
|
||||||
//...more...
|
|
||||||
};
|
|
||||||
static_assert(offsetof(KProcess_1_0_0_Old, m_svcAccessControl) == 0x080,
|
|
||||||
"KProcess_1_0_0_Old isn't the expected layout.");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// Kernel's internal structure of a process object.
|
|
||||||
// Old 3DS Version 8.0.0 - 9.5.0...
|
|
||||||
class KProcess_8_0_0_Old : public KSynchronizationObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
u32 m_unknown014; // +014
|
|
||||||
u32 m_unknown018; // +018
|
|
||||||
KThread *volatile m_interactingThread; // +01C
|
|
||||||
u16 m_unknown020; // +020
|
|
||||||
u16 m_unknown022; // +022
|
|
||||||
u32 m_unknown024; // +024
|
|
||||||
u32 m_unknown028; // +028
|
|
||||||
u32 m_memoryBlockCount; // +02C
|
|
||||||
KLinkedListNode *m_memoryBlockFirst; // +030
|
|
||||||
KLinkedListNode *m_memoryBlockLast; // +034
|
|
||||||
u32 m_unknown038; // +038
|
|
||||||
u32 m_unknown03C; // +03C
|
|
||||||
void *m_translationTableBase; // +040
|
|
||||||
u8 m_contextID; // +044
|
|
||||||
u32 m_unknown048; // +048
|
|
||||||
void *m_userVirtualMemoryEnd; // +04C
|
|
||||||
void *m_userLinearVirtualBase; // +050
|
|
||||||
u32 m_unknown054; // +054
|
|
||||||
u32 m_mmuTableSize; // +058
|
|
||||||
void *m_mmuTableAddress; // +05C
|
|
||||||
u32 m_threadContextPagesSize; // +060
|
|
||||||
u32 m_threadLocalPageCount; // +064
|
|
||||||
KLinkedListNode *m_threadLocalPageFirst; // +068
|
|
||||||
KLinkedListNode *m_threadLocalPageLast; // +06C
|
|
||||||
u32 m_unknown070; // +070
|
|
||||||
s32 m_idealProcessor; // +074
|
|
||||||
u32 m_unknown078; // +078
|
|
||||||
void *m_resourceLimits; // +07C
|
|
||||||
u32 m_unknown080; // +080
|
|
||||||
u32 m_threadCount; // +084
|
|
||||||
u8 m_svcAccessControl[0x80 / 8]; // +088
|
|
||||||
u32 m_interruptFlags[0x80 / 32]; // +098
|
|
||||||
u32 m_kernelFlags; // +0A8
|
|
||||||
u16 m_handleTableSize; // +0AC
|
|
||||||
u16 m_kernelReleaseVersion; // +0AE
|
|
||||||
KCodeSet *m_codeSet; // +0B0
|
|
||||||
u32 m_processID; // +0B4
|
|
||||||
u32 m_unknown0B8; // +0B8
|
|
||||||
u32 m_unknown0BC; // +0BC
|
|
||||||
KThread *m_mainThread; // +0C0
|
|
||||||
//...more...
|
|
||||||
};
|
|
||||||
static_assert(offsetof(KProcess_8_0_0_Old, m_svcAccessControl) == 0x088,
|
|
||||||
"KProcess_8_0_0_Old isn't the expected layout.");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// Kernel's internal structure of a process object.
|
|
||||||
// New 3DS Version 8.0.0 - 9.5.0...
|
|
||||||
class KProcess_8_0_0_New : public KSynchronizationObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
u32 m_unknown014; // +014
|
|
||||||
u32 m_unknown018; // +018
|
|
||||||
KThread *volatile m_interactingThread; // +01C
|
|
||||||
u16 m_unknown020; // +020
|
|
||||||
u16 m_unknown022; // +022
|
|
||||||
u32 m_unknown024; // +024
|
|
||||||
u32 m_unknown028; // +028
|
|
||||||
u32 m_unknown02C; // +02C new to New 3DS
|
|
||||||
u32 m_unknown030; // +030 new to New 3DS
|
|
||||||
u32 m_memoryBlockCount; // +034
|
|
||||||
KLinkedListNode *m_memoryBlockFirst; // +038
|
|
||||||
KLinkedListNode *m_memoryBlockLast; // +03C
|
|
||||||
u32 m_unknown040; // +040
|
|
||||||
u32 m_unknown044; // +044
|
|
||||||
void *m_translationTableBase; // +048
|
|
||||||
u8 m_contextID; // +04C
|
|
||||||
u32 m_unknown050; // +050
|
|
||||||
void *m_userVirtualMemoryEnd; // +054
|
|
||||||
void *m_userLinearVirtualBase; // +058
|
|
||||||
u32 m_unknown05C; // +05C
|
|
||||||
u32 m_mmuTableSize; // +060
|
|
||||||
void *m_mmuTableAddress; // +064
|
|
||||||
u32 m_threadContextPagesSize; // +068
|
|
||||||
u32 m_threadLocalPageCount; // +06C
|
|
||||||
KLinkedListNode *m_threadLocalPageFirst; // +070
|
|
||||||
KLinkedListNode *m_threadLocalPageLast; // +074
|
|
||||||
u32 m_unknown078; // +078
|
|
||||||
s32 m_idealProcessor; // +07C
|
|
||||||
u32 m_unknown080; // +080
|
|
||||||
void *m_resourceLimits; // +084
|
|
||||||
u32 m_unknown088; // +088
|
|
||||||
u32 m_threadCount; // +08C
|
|
||||||
u8 m_svcAccessControl[0x80 / 8]; // +090
|
|
||||||
u32 m_interruptFlags[0x80 / 32]; // +0A0
|
|
||||||
u32 m_kernelFlags; // +0B0
|
|
||||||
u16 m_handleTableSize; // +0B4
|
|
||||||
u16 m_kernelReleaseVersion; // +0B6
|
|
||||||
KCodeSet *m_codeSet; // +0B8
|
|
||||||
u32 m_processID; // +0BC
|
|
||||||
u32 m_unknown0C0; // +0C0
|
|
||||||
u32 m_unknown0C4; // +0C4
|
|
||||||
KThread *m_mainThread; // +0C8
|
|
||||||
//...more...
|
|
||||||
};
|
|
||||||
static_assert(offsetof(KProcess_8_0_0_New, m_svcAccessControl) == 0x090,
|
|
||||||
"KProcess_8_0_0_New isn't the expected layout.");
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
|
||||||
// Done using illegal offsetof
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
#include <3ds.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "brahma.h"
|
|
||||||
#include "hid.h"
|
|
||||||
|
|
||||||
#ifndef LAUNCHER_PATH
|
|
||||||
#define LAUNCHER_PATH "Cakes.dat"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main (void) {
|
|
||||||
if (brahma_init()) {
|
|
||||||
if (load_arm9_payload_offset("/" LAUNCHER_PATH, 0x12000, 0x10000) != 1)
|
|
||||||
goto error;
|
|
||||||
firm_reboot();
|
|
||||||
brahma_exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return to hbmenu
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
gfxInitDefault();
|
|
||||||
consoleInit(GFX_BOTTOM, NULL);
|
|
||||||
printf("An error occurred while loading the payload.\nMake sure your launcher is located at:\n/" LAUNCHER_PATH);
|
|
||||||
wait_any_key();
|
|
||||||
|
|
||||||
gfxExit();
|
|
||||||
return 1;
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
.arm
|
|
||||||
.align 4
|
|
||||||
.code 32
|
|
||||||
.text
|
|
||||||
|
|
||||||
.global InvalidateEntireInstructionCache
|
|
||||||
.type InvalidateEntireInstructionCache, %function
|
|
||||||
InvalidateEntireInstructionCache:
|
|
||||||
mov r0, #0
|
|
||||||
mcr p15, 0, r0, c7, c5, 0
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
.global CleanEntireDataCache
|
|
||||||
.type CleanEntireDataCache, %function
|
|
||||||
CleanEntireDataCache:
|
|
||||||
mov r0, #0
|
|
||||||
mcr p15, 0, r0, c7, c10, 0
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
.global dsb
|
|
||||||
.type dsb, %function
|
|
||||||
dsb:
|
|
||||||
mov r0, #0
|
|
||||||
mcr p15, 0, r0, c7, c10, 4
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
.global DisableInterrupts
|
|
||||||
.type DisableInterrupts, %function
|
|
||||||
DisableInterrupts:
|
|
||||||
mrs r0, cpsr
|
|
||||||
CPSID I
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
.global EnableInterrupts
|
|
||||||
.type EnableInterrupts, %function
|
|
||||||
EnableInterrupts:
|
|
||||||
msr cpsr_cx, r0
|
|
||||||
bx lr
|
|
@ -1,22 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
import socket
|
|
||||||
import sys
|
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
|
||||||
print "python client.py <ip> <file>\n"
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
port = 80
|
|
||||||
host = sys.argv[1]
|
|
||||||
pfile = sys.argv[2]
|
|
||||||
|
|
||||||
f = open(pfile, "rb")
|
|
||||||
buf = f.read()
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
s = socket.socket()
|
|
||||||
s.connect((host, port))
|
|
||||||
sent = s.send(buf)
|
|
||||||
print "Sent %d bytes\n" % sent
|
|
||||||
s.close()
|
|
119
source/crypto.c
119
source/crypto.c
@ -357,113 +357,42 @@ int rsa_verify(const void* data, u32 size, const void* sig, u32 mode)
|
|||||||
* Nand/FIRM Crypto stuff
|
* Nand/FIRM Crypto stuff
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
|
||||||
//Get Nand CTR key
|
|
||||||
void getNandCTR(u8 *buf) {
|
|
||||||
u8 *addr = (u8*)0x080D8BBC;
|
|
||||||
u8 keyLen = 0x10; //CTR length
|
|
||||||
addr += 0x0F;
|
|
||||||
while (keyLen --) { *(buf++) = *(addr--); }
|
|
||||||
}
|
|
||||||
|
|
||||||
//Read firm0 from NAND and write to buffer
|
|
||||||
void nandFirm0(u8 *outbuf, const u32 size){
|
|
||||||
u8 CTR[0x10];
|
|
||||||
getNandCTR(CTR);
|
|
||||||
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
|
|
||||||
aes_use_keyslot(0x06);
|
|
||||||
aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Emulates the Arm9loader process
|
//Emulates the Arm9loader process
|
||||||
//9.5.0 = 0x0F
|
void arm9loader(void *armHdr){
|
||||||
//9.6.0 = 0x18
|
|
||||||
void arm9loader(void *armHdr, u32 kversion){
|
|
||||||
//Set Nand key#2 here (decrypted from 0x12C10)
|
//Set Nand key#2 here (decrypted from 0x12C10)
|
||||||
u8 key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
|
u8 key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
|
||||||
|
|
||||||
u8 keyX[0x10];
|
u8 keyX[0x10];
|
||||||
u8 keyY[0x10];
|
u8 keyY[0x10];
|
||||||
u8 CTR[0x10];
|
u8 CTR[0x10];
|
||||||
u32 slot = (kversion >= 0x0F ? 0x16 : 0x15);
|
u32 slot = 0x16;
|
||||||
|
|
||||||
//Setupkeys needed for arm9bin decryption
|
//Setupkeys needed for arm9bin decryption
|
||||||
memcpy(keyY, armHdr+0x10, 0x10);
|
memcpy((u8*)keyY, (void *)((uintptr_t)armHdr+0x10), 0x10);
|
||||||
memcpy(CTR, armHdr+0x20, 0x10);
|
memcpy((u8*)CTR, (void *)((uintptr_t)armHdr+0x20), 0x10);
|
||||||
u32 size = atoi(armHdr+0x30);
|
u32 size = atoi((void *)((uintptr_t)armHdr+0x30));
|
||||||
|
|
||||||
if(kversion >= 0x0F){
|
//Set 0x11 to key2 for the arm9bin and misc keys
|
||||||
if(kversion >= 0x18) aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_use_keyslot(0x11);
|
aes_use_keyslot(0x11);
|
||||||
aes(keyX, armHdr+0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
|
||||||
aes_setkey(slot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
aes_setkey(slot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
//Set 0x16 keyX, keyY and CTR
|
||||||
aes_setiv(CTR, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes((u8*)keyX, (void *)((uintptr_t)armHdr+0x60), 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||||
|
aes_setkey(slot, (u8*)keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
aes_setkey(slot, (u8*)keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
aes_setiv((u8*)CTR, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_use_keyslot(slot);
|
aes_use_keyslot(slot);
|
||||||
|
|
||||||
aes(armHdr+0x800, armHdr+0x800, size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
//Decrypt arm9bin
|
||||||
}
|
aes((void *)(armHdr+0x800), (void *)(armHdr+0x800), size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
void setKeys(kversion){
|
//Set keys 0x19..0x1F keyXs
|
||||||
u8 key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
|
u8* decKey = (void *)((uintptr_t)armHdr+0x8A824);
|
||||||
//Initialze keys
|
aes_use_keyslot(0x11);
|
||||||
if(kversion >= 0x18){
|
for(slot = 0x19; slot < 0x20; slot++) {
|
||||||
|
aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
u8 keyX18[16] = {0x82, 0xE9, 0xC9, 0xBE, 0xBF, 0xB8, 0xBD, 0xB8, 0x75, 0xEC, 0xC0, 0xA0, 0x7D, 0x47, 0x43, 0x74};
|
aes(decKey, (void *)((uintptr_t)armHdr+0x8A814), 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||||
u8 keyX19[16] = {0xF5, 0x36, 0x7F, 0xCE, 0x73, 0x14, 0x2E, 0x66, 0xED, 0x13, 0x91, 0x79, 0x14, 0xB7, 0xF2, 0xEF};
|
aes_setkey(slot, (u8*)decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
u8 keyX1A[16] = {0xEA, 0xBA, 0x98, 0x4C, 0x9C, 0xB7, 0x66, 0xD4, 0xA3, 0xA7, 0xE9, 0x74, 0xE2, 0xE7, 0x13, 0xA3};
|
*(u8 *)((void *)((uintptr_t)armHdr+0x8A814+0xF)) += 1;
|
||||||
u8 keyX1B[16] = {0x45, 0xAD, 0x04, 0x95, 0x39, 0x92, 0xC7, 0xC8, 0x93, 0x72, 0x4A, 0x9A, 0x7B, 0xCE, 0x61, 0x82};
|
|
||||||
u8 keyX1C[16] = {0xC3, 0x83, 0x0F, 0x81, 0x56, 0xE3, 0x54, 0x3B, 0x72, 0x3F, 0x0B, 0xC0, 0x46, 0x74, 0x1E, 0x8F};
|
|
||||||
u8 keyX1D[16] = {0xD6, 0xB3, 0x8B, 0xC7, 0x59, 0x41, 0x75, 0x96, 0xD6, 0x19, 0xD6, 0x02, 0x9D, 0x13, 0xE0, 0xD8};
|
|
||||||
u8 keyX1E[16] = {0xBB, 0x62, 0x3A, 0x97, 0xDD, 0xD7, 0x93, 0xD7, 0x57, 0xC4, 0x10, 0x4B, 0x8D, 0x9F, 0xB9, 0x69};
|
|
||||||
u8 keyX1F[16] = {0x4C, 0x28, 0xEC, 0x6E, 0xFF, 0xA3, 0xC2, 0x36, 0x46, 0x07, 0x8B, 0xBA, 0x35, 0x0C, 0x79, 0x95};
|
|
||||||
aes_setkey(0x18, keyX18, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x19, keyX19, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1A, keyX19, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1B, keyX1B, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1C, keyX1C, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1D, keyX1D, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1E, keyX1E, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1F, keyX1F, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
//data at armHdr+0x8A804 (its not in FCRAM for whatever reason)
|
|
||||||
u8 encryptedData1[0x10] = {
|
|
||||||
0xA4, 0x8D, 0xE4, 0xF1, 0x0B, 0x36, 0x44, 0xAA, 0x90, 0x31, 0x28, 0xFF,
|
|
||||||
0x4D, 0xCA, 0x76, 0xDF
|
|
||||||
};
|
|
||||||
//data at armHdr+0x8A814 (its not in FCRAM for whatever reason)
|
|
||||||
u8 encryptedData2[0x10] = {
|
|
||||||
0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D,
|
|
||||||
0x9D, 0x2A, 0x21, 0x98
|
|
||||||
};
|
|
||||||
|
|
||||||
//Set key 0x18 keyX
|
|
||||||
u8 keyX18[0x10];
|
|
||||||
aes(keyX18, encryptedData1, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
|
||||||
aes_setkey(0x18, keyX18, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
|
|
||||||
//Set key 0x11 normalkey
|
|
||||||
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_use_keyslot(0x11);
|
|
||||||
|
|
||||||
//Set keys 0x19..0x1F keyXs
|
|
||||||
u8 keyTemp[0x10];
|
|
||||||
u8 keys[7][0x10];
|
|
||||||
aes_use_keyslot(0x11);
|
|
||||||
int i; for(i = 0; i < 7; i++) {
|
|
||||||
aes(keyTemp, encryptedData2, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
|
||||||
encryptedData2[0x0F]++;
|
|
||||||
memcpy(keys[i], keyTemp, 0x10);
|
|
||||||
}
|
|
||||||
aes_setkey(0x19, keys[0], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1A, keys[1], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1B, keys[2], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1C, keys[3], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1D, keys[4], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1E, keys[5], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
aes_setkey(0x1F, keys[6], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -131,9 +131,6 @@ void rsa_use_keyslot(u32 keyslot);
|
|||||||
int rsa_verify(const void* data, u32 size, const void* sig, u32 mode);
|
int rsa_verify(const void* data, u32 size, const void* sig, u32 mode);
|
||||||
|
|
||||||
//NAND/FIRM stuff
|
//NAND/FIRM stuff
|
||||||
void getNandCTR(u8 *buf);
|
void arm9loader(void *armHdr);
|
||||||
void nandFirm0(u8 *outbuf, const u32 size);
|
|
||||||
void arm9loader(void *armHdr, u32 kversion);
|
|
||||||
void setKeys(kversion);
|
|
||||||
|
|
||||||
#endif /*__CRYPTO_H*/
|
#endif /*__CRYPTO_H*/
|
||||||
|
@ -17,4 +17,5 @@ void clearScreen(void){
|
|||||||
void loadSplash(void){
|
void loadSplash(void){
|
||||||
clearScreen();
|
clearScreen();
|
||||||
fileRead(fb->top_left, "/rei/splash.bin", 0x46500);
|
fileRead(fb->top_left, "/rei/splash.bin", 0x46500);
|
||||||
|
unsigned i,t; for(t=120;t>0;t--){for(i=0xFFFF;i>0;i--);}; //Ghetto sleep func
|
||||||
}
|
}
|
@ -16,11 +16,11 @@
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
DSTATUS disk_status (
|
DSTATUS disk_status (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -31,10 +31,10 @@ DSTATUS disk_status (
|
|||||||
|
|
||||||
DSTATUS disk_initialize (
|
DSTATUS disk_initialize (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
sdmmc_sdcard_init();
|
sdmmc_sdcard_init();
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,15 +46,15 @@ DSTATUS disk_initialize (
|
|||||||
|
|
||||||
DRESULT disk_read (
|
DRESULT disk_read (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
BYTE *buff, /* Data buffer to store read data */
|
BYTE *buff, /* Data buffer to store read data */
|
||||||
DWORD sector, /* Sector address in LBA */
|
DWORD sector, /* Sector address in LBA */
|
||||||
UINT count /* Number of sectors to read */
|
UINT count /* Number of sectors to read */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (sdmmc_sdcard_readsectors(sector, count, buff)) {
|
if (sdmmc_sdcard_readsectors(sector, count, buff)) {
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
@ -67,33 +67,34 @@ DRESULT disk_read (
|
|||||||
|
|
||||||
#if _USE_WRITE
|
#if _USE_WRITE
|
||||||
DRESULT disk_write (
|
DRESULT disk_write (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
const BYTE *buff, /* Data to be written */
|
const BYTE *buff, /* Data to be written */
|
||||||
DWORD sector, /* Sector address in LBA */
|
DWORD sector, /* Sector address in LBA */
|
||||||
UINT count /* Number of sectors to write */
|
UINT count /* Number of sectors to write */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
|
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Miscellaneous Functions */
|
/* Miscellaneous Functions */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
#if _USE_IOCTL
|
#if _USE_IOCTL
|
||||||
DRESULT disk_ioctl (
|
DRESULT disk_ioctl (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE cmd, /* Control code */
|
BYTE cmd, /* Control code */
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
void *buff /* Buffer to send/receive control data */
|
void *buff /* Buffer to send/receive control data */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
/ and optional writing functions as well. */
|
/ and optional writing functions as well. */
|
||||||
|
|
||||||
|
|
||||||
#define _FS_MINIMIZE 1
|
#define _FS_MINIMIZE 0
|
||||||
/* This option defines minimization level to remove some basic API functions.
|
/* This option defines minimization level to remove some basic API functions.
|
||||||
/
|
/
|
||||||
/ 0: All basic functions are enabled.
|
/ 0: All basic functions are enabled.
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
// Copyright 2014 Normmatt
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
.arm
|
.arm
|
||||||
.global ioDelay
|
.global waitcycles
|
||||||
.type ioDelay STT_FUNC
|
.type waitcycles STT_FUNC
|
||||||
|
|
||||||
@ioDelay ( u32 us )
|
@waitcycles ( u32 us )
|
||||||
ioDelay:
|
waitcycles:
|
||||||
ldr r1, =0x18000000 @ VRAM
|
PUSH {R0-R2,LR}
|
||||||
1:
|
STR R0, [SP,#4]
|
||||||
@ Loop doing uncached reads from VRAM to make loop timing more reliable
|
waitcycles_loop:
|
||||||
ldr r2, [r1]
|
LDR R3, [SP,#4]
|
||||||
subs r0, #1
|
SUBS R2, R3, #1
|
||||||
bgt 1b
|
STR R2, [SP,#4]
|
||||||
bx lr
|
CMP R3, #0
|
||||||
|
BNE waitcycles_loop
|
||||||
|
POP {R0-R2,PC}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,52 +1,52 @@
|
|||||||
// Copyright 2014 Normmatt
|
#ifndef __SDMMC_H__
|
||||||
// Licensed under GPLv2 or any later version
|
#define __SDMMC_H__
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#pragma once
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
#include "common.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
#define SDMMC_BASE 0x10006000u
|
#define SDMMC_BASE 0x10006000
|
||||||
|
|
||||||
#define REG_SDCMD 0x00
|
#define REG_SDCMD 0x00
|
||||||
#define REG_SDPORTSEL 0x02
|
#define REG_SDPORTSEL 0x02
|
||||||
#define REG_SDCMDARG 0x04
|
#define REG_SDCMDARG 0x04
|
||||||
#define REG_SDCMDARG0 0x04
|
#define REG_SDCMDARG0 0x04
|
||||||
#define REG_SDCMDARG1 0x06
|
#define REG_SDCMDARG1 0x06
|
||||||
#define REG_SDSTOP 0x08
|
#define REG_SDSTOP 0x08
|
||||||
#define REG_SDBLKCOUNT 0x0a
|
#define REG_SDBLKCOUNT 0x0a
|
||||||
|
|
||||||
#define REG_SDRESP0 0x0c
|
#define REG_SDRESP0 0x0c
|
||||||
#define REG_SDRESP1 0x0e
|
#define REG_SDRESP1 0x0e
|
||||||
#define REG_SDRESP2 0x10
|
#define REG_SDRESP2 0x10
|
||||||
#define REG_SDRESP3 0x12
|
#define REG_SDRESP3 0x12
|
||||||
#define REG_SDRESP4 0x14
|
#define REG_SDRESP4 0x14
|
||||||
#define REG_SDRESP5 0x16
|
#define REG_SDRESP5 0x16
|
||||||
#define REG_SDRESP6 0x18
|
#define REG_SDRESP6 0x18
|
||||||
#define REG_SDRESP7 0x1a
|
#define REG_SDRESP7 0x1a
|
||||||
|
|
||||||
#define REG_SDSTATUS0 0x1c
|
#define REG_SDSTATUS0 0x1c
|
||||||
#define REG_SDSTATUS1 0x1e
|
#define REG_SDSTATUS1 0x1e
|
||||||
|
|
||||||
#define REG_SDIRMASK0 0x20
|
#define REG_SDIRMASK0 0x20
|
||||||
#define REG_SDIRMASK1 0x22
|
#define REG_SDIRMASK1 0x22
|
||||||
#define REG_SDCLKCTL 0x24
|
#define REG_SDCLKCTL 0x24
|
||||||
|
|
||||||
|
#define REG_SDBLKLEN 0x26
|
||||||
|
#define REG_SDOPT 0x28
|
||||||
|
#define REG_SDFIFO 0x30
|
||||||
|
|
||||||
#define REG_SDBLKLEN 0x26
|
#define REG_DATACTL 0xd8
|
||||||
#define REG_SDOPT 0x28
|
#define REG_SDRESET 0xe0
|
||||||
#define REG_SDFIFO 0x30
|
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
|
||||||
|
|
||||||
#define REG_SDDATACTL 0xd8
|
#define REG_DATACTL32 0x100
|
||||||
#define REG_SDRESET 0xe0
|
#define REG_SDBLKLEN32 0x104
|
||||||
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
|
#define REG_SDBLKCOUNT32 0x108
|
||||||
|
#define REG_SDFIFO32 0x10C
|
||||||
|
|
||||||
#define REG_SDDATACTL32 0x100
|
#define REG_CLK_AND_WAIT_CTL 0x138
|
||||||
#define REG_SDBLKLEN32 0x104
|
#define REG_RESET_SDIO 0x1e0
|
||||||
#define REG_SDBLKCOUNT32 0x108
|
|
||||||
#define REG_SDFIFO32 0x10C
|
|
||||||
|
|
||||||
#define REG_CLK_AND_WAIT_CTL 0x138
|
|
||||||
#define REG_RESET_SDIO 0x1e0
|
|
||||||
|
|
||||||
#define TMIO_STAT0_CMDRESPEND 0x0001
|
#define TMIO_STAT0_CMDRESPEND 0x0001
|
||||||
#define TMIO_STAT0_DATAEND 0x0004
|
#define TMIO_STAT0_DATAEND 0x0004
|
||||||
@ -97,75 +97,88 @@
|
|||||||
#define TMIO_MASK_ALL 0x837f031d
|
#define TMIO_MASK_ALL 0x837f031d
|
||||||
|
|
||||||
#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \
|
#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \
|
||||||
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
|
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
|
||||||
|
|
||||||
#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND)
|
#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND)
|
||||||
#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND)
|
#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND)
|
||||||
|
|
||||||
typedef struct mmcdevice {
|
#ifdef __cplusplus
|
||||||
u8* data;
|
extern "C" {
|
||||||
u32 size;
|
#endif
|
||||||
u32 error;
|
|
||||||
u16 stat0;
|
|
||||||
u16 stat1;
|
|
||||||
u32 ret[4];
|
|
||||||
u32 initarg;
|
|
||||||
u32 isSDHC;
|
|
||||||
u32 clk;
|
|
||||||
u32 SDOPT;
|
|
||||||
u32 devicenumber;
|
|
||||||
u32 total_size; //size in sectors of the device
|
|
||||||
u32 res;
|
|
||||||
} mmcdevice;
|
|
||||||
|
|
||||||
/*int sdmmc_sdcard_init();
|
typedef struct mmcdevice {
|
||||||
void sdmmc_sdcard_readsector(uint32_t sector_no, void *out);
|
uint8_t* data;
|
||||||
void sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, void *out);
|
uint32_t size;
|
||||||
void sdmmc_sdcard_writesector(uint32_t sector_no, void *in);
|
uint32_t error;
|
||||||
void sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, void *in);
|
uint16_t stat0;
|
||||||
void sdmmc_blktransferinit();*/
|
uint16_t stat1;
|
||||||
|
uint32_t ret[4];
|
||||||
|
uint32_t initarg;
|
||||||
|
uint32_t isSDHC;
|
||||||
|
uint32_t clk;
|
||||||
|
uint32_t SDOPT;
|
||||||
|
uint32_t devicenumber;
|
||||||
|
uint32_t total_size; //size in sectors of the device
|
||||||
|
uint32_t res;
|
||||||
|
} mmcdevice;
|
||||||
|
|
||||||
|
void sdmmc_sdcard_init();
|
||||||
|
int sdmmc_sdcard_readsector(uint32_t sector_no, uint8_t *out);
|
||||||
|
int sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
|
||||||
|
int sdmmc_sdcard_writesector(uint32_t sector_no, uint8_t *in);
|
||||||
|
int sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
|
||||||
|
|
||||||
|
int sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
|
||||||
|
int sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
|
||||||
|
|
||||||
|
mmcdevice *getMMCDevice(int drive);
|
||||||
|
|
||||||
|
void InitSD();
|
||||||
|
int Nand_Init();
|
||||||
|
int SD_Init();
|
||||||
|
|
||||||
void sdmmc_sdcard_init();
|
#ifdef __cplusplus
|
||||||
int sdmmc_sdcard_readsector(u32 sector_no, u8 *out);
|
};
|
||||||
int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out);
|
#endif
|
||||||
int sdmmc_sdcard_writesector(u32 sector_no, u8 *in);
|
|
||||||
int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, u8 *in);
|
|
||||||
|
|
||||||
int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out);
|
//---------------------------------------------------------------------------------
|
||||||
int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, u8 *in);
|
static inline uint16_t sdmmc_read16(uint16_t reg) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
mmcdevice *getMMCDevice(int drive);
|
return *(volatile uint16_t*)(SDMMC_BASE + reg);
|
||||||
|
|
||||||
void InitSDMMC();
|
|
||||||
int Nand_Init();
|
|
||||||
int SD_Init();
|
|
||||||
|
|
||||||
static inline u16 sdmmc_read16(u16 reg) {
|
|
||||||
return *(vu16*)(SDMMC_BASE + reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sdmmc_write16(u16 reg, u16 val) {
|
//---------------------------------------------------------------------------------
|
||||||
*(vu16*)(SDMMC_BASE + reg) = val;
|
static inline void sdmmc_write16(uint16_t reg, uint16_t val) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
*(volatile uint16_t*)(SDMMC_BASE + reg) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u32 sdmmc_read32(u16 reg) {
|
//---------------------------------------------------------------------------------
|
||||||
return *(vu32*)(SDMMC_BASE + reg);
|
static inline uint32_t sdmmc_read32(uint16_t reg) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
return *(volatile uint32_t*)(SDMMC_BASE + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sdmmc_write32(u16 reg, u32 val) {
|
//---------------------------------------------------------------------------------
|
||||||
*(vu32*)(SDMMC_BASE + reg) = val;
|
static inline void sdmmc_write32(uint16_t reg, uint32_t val) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
*(volatile uint32_t*)(SDMMC_BASE + reg) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set) {
|
//---------------------------------------------------------------------------------
|
||||||
u16 val = sdmmc_read16(reg);
|
static inline void sdmmc_mask16(uint16_t reg, const uint16_t clear, const uint16_t set) {
|
||||||
val &= ~clear;
|
//---------------------------------------------------------------------------------
|
||||||
val |= set;
|
uint16_t val = sdmmc_read16(reg);
|
||||||
sdmmc_write16(reg, val);
|
val &= ~clear;
|
||||||
|
val |= set;
|
||||||
|
sdmmc_write16(reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void setckl(u32 data)
|
static inline void setckl(uint32_t data)
|
||||||
{
|
{
|
||||||
sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
|
sdmmc_mask16(REG_SDCLKCTL,0x100,0);
|
||||||
sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF);
|
sdmmc_mask16(REG_SDCLKCTL,0x2FF,data&0x2FF);
|
||||||
sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100);
|
sdmmc_mask16(REG_SDCLKCTL,0x0,0x100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -11,66 +11,52 @@
|
|||||||
#include "emunand.h"
|
#include "emunand.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
|
|
||||||
firmHeader *firmLocation = (firmHeader *)0x24000000;
|
const firmHeader *firmLocation = (firmHeader *)0x24000000;
|
||||||
const u32 firmSize = 0xF1000;
|
const u32 firmSize = 0xF3000;
|
||||||
firmSectionHeader *section;
|
firmSectionHeader *section;
|
||||||
u32 emuOffset = 0;
|
u32 emuOffset = 0;
|
||||||
u32 emuHeader = 0;
|
u32 emuHeader = 0;
|
||||||
u32 kversion = 0;
|
|
||||||
|
|
||||||
//Load firm into FCRAM
|
//Load firm into FCRAM
|
||||||
void loadFirm(int mode){
|
void loadFirm(void){
|
||||||
//Sysnand mode
|
//Read FIRM from SD card and write to FCRAM
|
||||||
if(mode == 0 || getEmunand(&emuOffset, &emuHeader) == 0){
|
fileRead((u8*)firmLocation, "/rei/firmware.bin", firmSize);
|
||||||
//Read FIRM from NAND and write to FCRAM
|
section = firmLocation->section;
|
||||||
nandFirm0((u8*)firmLocation, firmSize);
|
arm9loader((u8*)firmLocation + section[2].offset);
|
||||||
section = firmLocation->section;
|
|
||||||
kversion = 0x04; //TODO: make this not hard coded
|
|
||||||
arm9loader((u8*)firmLocation + section[2].offset, kversion);
|
|
||||||
}
|
|
||||||
//Emunand mode
|
|
||||||
else{
|
|
||||||
//Read FIRM from SD card and write to FCRAM
|
|
||||||
fileRead((u8*)firmLocation, "/rei/firmware.bin", firmSize);
|
|
||||||
section = firmLocation->section;
|
|
||||||
kversion = 0x18; //TODO: make this not hard coded
|
|
||||||
arm9loader((u8*)firmLocation + section[2].offset, kversion);
|
|
||||||
loadEmu();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Nand redirection
|
//Nand redirection
|
||||||
void loadEmu(void){
|
void loadEmu(void){
|
||||||
|
|
||||||
//Read emunand code from SD
|
//Read emunand code from SD
|
||||||
u32 code = emuCode(kversion);
|
u32 code = emuCode();
|
||||||
fileRead((u8*)code, "/rei/emunand/emunand.bin", 0);
|
fileRead(code, "/rei/emunand/emunand.bin", 0);
|
||||||
u32 *pos_offset = memsearch((u8*)code, "NAND", 0x218, 4);
|
u32 *pos_offset = memsearch(code, "NAND", 0x218, 4);
|
||||||
u32 *pos_header = memsearch((u8*)code, "NCSD", 0x218, 4);
|
u32 *pos_header = memsearch(code, "NCSD", 0x218, 4);
|
||||||
memcpy((void *)pos_offset, (void *)emuOffset, 4);
|
if (pos_offset && pos_header) {
|
||||||
memcpy((void *)pos_header, (void *)emuHeader, 4);
|
*pos_offset = emuOffset;
|
||||||
|
*pos_header = emuHeader;
|
||||||
|
}
|
||||||
|
fileWrite(code, "help.bin", 0x200);
|
||||||
//Add emunand hooks
|
//Add emunand hooks
|
||||||
memcpy((u8*)emuHook(1, kversion), nandRedir, sizeof(nandRedir));
|
memcpy((u8*)emuHook(1), nandRedir, sizeof(nandRedir));
|
||||||
memcpy((u8*)emuHook(2, kversion), nandRedir, sizeof(nandRedir));
|
memcpy((u8*)emuHook(2), nandRedir, sizeof(nandRedir));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Patches
|
//Patches
|
||||||
void patchFirm(){
|
void patchFirm(){
|
||||||
|
|
||||||
//Part1: Set MPU for payload area
|
//Part1: Set MPU for payload area
|
||||||
memcpy((u8*)mpuCode(kversion), mpu, sizeof(mpu));
|
memcpy((u8*)mpuCode(), mpu, sizeof(mpu));
|
||||||
|
|
||||||
//Part2: Disable signature checks
|
//Part2: Disable signature checks
|
||||||
memcpy((u8*)sigPatch(1, kversion), sigPat1, sizeof(sigPat1));
|
memcpy((u8*)sigPatch(1), sigPat1, sizeof(sigPat1));
|
||||||
memcpy((u8*)sigPatch(2, kversion), sigPat2, sizeof(sigPat2));
|
memcpy((u8*)sigPatch(2), sigPat2, sizeof(sigPat2));
|
||||||
|
|
||||||
//Part3: Create arm9 thread
|
//Part3: Create arm9 thread
|
||||||
fileRead((u8*)threadCode(kversion), "/rei/thread/arm9.bin", 0);
|
fileRead((u8*)threadCode(), "/rei/thread/arm9.bin", 0);
|
||||||
if(kversion == 0x18){ //TODO: 0x18 only untill i can figure out why the hell this doesnt work on sysnand anymore.
|
memcpy((u8*)threadHook(1), th1, sizeof(th1));
|
||||||
memcpy((u8*)threadHook(1, kversion), th1, sizeof(th1));
|
memcpy((u8*)threadHook(2), th2, sizeof(th2));
|
||||||
memcpy((u8*)threadHook(2, kversion), th2, sizeof(th2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Firmlaunchhax
|
//Firmlaunchhax
|
||||||
@ -108,10 +94,7 @@ void launchFirm(void){
|
|||||||
memcpy(section[1].address, (u8*)firmLocation + section[1].offset, section[1].size);
|
memcpy(section[1].address, (u8*)firmLocation + section[1].offset, section[1].size);
|
||||||
memcpy(section[2].address, (u8*)firmLocation + section[2].offset, section[2].size);
|
memcpy(section[2].address, (u8*)firmLocation + section[2].offset, section[2].size);
|
||||||
*(u32 *)0x1FFFFFF8 = (u32)firmLocation->arm11Entry;
|
*(u32 *)0x1FFFFFF8 = (u32)firmLocation->arm11Entry;
|
||||||
|
|
||||||
setKeys(kversion);
|
|
||||||
|
|
||||||
//Final jump to arm9 binary
|
//Final jump to arm9 binary
|
||||||
((void (*)())0x801B01C)();
|
((void (*)())0x801B01C)();
|
||||||
//((void (*)())firmLocation->arm9Entry)();
|
|
||||||
}
|
}
|
@ -9,7 +9,7 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
void loadSplash(void);
|
void loadSplash(void);
|
||||||
void loadFirm(int mode);
|
void loadFirm(void);
|
||||||
void loadEmu(void);
|
void loadEmu(void);
|
||||||
void patchFirm(void);
|
void patchFirm(void);
|
||||||
void launchFirm(void);
|
void launchFirm(void);
|
||||||
|
@ -10,16 +10,11 @@
|
|||||||
#include "firm.h"
|
#include "firm.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
|
||||||
int mode = 1;
|
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
mountSD();
|
mountSD();
|
||||||
loadSplash();
|
loadSplash();
|
||||||
while(1){
|
loadFirm();
|
||||||
if(((~*(unsigned *)0x10146000) & 0xFFF) == (1 << 3)) break;
|
loadEmu();
|
||||||
else if(((~*(unsigned *)0x10146000) & 0xFFF) == ((1 << 3) | (1 << 1))) {mode = 0; break;}
|
|
||||||
} //Start = emu; Start+B = sys
|
|
||||||
loadFirm(mode);
|
|
||||||
patchFirm();
|
patchFirm();
|
||||||
launchFirm();
|
launchFirm();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -5,29 +5,38 @@
|
|||||||
*/
|
*/
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
void memcpy(u8 *dest, u8 *src, u32 size){
|
|
||||||
for (u32 i = 0; i < size; i++) dest[i] = src[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
void memcpy32(u32 *dest, u32 *src, u32 size){
|
void memcpy32(u32 *dest, u32 *src, u32 size){
|
||||||
for (u32 i = 0; i < size; i++) dest[i] = src[i];
|
for (u32 i = 0; i < size; i++) dest[i] = src[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void memset(u8 *dest, u32 fill, u32 size){
|
void memcpy(void *dest, const void *src, u32 size){
|
||||||
for (u32 i = 0; i < size; i++) dest[i] = fill;
|
char *destc = (char *)dest;
|
||||||
|
const char *srcc = (const char *)src;
|
||||||
|
u32 i; for (i = 0; i < size; i++) {
|
||||||
|
destc[i] = srcc[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int memcmp(u8 *buf1, u8 *buf2, u32 size){
|
void memset(void *dest, int filler, u32 size){
|
||||||
for (u32 i = 0; i < size; i++) {
|
char *destc = (char *)dest;
|
||||||
int cmp = buf1[i] - buf2[i];
|
u32 i; for (i = 0; i < size; i++) {
|
||||||
if (cmp != 0) return cmp;
|
destc[i] = filler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int memcmp(const void *buf1, const void *buf2, u32 size){
|
||||||
|
const char *buf1c = (const char *)buf1;
|
||||||
|
const char *buf2c = (const char *)buf2;
|
||||||
|
u32 i; for (i = 0; i < size; i++) {
|
||||||
|
int cmp = buf1c[i] - buf2c[i];
|
||||||
|
if (cmp) return cmp;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 *memsearch(u8 *start_pos, u8 *search, u32 size, u32 size_search){
|
void *memsearch(void *start_pos, void *search, u32 size, u32 size_search){
|
||||||
for (u8 *pos = start_pos; pos <= start_pos + size - size_search; pos++) {
|
for (void *pos = start_pos + size - size_search; pos >= start_pos; pos--) {
|
||||||
if (memcmp(pos, search, size_search) == 0) return (u32*)pos;
|
if (memcmp(pos, search, size_search) == 0) return pos;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
@ -8,10 +8,10 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
void memcpy(u8 *dest, u8 *src, u32 size);
|
void memcpy(void *dest, const void *src, u32 size);
|
||||||
void memcpy32(u32 *dest, u32 *src, u32 size);
|
void memcpy32(u32 *dest, u32 *src, u32 size);
|
||||||
void memset(u8 *dest, u32 fill, u32 size);
|
void memset(void *dest, int filler, u32 size);
|
||||||
int memcmp(u8 *buf1, u8 *buf2, u32 size);
|
int memcmp(const void *buf1, const void *buf2, u32 size);
|
||||||
u32 *memsearch(u8 *start_pos, u8 *search, u32 size, u32 size_search);
|
void *memsearch(void *start_pos, void *search, u32 size, u32 size_search);
|
||||||
|
|
||||||
#endif
|
#endif
|
128
source/patches.c
128
source/patches.c
@ -8,9 +8,8 @@
|
|||||||
|
|
||||||
#define FIRM 0x24000000
|
#define FIRM 0x24000000
|
||||||
|
|
||||||
#define KERNEL9 (FIRM + 0x66A00)
|
#define KERNEL9 (FIRM + 0x68000)
|
||||||
#define PROC9 (FIRM + 0x7D700)
|
#define PROC9 (FIRM + 0x7ED00)
|
||||||
#define v9_6_Offset 0x1600
|
|
||||||
|
|
||||||
#define K9_ADDR 0x08006000
|
#define K9_ADDR 0x08006000
|
||||||
#define P9_ADDR 0x08028000
|
#define P9_ADDR 0x08028000
|
||||||
@ -49,124 +48,37 @@ u8 th2[4] = {0xE0, 0xA6, 0x01, 0x08}; //0x0801A6E0
|
|||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
||||||
//Where the emunand code is stored in firm
|
//Where the emunand code is stored in firm
|
||||||
u32 emuCode(u32 kver){
|
u32 emuCode(void){
|
||||||
u32 ret = NULL;
|
return KERNEL9 + (0x0801A4C0 - K9_ADDR);
|
||||||
switch(kver){
|
|
||||||
case 0x04:
|
|
||||||
case 0x0C:
|
|
||||||
case 0x0F:
|
|
||||||
ret = KERNEL9 + (0x0801A4C0 - K9_ADDR);
|
|
||||||
break;
|
|
||||||
case 0x18:
|
|
||||||
ret = KERNEL9 + v9_6_Offset + (0x0801A4C0 - K9_ADDR);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Where thread code is stored in firm
|
//Where thread code is stored in firm
|
||||||
u32 threadCode(u32 kver){
|
u32 threadCode(void){
|
||||||
u32 ret = NULL;
|
return KERNEL9 + (0x0801A6E0 - K9_ADDR);
|
||||||
switch(kver){
|
|
||||||
case 0x04:
|
|
||||||
case 0x0C:
|
|
||||||
case 0x0F:
|
|
||||||
ret = KERNEL9 + (0x0801A6E0 - K9_ADDR);
|
|
||||||
case 0x18:
|
|
||||||
ret = KERNEL9 + v9_6_Offset + (0x0801A6E0 - K9_ADDR);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Area of MPU setting code
|
//Area of MPU setting code
|
||||||
u32 mpuCode(u32 kver){
|
u32 mpuCode(void){
|
||||||
u32 ret = NULL;
|
return KERNEL9 + (0x0801B3D4 - K9_ADDR);
|
||||||
switch(kver){
|
|
||||||
case 0x04:
|
|
||||||
case 0x0C:
|
|
||||||
case 0x0F:
|
|
||||||
ret = KERNEL9 + (0x0801B3D4 - K9_ADDR);
|
|
||||||
break;
|
|
||||||
case 0x18:
|
|
||||||
ret = KERNEL9 + v9_6_Offset + (0x0801B3D4 - K9_ADDR);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Offsets to redirect to thread code
|
//Offsets to redirect to thread code
|
||||||
u32 threadHook(u8 val, u32 kver){
|
u32 threadHook(u8 val){
|
||||||
u32 ret = NULL;
|
return val == 1 ?
|
||||||
switch(kver){
|
PROC9 + (0x08086140 - P9_ADDR):
|
||||||
case 0x04:
|
PROC9 + (0x08086174 - P9_ADDR);
|
||||||
ret = val == 1 ?
|
|
||||||
PROC9 + (0x0808690C - P9_ADDR) :
|
|
||||||
PROC9 + (0x08086940 - P9_ADDR);
|
|
||||||
break;
|
|
||||||
case 0x0C:
|
|
||||||
//TODO: find
|
|
||||||
break;
|
|
||||||
case 0x0F:
|
|
||||||
ret = val == 1 ?
|
|
||||||
PROC9 + (0x080860B0 - P9_ADDR) :
|
|
||||||
PROC9 + (0x080860E4 - P9_ADDR);
|
|
||||||
break;
|
|
||||||
case 0x18:
|
|
||||||
ret = val == 1 ?
|
|
||||||
PROC9 + v9_6_Offset + (0x08086140 - P9_ADDR) :
|
|
||||||
PROC9 + v9_6_Offset + (0x08086174 - P9_ADDR);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Offsets to redirect to Emunand code
|
//Offsets to redirect to Emunand code
|
||||||
u32 emuHook(u8 val, u32 kver){ //latest only
|
u32 emuHook(u8 val){ //latest only
|
||||||
u32 ret = NULL;
|
return val == 1 ?
|
||||||
switch(kver){
|
PROC9 + (0x0807882C - P9_ADDR):
|
||||||
case 0x04:
|
PROC9 + (0x0807886C - P9_ADDR);
|
||||||
//???
|
|
||||||
break;
|
|
||||||
case 0x0C:
|
|
||||||
//???
|
|
||||||
break;
|
|
||||||
case 0x0F:
|
|
||||||
if(val == 1) ret = PROC9 + (0x0807882C - P9_ADDR);
|
|
||||||
else if(val == 2) ret = PROC9 + (0x0807886C - P9_ADDR);
|
|
||||||
break;
|
|
||||||
case 0x18:
|
|
||||||
if(val == 1) ret = PROC9 + v9_6_Offset + (0x0807882C - P9_ADDR);
|
|
||||||
else if(val == 2) ret = PROC9 + v9_6_Offset + (0x0807886C - P9_ADDR);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Offsets to redirect to thread code
|
//Offsets to redirect to thread code
|
||||||
u32 sigPatch(u8 val, u32 kver){
|
u32 sigPatch(u8 val){
|
||||||
u32 ret = NULL;
|
return val == 1 ?
|
||||||
switch(kver){
|
PROC9 + (0x080632B8 - P9_ADDR) :
|
||||||
case 0x04:
|
PROC9 + (0x0805D628 - P9_ADDR);
|
||||||
ret = val == 1 ?
|
|
||||||
PROC9 + (0x08063C28 - P9_ADDR) :
|
|
||||||
PROC9 + (0x0805E2D4 - P9_ADDR);
|
|
||||||
break;
|
|
||||||
case 0x0C:
|
|
||||||
ret = val == 1 ?
|
|
||||||
0 :
|
|
||||||
0; //TODO: find
|
|
||||||
break;
|
|
||||||
case 0x0F:
|
|
||||||
ret = val == 1 ?
|
|
||||||
PROC9 + (0x08063374 - P9_ADDR) :
|
|
||||||
PROC9 + (0x0805D498 - P9_ADDR);
|
|
||||||
break;
|
|
||||||
case 0x18:
|
|
||||||
ret = val == 1 ?
|
|
||||||
PROC9 + v9_6_Offset + (0x080632B8 - P9_ADDR) :
|
|
||||||
PROC9 + v9_6_Offset + (0x0805D628 - P9_ADDR);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
@ -21,11 +21,11 @@ u8 th2[4];
|
|||||||
/**************************************************
|
/**************************************************
|
||||||
* Functions
|
* Functions
|
||||||
**************************************************/
|
**************************************************/
|
||||||
u32 emuCode(u32 kver);
|
u32 emuCode(void);
|
||||||
u32 mpuCode(u32 kver);
|
u32 mpuCode(void);
|
||||||
u32 threadCode(u32 kver);
|
u32 threadCode(void);
|
||||||
u32 threadHook(u8 val, u32 kver);
|
u32 threadHook(u8 val);
|
||||||
u32 emuHook(u8 val, u32 kver);
|
u32 emuHook(u8 val);
|
||||||
u32 sigPatch(u8 val, u32 kver);
|
u32 sigPatch(u8 val);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -10,10 +10,10 @@ void *memset(void * ptr, int value, unsigned int num){
|
|||||||
}
|
}
|
||||||
|
|
||||||
int strcomp(char* s1, char* s2, unsigned int size){
|
int strcomp(char* s1, char* s2, unsigned int size){
|
||||||
for(int i = 0; i < size; i++){
|
for(int i = 0; i < size*2; i++){
|
||||||
if(s1[i] != s2[i]) return 0;
|
if(s1[i] != s2[i]) return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strcopy(char* dest, char* source, unsigned int size){
|
void strcopy(char* dest, char* source, unsigned int size){
|
||||||
|
@ -68,7 +68,9 @@ void screenShot(int frame){
|
|||||||
void patches(void){
|
void patches(void){
|
||||||
//Change version string
|
//Change version string
|
||||||
for(int i = 0; i < 0x600000; i+=4){
|
for(int i = 0; i < 0x600000; i+=4){
|
||||||
if(strcomp((void*)0x27B00000 - i, (void*)L"Ver.", 4)) strcopy((void*)0x27B00000 - i, (void*)L"\uE024Rei", 4);
|
if(strcomp((void*)0x27B00000 - i, (void*)L"Ver.", 4)){
|
||||||
|
if(strcomp((void*)0x27B00000 - i + 0x28, (void*)"T_ver_00", 4)) strcopy((void*)0x27B00000 - i, (void*)L"\uE024Rei", 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +81,7 @@ void thread(void){
|
|||||||
screenShot(BOT_FRAME);
|
screenShot(BOT_FRAME);
|
||||||
}
|
}
|
||||||
if(isPressed(BUTTON_START | BUTTON_X)){
|
if(isPressed(BUTTON_START | BUTTON_X)){
|
||||||
memdump(L"sdmc:/BootRom.bin", 0xFFFF0000, 0x8000);
|
memdump(L"sdmc:/FCRAM.bin", (void*)0x27500000, 0x600000);
|
||||||
}
|
}
|
||||||
patches();
|
patches();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user