# -*- coding: utf-8 -*- # Headless-adapted Il2CppDumper -> Ghidra symbol applier ("fake PDB" from script.json). # Names every method, string literal and metadata entry, and creates function boundaries # from the dumper's address table -- WITHOUT Ghidra having to rediscover them via analysis. # Light path: names + function starts only (no il2cpp.h struct import, no signatures). # # Adapted from yoten/ghidra.py: replaced the interactive askFile() with a script arg / default # path so it runs under analyzeHeadless. Jython 2.7. # # Run (after the program is imported into the project): # analyzeHeadless ghidra/project SAND -process GameAssembly.dll -noanalysis \ # -scriptPath ghidra/scripts -postScript apply_il2cpp_symbols.py [path/to/script.json] # Default script.json: the live yoten dump. # @category il2cpp import json DEFAULT_SCRIPT_JSON = "/mnt/c/Users/downloadpizza/Downloads/yoten/script.json" processFields = ["ScriptMethod", "ScriptString", "ScriptMetadata", "ScriptMetadataMethod", "Addresses"] baseAddress = currentProgram.getImageBase() USER_DEFINED = ghidra.program.model.symbol.SourceType.USER_DEFINED def get_addr(addr): return baseAddress.add(addr) def set_name(addr, name): try: createLabel(addr, name.replace(' ', '-'), True, USER_DEFINED) except: pass def make_function(start): if getFunctionAt(start) is None: try: createFunction(start, None) except: pass args = getScriptArgs() path = args[0] if args else DEFAULT_SCRIPT_JSON print("apply_il2cpp_symbols: loading " + path) data = json.loads(open(path, 'rb').read().decode('utf-8')) if "Addresses" in data and "Addresses" in processFields: addresses = data["Addresses"] monitor.initialize(len(addresses)) monitor.setMessage("Function boundaries") for index in range(len(addresses) - 1): make_function(get_addr(addresses[index])) monitor.incrementProgress(1) if "ScriptMethod" in data and "ScriptMethod" in processFields: scriptMethods = data["ScriptMethod"] monitor.initialize(len(scriptMethods)) monitor.setMessage("Methods") for sm in scriptMethods: set_name(get_addr(sm["Address"]), sm["Name"].encode("utf-8")) monitor.incrementProgress(1) if "ScriptString" in data and "ScriptString" in processFields: scriptStrings = data["ScriptString"] monitor.initialize(len(scriptStrings)) monitor.setMessage("Strings") for i, ss in enumerate(scriptStrings, 1): addr = get_addr(ss["Address"]) createLabel(addr, "StringLiteral_" + str(i), True, USER_DEFINED) setEOLComment(addr, ss["Value"].encode("utf-8")) monitor.incrementProgress(1) if "ScriptMetadata" in data and "ScriptMetadata" in processFields: for md in data["ScriptMetadata"]: addr = get_addr(md["Address"]) set_name(addr, md["Name"].encode("utf-8")) setEOLComment(addr, md["Name"].encode("utf-8")) if "ScriptMetadataMethod" in data and "ScriptMetadataMethod" in processFields: for mdm in data["ScriptMetadataMethod"]: addr = get_addr(mdm["Address"]) set_name(addr, mdm["Name"].encode("utf-8")) setEOLComment(addr, mdm["Name"].encode("utf-8")) print("apply_il2cpp_symbols: done")