Skip to content

Instantly share code, notes, and snippets.

@Reisyukaku
Created April 27, 2024 09:39
Show Gist options
  • Save Reisyukaku/98956092615231589d08abf31e40cbc9 to your computer and use it in GitHub Desktop.
Save Reisyukaku/98956092615231589d08abf31e40cbc9 to your computer and use it in GitHub Desktop.
Hacky script to dump lua class structure of pkmn SV
from ghidra.program.model.listing import CodeUnit
from ghidra.app.util.datatype import DataTypeSelectionDialog
from ghidra.program.model.data import ArrayDataType, DataUtilities
from ghidra.util.data.DataTypeParser import AllowedDataTypes
from ghidra.program.model.symbol import Namespace, SourceType
import re
def CalculateArraySize(addr):
i = 0
while getLong(addr) > 0:
addr = addr.add(16)
i = i + 1
return i
def NameRef(addr):
func = getFunctionAt(addr)
code_unit_iterator = listing.getCodeUnitIterator(CodeUnit.INSTRUCTION_PROPERTY, func.getBody(), True)
tableAddr = 0
base = 0
code_unit = code_unit_iterator.next()
while code_unit_iterator.hasNext():
if code_unit.getMnemonicString() == "adrp":
base = code_unit.getScalar(1).getValue()
code_unit = code_unit_iterator.next()
if base > 0 and (code_unit.getMnemonicString() == "str" or code_unit.getMnemonicString() == "ldr"):
pattern = re.compile(r'#(-?0x[0-9a-fA-F]+|\d+)')
match = re.search(pattern, code_unit.toString())
if match:
immediate_value = match.group(1)
tableAddr = base + int(immediate_value, 16)
break
code_unit = code_unit_iterator.next()
if tableAddr > 0:
symbol = getSymbolAt(toAddr(tableAddr))
symbol.setName(class_name + "_Ref", SourceType.USER_DEFINED)
#print(symbol.getName())
def printNonStaticFuncTable(tableAddr, tblSize):
data = listing.getDefinedDataAt(tableAddr)
size = data.getDataType().getLength() / tblSize
for i in range(1,tblSize):
off = tableAddr.add(i * size)
strPtr = getLong(off)
print("\tfunction " + getDataAt(toAddr(strPtr)).getValue() + "();")
def printStaticFuncTable(tableAddr, tblSize):
data = listing.getDefinedDataAt(tableAddr)
size = data.getDataType().getLength() / tblSize
for i in range(0,tblSize):
off = tableAddr.add(i * size)
strPtr = getLong(off)
print("\tstatic function " + getDataAt(toAddr(strPtr)).getValue() + "();")
def createTable(tableAddr, tblcnt):
print("{}[{}] @ {}".format(data_type.getDisplayName(), str(tblcnt), tableAddr.toString()))
try:
array_type = ArrayDataType(data_type, tblcnt, data_type.getLength())
DataUtilities.createData(current_prog, tableAddr, array_type, array_type.getLength(), True, DataUtilities.ClearDataMode.CLEAR_ALL_CONFLICT_DATA)
print("Data type set.")
except:
print("Error creating type @ " + tableAddr.toString())
def parseTableInfo(addr):
print("\nclass " + class_name + " {")
func = getFunctionAt(addr)
if func is not None:
code_unit_iterator = listing.getCodeUnitIterator(CodeUnit.INSTRUCTION_PROPERTY, func.getBody(), True)
firstFound = False
while code_unit_iterator.hasNext():
code_unit = code_unit_iterator.next()
if code_unit.getMnemonicString() == "bl":
target = code_unit.getOperandReferences(0)[0].getToAddress()
if firstFound == False:
NameRef(target)
firstFound = True
#non-static functions
if "lua_setfield" in getFunctionAt(target).getName():
code_unit = code_unit_iterator.next()
base = code_unit.getScalar(1)
code_unit = code_unit_iterator.next()
off = code_unit.getScalar(2)
tableAddr = base.getValue() + off.getValue()
arrSize = CalculateArraySize(toAddr(tableAddr))
if arrSize > 0:
'createTable(toAddr(tableAddr), arrSize)
printNonStaticFuncTable(toAddr(tableAddr), arrSize)
#Static functions
if "checkversion" in getFunctionAt(target).getName():
code_unit = code_unit_iterator.next()
while code_unit_iterator.hasNext():
if "mov w2" in code_unit.toString() or "mov x2" in code_unit.toString():
break
code_unit = code_unit_iterator.next()
tblcnt = code_unit.getScalar(1).getValue()
code_unit = code_unit_iterator.next()
tableAddr = 0
while code_unit_iterator.hasNext():
if code_unit.getMnemonicString() == "adrp":
base = code_unit.getScalar(1)
code_unit = code_unit_iterator.next()
off = code_unit.getScalar(2)
tableAddr = base.getValue() + off.getValue()
break
code_unit = code_unit_iterator.next()
if tableAddr > 0:
'createTable(toAddr(tableAddr), tblcnt)
printStaticFuncTable(toAddr(tableAddr), tblcnt)
else:
print("Error finding table addr")
print("}")
else:
print("No function found at the specified address.")
def parseClassDef(addr):
func = getFunctionAt(addr)
if func is not None:
code_unit_iterator = listing.getCodeUnitIterator(CodeUnit.INSTRUCTION_PROPERTY, func.getBody(), True)
while code_unit_iterator.hasNext():
code_unit = code_unit_iterator.next()
if code_unit.getMnemonicString() == "adrp" and "x1" in code_unit.toString():
target = code_unit.getScalar(1)
code_unit = code_unit_iterator.next()
off = code_unit.getScalar(2)
global class_name
class_name = getDataAt(toAddr(target.getValue() + off.getValue())).getValue()
if code_unit.getMnemonicString() == "adrp" and "x2" in code_unit.toString():
target = code_unit.getScalar(1)
code_unit = code_unit_iterator.next()
off = code_unit.getScalar(2)
fun = target.getValue() + off.getValue()
parseTableInfo(toAddr(fun))
else:
print("No function found at the specified address.")
def defineClasses(addr):
func = getFunctionAt(addr)
if func is not None:
code_unit_iterator = listing.getCodeUnitIterator(CodeUnit.INSTRUCTION_PROPERTY, func.getBody(), True)
while code_unit_iterator.hasNext():
code_unit = code_unit_iterator.next()
if code_unit.getMnemonicString() == "bl" or code_unit.getMnemonicString() == "b":
target = code_unit.getOperandReferences(0)[0].getToAddress()
parseClassDef(target)
else:
print("No function found at the specified address.")
current_prog = getCurrentProgram()
listing = current_prog.getListing()
data_type_manager = current_prog.getDataTypeManager()
tool = state.getTool()
selectionDialog = DataTypeSelectionDialog(tool, data_type_manager, -1, AllowedDataTypes.FIXED_LENGTH)
tool.showDialog(selectionDialog)
data_type = selectionDialog.getUserChosenDataType()
defineClasses(toAddr(0x710129bb70))
defineClasses(toAddr(0x7101295610))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment