retstr += str + " "
return retstr
-def parse_op(token_list):
+def parse_op(token_list, instr_offs):
global title
global desc
global name
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":
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")
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
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)
// 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;
}
// 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;
}