diff --git a/Il2CppInspector.Common/Outputs/JSONMetadata.cs b/Il2CppInspector.Common/Outputs/JSONMetadata.cs index f777aea..846ab89 100644 --- a/Il2CppInspector.Common/Outputs/JSONMetadata.cs +++ b/Il2CppInspector.Common/Outputs/JSONMetadata.cs @@ -132,10 +132,14 @@ namespace Il2CppInspector.Outputs // Metedata usage methods writeArray("methodInfoPointers", () => { - foreach (var method in model.Methods.Values.Where(m => m.HasMethodInfo)) { - writeObject(() => { + foreach (var method in model.Methods.Values.Where(m => m.HasMethodInfo)) + { + writeObject(() => + { writeName(method.MethodInfoPtrAddress, method.ToMangledMethodInfoString()); writeDotNetSignature(method.Method); + if (method.HasCompiledCode) + writer.WriteString("methodAddress", method.MethodCodeAddress.ToAddressString()); }); } }, "MethodInfo pointers"); diff --git a/Il2CppInspector.Common/Outputs/ScriptResources/Targets/Ghidra.py b/Il2CppInspector.Common/Outputs/ScriptResources/Targets/Ghidra.py index 81d05ca..11dffb5 100644 --- a/Il2CppInspector.Common/Outputs/ScriptResources/Targets/Ghidra.py +++ b/Il2CppInspector.Common/Outputs/ScriptResources/Targets/Ghidra.py @@ -64,11 +64,12 @@ def script_prologue(status): if currentProgram.getExecutableFormat().endswith('(ELF)'): currentProgram.setImageBase(toAddr(%IMAGE_BASE%), True) +def get_script_directory(): return getSourceFile().getParentFile().toString() + def script_epilogue(status): pass - -def get_script_directory(): - return getSourceFile().getParentFile().toString() - def add_function_to_group(addr, group): pass - +def add_xref(addr, to): pass +def create_fake_segment(name, size): pass +def write_string(addr, string): pass +def write_address(addr, value): pass class StatusWrapper(BaseStatusHandler): pass \ No newline at end of file diff --git a/Il2CppInspector.Common/Outputs/ScriptResources/Targets/IDA.py b/Il2CppInspector.Common/Outputs/ScriptResources/Targets/IDA.py index 09452df..67de37f 100644 --- a/Il2CppInspector.Common/Outputs/ScriptResources/Targets/IDA.py +++ b/Il2CppInspector.Common/Outputs/ScriptResources/Targets/IDA.py @@ -26,9 +26,11 @@ except ImportError: cached_genflags = 0 skip_make_function = False func_dirtree = None +is_32_bit = False +fake_segments_base = None def script_prologue(status): - global cached_genflags, skip_make_function, func_dirtree + global cached_genflags, skip_make_function, func_dirtree, is_32_bit, fake_segments_base # Disable autoanalysis cached_genflags = ida_ida.inf_get_genflags() ida_ida.inf_set_genflags(cached_genflags & ~ida_ida.INFFL_AUTO) @@ -63,8 +65,9 @@ def script_prologue(status): if FOLDERS_AVAILABLE: func_dirtree = ida_dirtree.get_std_dirtree(ida_dirtree.DIRTREE_FUNCS) - + is_32_bit = ida_ida.inf_is_32bit_exactly() + def script_epilogue(status): # Reenable auto-analysis global cached_genflags @@ -159,6 +162,38 @@ def add_function_to_group(addr, group): name = ida_funcs.get_func_name(addr) func_dirtree.rename(name, f"{group}/{name}") +def add_xref(addr, to): + ida_xref.add_dref(addr, to, ida_xref.XREF_USER | ida_xref.dr_I) + +def write_string(addr, string): + encoded_string = string.encode() + b'\x00' + string_length = len(encoded_string) + ida_bytes.put_bytes(addr, encoded_string) + ida_bytes.create_strlit(addr, string_length, ida_nalt.STRTYPE_C) + +def write_address(addr, value): + global is_32_bit + + if is_32_bit: + ida_bytes.put_dword(addr, value) + else: + ida_bytes.put_qword(addr, value) + +def create_fake_segment(name, size): + global is_32_bit + + start = ida_ida.inf_get_max_ea() + end = start + size + + ida_segment.add_segm(0, start, end, name, "DATA") + segment = ida_segment.get_segm_by_name(name) + segment.bitness = 1 if is_32_bit else 2 + segment.perm = ida_segment.SEGPERM_READ + segment.update() + + return start + +# Status handler class StatusHandler(BaseStatusHandler): def __init__(self): diff --git a/Il2CppInspector.Common/Outputs/ScriptResources/shared-main.py b/Il2CppInspector.Common/Outputs/ScriptResources/shared-main.py index 5bcc02e..13728cf 100644 --- a/Il2CppInspector.Common/Outputs/ScriptResources/shared-main.py +++ b/Il2CppInspector.Common/Outputs/ScriptResources/shared-main.py @@ -13,8 +13,11 @@ def define_il_method(jsonDef): def define_il_method_info(jsonDef): addr = parse_address(jsonDef) set_name(addr, jsonDef['name']) - set_type(addr, r'struct MethodInfo *') set_comment(addr, jsonDef['dotNetSignature']) + set_type(addr, r'struct MethodInfo *') + if 'methodAddress' in jsonDef: + add_xref(from_hex(jsonDef["methodAddress"]), addr) + def define_cpp_function(jsonDef): addr = parse_address(jsonDef) @@ -24,7 +27,6 @@ def define_cpp_function(jsonDef): def define_string(jsonDef): addr = parse_address(jsonDef) set_name(addr, jsonDef['name']) - set_type(addr, r'struct String *') set_comment(addr, jsonDef['string']) def define_field(addr, name, type, ilType = None): @@ -93,10 +95,27 @@ def process_json(jsonData, status): # String literals for version >= 19 if 'virtualAddress' in jsonData['stringLiterals'][0]: status.update_step('Processing string literals (V19+)', len(jsonData['stringLiterals'])) + + total_string_length = 0 + for d in jsonData['stringLiterals']: + total_string_length += len(d["string"]) + 1 + + aligned_length = total_string_length + (4096 - (total_string_length % 4096)) + segment_base = create_fake_segment(".fake_strings", aligned_length) + + current_string_address = segment_base for d in jsonData['stringLiterals']: define_string(d) + + ref_addr = parse_address(d) + write_string(current_string_address, d["string"]) + write_address(ref_addr, current_string_address) + set_type(ref_addr, r'const char* const') + + current_string_address += len(d["string"]) + 1 status.update_progress() + # String literals for version < 19 else: status.update_step('Processing string literals (pre-V19)')