Add embedded resources for universal script handling (ScriptResources)
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Cpp\UnityHeaders\**" />
|
||||
<EmbeddedResource Include="Cpp\Il2CppAPIHeaders\**" />
|
||||
<EmbeddedResource Include="Outputs\ScriptResources\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
55
Il2CppInspector.Common/Outputs/ScriptResources/ghidra-api.py
Normal file
55
Il2CppInspector.Common/Outputs/ScriptResources/ghidra-api.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# Ghidra-specific implementation
|
||||
from ghidra.app.cmd.function import ApplyFunctionSignatureCmd
|
||||
from ghidra.app.script import GhidraScriptUtil
|
||||
from ghidra.app.util.cparser.C import CParserUtils
|
||||
from ghidra.program.model.symbol import SourceType
|
||||
|
||||
def SetName(addr, name):
|
||||
createLabel(toAddr(addr), name, True)
|
||||
|
||||
def MakeFunction(start, name=None):
|
||||
addr = toAddr(start)
|
||||
# Don't override existing functions
|
||||
fn = getFunctionAt(addr)
|
||||
if fn is not None and name is not None:
|
||||
# Set existing function name if name available
|
||||
fn.setName(name, SourceType.USER_DEFINED)
|
||||
elif fn is None:
|
||||
# Create new function if none exists
|
||||
createFunction(addr, name)
|
||||
# Set header comment if name available
|
||||
if name is not None:
|
||||
setPlateComment(addr, name)
|
||||
|
||||
def DefineCode(code):
|
||||
# Code declarations are not supported in Ghidra
|
||||
# This only affects string literals for metadata version < 19
|
||||
# TODO: Replace with creating a DataType for enums
|
||||
pass
|
||||
|
||||
def SetFunctionType(addr, sig):
|
||||
typeSig = CParserUtils.parseSignature(None, currentProgram, sig)
|
||||
ApplyFunctionSignatureCmd(toAddr(addr), typeSig, SourceType.USER_DEFINED).applyTo(currentProgram)
|
||||
|
||||
def SetType(addr, type):
|
||||
if type.startswith('struct '):
|
||||
type = type[7:]
|
||||
|
||||
t = getDataTypes(type)[0]
|
||||
addr = toAddr(addr)
|
||||
removeDataAt(addr)
|
||||
createData(addr, t)
|
||||
|
||||
def SetComment(addr, text):
|
||||
setEOLComment(toAddr(addr), text)
|
||||
|
||||
def SetHeaderComment(addr, text):
|
||||
setPlateComment(toAddr(addr), text)
|
||||
|
||||
def CustomInitializer():
|
||||
# Do we need this for PE/MachO?
|
||||
currentProgram.setImageBase(toAddr(0), True)
|
||||
|
||||
def GetScriptDirectory():
|
||||
# Ghidra doesn't define __file__ so we have to iterate all the scripts
|
||||
return next(iter(filter(lambda x: x.getName() == '%SCRIPTFILENAME%', GhidraScriptUtil.getAllScripts())), None).getParentFile().toString()
|
||||
39
Il2CppInspector.Common/Outputs/ScriptResources/ida-api.py
Normal file
39
Il2CppInspector.Common/Outputs/ScriptResources/ida-api.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# IDA-specific implementation
|
||||
import idaapi
|
||||
|
||||
def SetName(addr, name):
|
||||
ret = idc.set_name(addr, name, SN_NOWARN | SN_NOCHECK)
|
||||
if ret == 0:
|
||||
new_name = name + '_' + str(addr)
|
||||
ret = idc.set_name(addr, new_name, SN_NOWARN | SN_NOCHECK)
|
||||
|
||||
def MakeFunction(start):
|
||||
ida_funcs.add_func(start)
|
||||
|
||||
def DefineCode(code):
|
||||
idc.parse_decls(code)
|
||||
|
||||
def SetFunctionType(addr, sig):
|
||||
SetType(addr, sig)
|
||||
|
||||
def SetType(addr, type):
|
||||
ret = idc.SetType(addr, type)
|
||||
if ret is None:
|
||||
print('SetType(0x%x, %r) failed!' % (addr, type))
|
||||
|
||||
def SetComment(addr, text):
|
||||
idc.set_cmt(addr, text, 1)
|
||||
|
||||
def SetHeaderComment(addr, text):
|
||||
SetComment(addr, text)
|
||||
|
||||
def CustomInitializer():
|
||||
print('Processing Types')
|
||||
|
||||
original_macros = ida_typeinf.get_c_macros()
|
||||
ida_typeinf.set_c_macros(original_macros + ";_IDA_=1")
|
||||
idc.parse_decls("%TYPE_HEADER_RELATIVE_PATH%", idc.PT_FILE)
|
||||
ida_typeinf.set_c_macros(original_macros)
|
||||
|
||||
def GetScriptDirectory():
|
||||
return os.path.dirname(os.path.realpath(__file__))
|
||||
113
Il2CppInspector.Common/Outputs/ScriptResources/shared-main.py
Normal file
113
Il2CppInspector.Common/Outputs/ScriptResources/shared-main.py
Normal file
@@ -0,0 +1,113 @@
|
||||
# Shared interface
|
||||
def ParseAddress(d):
|
||||
return int(d['virtualAddress'], 0)
|
||||
|
||||
def DefineILMethod(jsonDef):
|
||||
addr = ParseAddress(jsonDef)
|
||||
SetName(addr, jsonDef['name'].encode('utf-8'))
|
||||
SetFunctionType(addr, jsonDef['signature'].encode('utf-8'))
|
||||
SetHeaderComment(addr, jsonDef['dotNetSignature'].encode('utf-8'))
|
||||
|
||||
def DefineILMethodInfo(jsonDef):
|
||||
addr = ParseAddress(jsonDef)
|
||||
SetName(addr, jsonDef['name'].encode('utf-8'))
|
||||
SetType(addr, r'struct MethodInfo *')
|
||||
SetComment(addr, jsonDef['dotNetSignature'].encode('utf-8'))
|
||||
|
||||
def DefineCppFunction(jsonDef):
|
||||
addr = ParseAddress(jsonDef)
|
||||
SetName(addr, jsonDef['name'].encode('utf-8'))
|
||||
SetFunctionType(addr, jsonDef['signature'].encode('utf-8'))
|
||||
|
||||
def DefineString(jsonDef):
|
||||
addr = ParseAddress(jsonDef)
|
||||
SetName(addr, jsonDef['name'].encode('utf-8'))
|
||||
SetType(addr, r'struct String *')
|
||||
SetComment(addr, jsonDef['string'].encode('utf-8'))
|
||||
|
||||
def DefineFieldFromJson(jsonDef):
|
||||
DefineField(jsonDef['virtualAddress'], jsonDef['name'], jsonDef['type'], jsonDef['dotNetType'])
|
||||
|
||||
def DefineField(addr, name, type, ilType = None):
|
||||
addr = int(addr, 0)
|
||||
SetName(addr, name.encode('utf-8'))
|
||||
SetType(addr, type.encode('utf-8'))
|
||||
if (ilType is not None):
|
||||
SetComment(addr, ilType.encode('utf-8'))
|
||||
|
||||
# Process JSON
|
||||
def ProcessJSON(jsonData):
|
||||
|
||||
# Method definitions
|
||||
print('Processing method definitions')
|
||||
for d in jsonData['methodDefinitions']:
|
||||
DefineILMethod(d)
|
||||
|
||||
# Constructed generic methods
|
||||
print('Processing constructed generic methods')
|
||||
for d in jsonData['constructedGenericMethods']:
|
||||
DefineILMethod(d)
|
||||
|
||||
# Custom attributes generators
|
||||
print('Processing custom attributes generators')
|
||||
for d in jsonData['customAttributesGenerators']:
|
||||
DefineCppFunction(d)
|
||||
|
||||
# Method.Invoke thunks
|
||||
print('Processing Method.Invoke thunks')
|
||||
for d in jsonData['methodInvokers']:
|
||||
DefineCppFunction(d)
|
||||
|
||||
# String literals for version >= 19
|
||||
print('Processing string literals')
|
||||
if 'virtualAddress' in jsonData['stringLiterals'][0]:
|
||||
for d in jsonData['stringLiterals']:
|
||||
DefineString(d)
|
||||
|
||||
# String literals for version < 19
|
||||
else:
|
||||
litDecl = 'enum StringLiteralIndex {\n'
|
||||
for d in jsonData['stringLiterals']:
|
||||
litDecl += " " + d['name'].encode('utf-8') + ",\n"
|
||||
litDecl += '};\n'
|
||||
DefineCode(litDecl)
|
||||
|
||||
# Il2CppClass (TypeInfo) pointers
|
||||
print('Processing Il2CppClass (TypeInfo) pointers')
|
||||
for d in jsonData['typeInfoPointers']:
|
||||
DefineFieldFromJson(d)
|
||||
|
||||
# Il2CppType (TypeRef) pointers
|
||||
print('Processing Il2CppType (TypeRef) pointers')
|
||||
for d in jsonData['typeRefPointers']:
|
||||
DefineField(d['virtualAddress'], d['name'], r'struct Il2CppType *', d['dotNetType'])
|
||||
|
||||
# MethodInfo pointers
|
||||
print('Processing MethodInfo pointers')
|
||||
for d in jsonData['methodInfoPointers']:
|
||||
DefineILMethodInfo(d)
|
||||
|
||||
# Function boundaries
|
||||
print('Processing function boundaries')
|
||||
for d in jsonData['functionAddresses']:
|
||||
MakeFunction(int(d, 0))
|
||||
|
||||
# IL2CPP type metadata
|
||||
print('Processing IL2CPP type metadata')
|
||||
for d in jsonData['typeMetadata']:
|
||||
DefineField(d['virtualAddress'], d['name'], d['type'])
|
||||
|
||||
# IL2CPP function metadata
|
||||
print('Processing IL2CPP function metadata')
|
||||
for d in jsonData['functionMetadata']:
|
||||
DefineCppFunction(d)
|
||||
|
||||
# Entry point
|
||||
print('Generated script file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty')
|
||||
CustomInitializer()
|
||||
|
||||
with open(os.path.join(GetScriptDirectory(), "%JSON_METADATA_RELATIVE_PATH%"), "r") as jsonFile:
|
||||
jsonData = json.load(jsonFile)['addressMap']
|
||||
ProcessJSON(jsonData)
|
||||
|
||||
print('Script execution complete.')
|
||||
@@ -0,0 +1,3 @@
|
||||
# Generated script file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty
|
||||
import json
|
||||
import os
|
||||
Reference in New Issue
Block a user