From aa2a486461c056a8dfd551819aebc3a601637b2c Mon Sep 17 00:00:00 2001 From: chaoskagami Date: Thu, 2 Jun 2016 08:33:09 -0400 Subject: [PATCH] All of the basic patches now use the interpreter. --- host/bytecode_asm.py | 31 +++++++++++++++++++++++++------ patch/memexec.pco | 14 +++++++------- source/interp.c | 13 +++++++++---- source/patch/memexec.c | 41 +---------------------------------------- source/patch/unitinfo.c | 40 +--------------------------------------- 5 files changed, 43 insertions(+), 96 deletions(-) diff --git a/host/bytecode_asm.py b/host/bytecode_asm.py index f82e0df..30aed0e 100755 --- a/host/bytecode_asm.py +++ b/host/bytecode_asm.py @@ -57,7 +57,7 @@ def cat_list(list): retstr += str + " " return retstr -def parse_op(token_list): +def parse_op(token_list, instr_offs): global title global desc global name @@ -134,10 +134,12 @@ def parse_op(token_list): if s != 2: syn_err("invalid number of arguments") - if len(token_list[1] == 2): - token_list[1] = "00" + token_list[1] - - return bytearray.fromhex("07" + token_list[1]) + if instr_offs == None: + return bytearray.fromhex("070000") + else: + tok = bytearray.fromhex(token_list[1]) + num = struct.unpack(">H", tok)[0] + return bytearray.fromhex("07") + struct.pack(">H", instr_offs[num]) elif token_list[0] == "rewind": return bytearray.fromhex("08") elif token_list[0] == "and": @@ -184,16 +186,33 @@ except: size = 0 +offsets = [] + with open(in_file, "r") as ins: with open(out_file, "wb") as writ: bytecode = bytearray() + # We have to do two passes because of JMP. + # One to figure out the opcode offsets, one + # to actually parse everything. + for line in ins: lines += 1 tokens = re.split("\s+", line.strip("\n")) # Split by whitespace. - bytes = parse_op(tokens) # Parse. + bytes = parse_op(tokens, None) # Parse. if bytes: + offsets += [size] size += len(bytes) + + print(offsets) + + ins.seek(0) + + for line in ins: + lines += 1 + tokens = re.split("\s+", line.strip("\n")) # Split by whitespace. + bytes = parse_op(tokens, offsets) # Parse. + if bytes: bytecode += bytes data = bytearray("AIDA") diff --git a/patch/memexec.pco b/patch/memexec.pco index 6226e98..8b20931 100644 --- a/patch/memexec.pco +++ b/patch/memexec.pco @@ -13,11 +13,11 @@ rel native_s1 find 9705000015E40000 # Move backwards until we find what we want. -# LOOP: (3) - back 01 - test 00016416 - jmp 0007 - jmp 0003 +# LOOP: (2) +back 04 +test 16640100 +jmp 0006 +jmp 0002 -# END LOOP: (7) - and efff +# END LOOP: (6) +and efff diff --git a/source/interp.c b/source/interp.c index 8031d42..4d52951 100644 --- a/source/interp.c +++ b/source/interp.c @@ -185,18 +185,23 @@ int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { code += 2; if(memcmp(current_mode->memory+offset, code, *(code-1))) { test_was_false = 1; + fprintf(stderr, "false\n"); + } else { + fprintf(stderr, "true\n"); } - offset += *(code-1); code += *(code-1); break; case OP_JMP: // Jump to offset. if (debug) fprintf(stderr, "jmp\n"); code++; - if (!test_was_false) - code = bytecode + *((uint16_t*)code); - else + if (!test_was_false) { + fprintf(stderr, "jmp to %hu,%hu\n", code[0], code[1]); + code = bytecode + code[1] + ( code[0] * 0x100 ); + } else { + code += 2; test_was_false = 0; + } break; case OP_REWIND: if (debug) diff --git a/source/patch/memexec.c b/source/patch/memexec.c index 7f8888c..4fc0b33 100644 --- a/source/patch/memexec.c +++ b/source/patch/memexec.c @@ -6,48 +6,9 @@ // 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. - - uint8_t* firm_mem = (uint8_t*)firm_loc + arm11_section->offset; - uint32_t size = arm11_section->size; - - const uint8_t pattern[] = {0x97, 0x05, 0x00, 0x00, 0x15, 0xE4, 0x00, 0x00}; - - // We look for 'exe:' first; this string is close to what we patch - uint32_t* off = (uint32_t*)memfind(firm_mem, size, pattern, 8); - - if (off == NULL) { - fprintf(stderr, "memexec: couldn't find pattern.\n"); - return 1; - } - - // NOTE - Luma3DS' check here was incoherent. - // It read as 'decrement until 0x00000000, which means on - // failure it would cause lockup due to read of unreadable mapped areas. - // Even worse, it could end up patching something that isn't in FCRAM. - while(off > (uint32_t*)firm_mem && *off != 0x16416) - off--; - - if(off == (uint32_t*)firm_mem) { - fprintf(stderr, "memexec: beginning missing.\n"); - return 1; - } - - *off &= ~(1 << 4); //Clear XN bit - - fprintf(stderr, "memexec: Cleared XN bit.\n"); + execb(PATH_PATCHES "/memexec.vco"); return 0; } diff --git a/source/patch/unitinfo.c b/source/patch/unitinfo.c index e143e73..9649449 100644 --- a/source/patch/unitinfo.c +++ b/source/patch/unitinfo.c @@ -5,47 +5,9 @@ // 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; - int found_sect = 0; - - for (arm9_section = firm_loc->section; - arm9_section < firm_loc->section + 4; arm9_section++) { - if (arm9_section->type == FIRM_TYPE_ARM9) { - found_sect = 1; - break; - } - } - - if (!found_sect) { - fprintf(stderr, "unitinfo: no arm9 section?\n"); - return 1; - } - - uint8_t* firm_mem = (uint8_t*)firm_loc + arm9_section->offset; - uint32_t size = arm9_section->size; - - const uint8_t pattern[] = {0x01, 0x10, 0xA0, 0x13}; - - // We look for 'exe:' first; this string is close to what we patch - uint8_t* off = memfind(firm_mem, size, pattern, 4); - - if (off == NULL) { - fprintf(stderr, "unitinfo: Couldn't find UNITINFO.\n"); - return 1; - } - - off[3] = 0xE3; - - fprintf(stderr, "unitinfo: Applied\n"); + execb(PATH_PATCHES "/unitinfo.vco"); return 0; } -- 2.39.5