From 1e20d98690e6ab5b65eaeb8880a618b5aa07f038 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 1 Jun 2016 09:27:47 -0400 Subject: [PATCH] Finalize bytecode specs --- doc/bytecode.md | 108 ++++++++++++++++++++++++++++++------- source/patch/aadowngrade.c | 33 ++---------- source/patch/base.c | 13 ----- source/patch/memexec.c | 10 ++++ source/patch/module.c | 2 + source/patch/prot.c | 41 +++----------- source/patch/sig.c | 9 ++++ source/patch/svc.c | 2 + source/patch/unitinfo.c | 7 +++ 9 files changed, 131 insertions(+), 94 deletions(-) diff --git a/doc/bytecode.md b/doc/bytecode.md index 6c9f6f3..3a74221 100644 --- a/doc/bytecode.md +++ b/doc/bytecode.md @@ -1,23 +1,93 @@ Bytecode format =================== -All instructions are dwords (four bytes) - this is for optimization reasons. - -Registers -------------------- -r1-r4 - General -pc - Current offset in bytecode -mem - Memory offset set. - -Instruction List -------------------- -1) call index -2) add reg, reg -3) sub reg, reg -4) mul reg, reg -5) div reg, reg -6) mov reg/ref/imm, reg/ref/imm -7) push reg -8) pop -9) .byte byte +Instructions are one byte and have a variable number of bytes afterwards. +Unless otherwise noted, if an instruction doesn't succeed, it will abort. + +rel : 2 bytes : Opcode 0x01 + Chooses firmware relativity. + + : The location and size to operate in. + 0: NATIVE_FIRM (whole size) + 1: AGB_FIRM (whole size) + 2: TWL_FIRM (whole size) + + 3: Native Proc9 ExeFS + 4: AGB Proc9 ExeFS + 5: TWL Proc9 ExeFS + + 6: Native Section 0 + 7: Native Section 1 + 8: Native Section 2 + 9: Native Section 3 + + 10: AGB Section 0 + 11: AGB Section 1 + 12: AGB Section 2 + 13: AGB Section 3 + + 14: TWL Section 0 + 15: TWL Section 1 + 16: TWL Section 2 + 17: TWL Section 3 + +find : 2 + size bytes : opcode 0x02 + Finds a pattern in memory. On success, operations + will be performed relative to the beginning of the found pattern. + + : 1 byte + How many bytes the pattern is. + : bytes + data to find + +back : 5 bytes : opcode 0x03 + Moves back bytes from current position. + + : 4 bytes + How many bytes to rewind. + +fwd : 5 bytes : opcode 0x04 + Moves forward bytes from current position. + + : 4 bytes + How many bytes to rewind. + +set : 2 + size bytes : opcode 0x05 + Copies the bytes in to the current location pointed to, + and increments the current location by bytes copied. + + : 1 byte + How many bytes to copy. + : bytes + Data to copy. + +test : 2 bytes : opcode 0x06 + Tests if the current location's data is equivalent to . + If equivalent, goes to the next instruction. If not, skips + one operation. + + NO ABORT ON FAIL + + : 1 byte + Size of data to test against. + : bytes + Pattern to test. + +jmp : 3 bytes : opcode 0x07 + Jumps to within the bytecode, and resumes execution from there. + + : 2 bytes + Offset to jump to. + +rewind : 1 byte : opcode 0x08 + Resets the location to the beginning of the space we're working off. + +and : 2 + bytes : opcode 0x09 + Performs an AND operation bitwise using data as a mask. + + : 1 byte + Size of . + + : bytes + Data to bitwise and with relative data. diff --git a/source/patch/aadowngrade.c b/source/patch/aadowngrade.c index 23622fd..64132a9 100644 --- a/source/patch/aadowngrade.c +++ b/source/patch/aadowngrade.c @@ -1,33 +1,10 @@ #include "patch_file.h" -// Do you like examples? - -/* In bytecode assembly: - - aadowngrade: - rel firm_mem - mov4 r1, pattern - mov4 r2, 6 - call memfind - jmpz notfound - - found: - add r1, 5 - mov1 [r1], 0xE0 - mov4 r1, 0 - return - - notfound: - mov4 r1, 1 - return - - pattern: - .byte 0x89 - .byte 0x0A - .byte 0x81 - .byte 0x42 - .byte 0x02 - .byte 0xD2 +/* + rel p9_exefs + find 6, 0x89, 0x0a, 0x81, 0x42, 0x02, 0xD2 + fwd 5 + set 1, 0xE0 */ PATCH(aadowngrade) diff --git a/source/patch/base.c b/source/patch/base.c index d5675b2..847740a 100644 --- a/source/patch/base.c +++ b/source/patch/base.c @@ -2,19 +2,6 @@ // Do you like examples? -/* Bytecode assembly: - - example: - mov r1, 2 - mov r2, string - call fprintf - mov r1, 0 - return - - string: - .str "Testing, testing, 1, 2, 3...\n" - */ - PATCH(example) { fprintf(stderr, "Testing, testing, 1, 2, 3, 4..\n"); diff --git a/source/patch/memexec.c b/source/patch/memexec.c index ff3afa9..7f8888c 100644 --- a/source/patch/memexec.c +++ b/source/patch/memexec.c @@ -6,6 +6,16 @@ // behavioral change that can be used maliciously and/or to // detect CFW use rather easily. +/* + rel native_s1 + find 8, 0x97, 0x05, 0x00, 0x00, 0x15, 0xE4, 0x00, 0x00 + back 1 + test 4, 0x00016416 + jmp 7 + jmp 3 + and ~(1<<4) + */ + PATCH(memexec) { firm_section_h* arm11_section = & firm_loc->section[1]; // Section 1, please. diff --git a/source/patch/module.c b/source/patch/module.c index 005d293..0db54e0 100644 --- a/source/patch/module.c +++ b/source/patch/module.c @@ -1,5 +1,7 @@ #include "patch_file.h" +/* Not possible to be implemented as bytecode. Hey, can't win em all. */ + PATCH(modules) { // TODO - load other module cxis here diff --git a/source/patch/prot.c b/source/patch/prot.c index ef2ddc2..ec2c2f1 100644 --- a/source/patch/prot.c +++ b/source/patch/prot.c @@ -2,40 +2,13 @@ // This patch applies the FIRM protection code needed for safe a9lh usage. -/* Bytecode assembly: - - firmprot: - rel firm_mem - mov r1, exe_str - mov r2, 4 - call memfind - jmpz nostr - - mov r3, r1 - mov r1, 2 - mov r2, str_atoff - call fprintf - - - - nostr: - mov r1, 2 - mov r2, noexe_str_str - call fprintf - mov r1, 0 - return - - exe_str: - .str "exe:" - noexe_str_str: - .str "Couldn't find 'exe' string.\n" - str_atoff: - .str "Firmprot: 'exe:' string @ %x\n" - firmprot_code: - .byte 0x00 - .byte 0x28 - .byte 0x01 - .byte 0xDA +/* + rel p9_exefs + find 4, "exe:" + back 0x1 + back 0xff + find 4, 0x00, 0x28, 0x01, 0xDA + set 4, 0x00, 0x20, 0xC0, 0x46 */ PATCH(firmprot) diff --git a/source/patch/sig.c b/source/patch/sig.c index 1f85495..b91e9ff 100644 --- a/source/patch/sig.c +++ b/source/patch/sig.c @@ -2,6 +2,15 @@ // This patch is responsible for fixing signature checks for the firmware. +/* + rel p9_exefs + find 4, 0xc0, 0x1c, 0x76, 0xe7 + set 2, 0x00, 0x20 + rewind + find 4, 0xb5, 0x22, 0x4d, 0x0c + set 4, 0x00, 0x20, 0x70, 0x47 + */ + PATCH(signatures) { exefs_h* firm_p9_exefs = get_firm_proc9_exefs(); diff --git a/source/patch/svc.c b/source/patch/svc.c index 912675b..ff9deed 100644 --- a/source/patch/svc.c +++ b/source/patch/svc.c @@ -1,5 +1,7 @@ #include "patch_file.h" +/* Not possible to do bytecode here, sadly. */ + // This patch handles replacement of services. This includes backdoor, but not // just backdoor. // Any service can be replaced provided there's enough space within the diff --git a/source/patch/unitinfo.c b/source/patch/unitinfo.c index 57f47c8..e143e73 100644 --- a/source/patch/unitinfo.c +++ b/source/patch/unitinfo.c @@ -5,6 +5,13 @@ // usually the ErrDisp patch in loader should be good enough for // debugging crashes. +/* + rel native_arm9 + find 4, 0x01, 0x10, 0xA0, 0x13 + fwd 3 + set 1, 0xE3 + */ + PATCH(unitinfo) { firm_section_h* arm9_section; -- 2.39.5