88 lines
3.2 KiB
Python
88 lines
3.2 KiB
Python
# -*- 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")
|