def get_dtype(self): if self.dtype is not None: return self.dtype dm = currentProgram.getDataTypeManager() bdm = BuiltInDataTypeManager.getDataTypeManager() new_struct = StructureDataType(CategoryPath("/struct"), self.name, self.size) size_lookup = {} size_lookup[1] = bdm.getDataType("/char") size_lookup[2] = bdm.getDataType("/short") size_lookup[4] = bdm.getDataType("/int") size_lookup[8] = bdm.getDataType("/longlong") off = 0 for i in range(len(self.members)): t, size = self.members[i][0], self.members[i][1] comment = "" if len(self.members[i]) > 2 and self.members[i][2] == False: comment = "NOT ACCESSED" if isinstance(t, Struct): if not t.is_array: sub_struct_dtype = t.get_dtype() new_struct.replaceAtOffset(off, sub_struct_dtype, ARCH_BITS / 8, "entry_{}".format(i), comment) else: arr_dtype = bdm.getPointer(size_lookup[1], ARCH_BITS / 8) new_struct.replaceAtOffset(off, arr_dtype, ARCH_BITS / 8, "entry_{}".format(i), comment) else: if size not in size_lookup: arr_dtype = ArrayDataType(size_lookup[1], size, 1) new_struct.replaceAtOffset(off, arr_dtype, size, "entry_{}".format(i), comment) else: new_struct.replaceAtOffset(off, size_lookup[size], size, "entry_{}".format(i), comment) off += size print("DONE CREATING STRUCT", self.name) dm.addDataType(new_struct, DataTypeConflictHandler.REPLACE_HANDLER) self.dtype = dm.getPointer(new_struct, ARCH_BITS / 8) return self.dtype
def defineIOExternalMethodArguments(): dtm = currentProgram.getDataTypeManager() dt = find_struct("IOExternalMethodArguments") IOMemoryDescriptor = find_struct("IOMemoryDescriptor") if IOMemoryDescriptor == None: IOMemoryDescriptor = dtm.getDataType("/ulonglong") new = None if dt == None: dt = StructureDataType("IOExternalMethodArguments", 0) new = dt elif dt.getLength() > 1: yes = askYesNo( "IOExternalMethodArguments", "[-] Looks like IOExternalMethodArguments is already defined, continue ?" ) if yes == False: exit() uint = dtm.getDataType("/uint") ulonglong = dtm.getDataType("/ulonglong") st = dt st.add(uint, "version", "") st.add(uint, "selector", "") st.add(ulonglong, "asyncWakePort", "") st.add(PointerDataType(uint), "asyncReference", "") st.add(uint, "asyncReferenceCount", "") st.add(PointerDataType(ulonglong), "scalarInput", "") st.add(uint, "scalarInputCount", "") st.add(PointerDataType(ulonglong), "structureInput", "") st.add(uint, "structureInputSize", "") st.add(PointerDataType(IOMemoryDescriptor), "StructureInputDescriptor", "") st.add(PointerDataType(ulonglong), "scalarOutput", "") st.add(uint, "scalarOutputCount", "") st.add(PointerDataType(ulonglong), "structureOutput", "") st.add(uint, "structureOutputSize", "") st.add(PointerDataType(IOMemoryDescriptor), "structureOutputDescriptor", "") st.add(uint, "structureOutputDescriptorSize", "") st.add(uint, "__reservedA", "") st.add(PointerDataType(ulonglong), "structureVariableOutputData", "") st.setInternallyAligned(True) if new: dtm.addDataType(new, None) dtm.addDataType(PointerDataType(new), None)
def prepareClassName(className, classSize): locs = ["/", "/Demangler/"] for location in locs: res = findDataTypeByName(location + className) if res: return class_struct = StructureDataType(className, 0) currentProgram.getDataTypeManager().addDataType(class_struct, None)
def createClassType(namespace, vftableDataType): dtm = currentProgram.getDataTypeManager() categoryPath="/%s" % ('/'.join(namespace.split("::")[:-1])) #structDataType=StructureDataType(CategoryPath(categoryPath), namespace.split('::')[-1], 0) structDataType=StructureDataType(CategoryPath(categoryPath), namespace, 0) dt=dtm.addDataType(structDataType, DataTypeConflictHandler.REPLACE_HANDLER) p=PointerDataType(vftableDataType) dt.add(p, currentProgram.getDefaultPointerSize(), "fvtable","") return dt
def createVftableType(namespace, length): dtm = currentProgram.getDataTypeManager() programName = getProgramFile().getName() categoryPath="/%s" % ('/'.join(namespace.split("::")[:-1])) #category=dtm.createCategory(CategoryPath(categoryPath)) structDataType=StructureDataType(CategoryPath(categoryPath), "%s_vftable" % namespace.split('::')[-1], 0) dt=dtm.addDataType(structDataType, DataTypeConflictHandler.REPLACE_HANDLER) for i in range(0,length): p=PointerDataType() dt.add(p, currentProgram.getDefaultPointerSize(), "member%X" % (i),"") return dt
def create_types(self): """ Create custom data types if the don't exist yet (why would they?). """ self.function_type = dtm.getDataType("/ScatterLoadSubFunction") if not self.function_type: self.function_type = FunctionDefinitionDataType("ScatterLoadSubFunction") self.function_type.setReturnType(VoidDataType.dataType) self.function_type.setArguments([ ParameterDefinitionImpl("source", PointerDataType(VoidDataType.dataType), None), ParameterDefinitionImpl("destination", PointerDataType(VoidDataType.dataType), None), ParameterDefinitionImpl("dest_size", UnsignedIntegerDataType.dataType, None) ]) self.table_entry_type = dtm.getDataType("/ScatterLoadTableEntry") if not self.table_entry_type: self.table_entry_type = StructureDataType("ScatterLoadTableEntry", 0) self.table_entry_type.add(PointerDataType(VoidDataType.dataType), 0, "source", "Source data for RAM initialization") self.table_entry_type.add(PointerDataType(VoidDataType.dataType), 0, "destination", "Start of target area in RAM") self.table_entry_type.add(UnsignedIntegerDataType.dataType, 0, "dest_size", "Length of target area in RAM, in bytes") self.table_entry_type.add(PointerDataType(self.function_type), 0, "func", "Function to be called")
def defineIOExternalTrap(): dtm = currentProgram.getDataTypeManager() dt = dtm.findDataType(currentProgram.getName() + "/" + "IOExternalTrap") uint = dtm.getDataType("/uint") IOService = dtm.getDataType("/IOService") IOTrap_def = "IOService::IOTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)" fdef = FunctionDefinitionDataType(IOTrap_def) fdef.setReturnType(uint) fdef.setGenericCallingConvention(GenericCallingConvention.thiscall) st = StructureDataType("IOExternalTrap", 0) st.setToMachineAlignment() st.add(PointerDataType(IOService), "object", "") st.add(PointerDataType(fdef), "func", "") dtm.addDataType(PointerDataType(st), None)
def create_vtable_structures(class_name): this_class = found_classes[class_name] # Create a new struct vtable_structure_size = this_class.vtable_size * 4 vtable_struct = StructureDataType(this_class.vtable_struct_name, vtable_structure_size) # Add the base functions if this is a BASE vtable if this_class.name.startswith("BASE"): for index, base_function_name in enumerate( ("CheckType", "GetType", "Destructor", "AddRef", "Release")): vtable_struct.replaceAtOffset(index * 4, pointer_type, 4, base_function_name, "Base class function") else: # Add the parent class's vtable structure parent_class = found_classes[this_class.parent] parent_vtable_struct_path = "/" + parent_class.vtable_struct_name parent_vtable_struct = currentProgram.getDataTypeManager( ).getDataType(parent_vtable_struct_path) assert parent_vtable_struct is not None vtable_struct.replaceAtOffset(0, parent_vtable_struct, parent_class.vtable_size * 4, parent_class.name, "Base class") # Add pointer-sized values for any remaining values for index in range(parent_class.vtable_size, this_class.vtable_size): vtable_struct.replaceAtOffset(index * 4, pointer_type, 4, None, None) # If the struct already exists, a new struct will be created with ".conflict" in the name vtable_struct = currentProgram.getDataTypeManager().addDataType( vtable_struct, DataTypeConflictHandler.KEEP_HANDLER) # Set the class struct's vtable pointer to point to the new vtable structure class_namespace = symbol_table.getNamespace(this_class.name, None) class_struct = VariableUtilities.findOrCreateClassStruct( class_namespace, currentProgram.getDataTypeManager()) ptr_to_vtable_type = PointerDataType(vtable_struct) class_struct.replaceAtOffset(0, ptr_to_vtable_type, 4, "vtable", None)
def get_structure(entry): path = get_datatype_path(entry).getCategoryPath() dtm = currentProgram.getDataTypeManager() struct = StructureDataType(path, entry["Name"], 0, dtm) for comp in entry["Components"]: if comp["bitfield"]: bitfield = comp["bitfield"] struct.insertBitfieldAt(comp["offset"], bitfield["byteWidth"], bitfield["bitOffset"], get_datatype(bitfield["DataType"]), bitfield["bitSize"], comp["name"], comp["comment"]) else: struct.insertAtOffset( comp["offset"], get_datatype(comp["DataType"]), comp["length"], comp["name"], comp["comment"])
src = prog elif dst_prog_string == prog.getName(): dst = prog if src == None or dst == None: popup("Could not get src/dst program") exit(0) print src,dst src_dtm = src.getDataTypeManager() dst_dtm = dst.getDataTypeManager() structs = src_dtm.getAllStructures() for s in structs: name = s.getName() res = isThere('/'+name,dst_dtm) if res == True: continue res = isThere('/Demangler/'+name,dst_dtm) if res == True: continue struct = StructureDataType(name,0) dst_dtm.addDataType(struct,None) dst_dtm.addDataType(PointerDataType(struct),None)
import struct debug = False process_is_64bit = False # Init Structs ptr_data_type = PointerDataType() byte_data_type = ByteDataType() char_data_type = CharDataType() void_data_type = VoidDataType() unsigned_int_type = UnsignedIntegerDataType() short_data_type = ShortDataType() char_ptr_type = ptr_data_type.getPointer(char_data_type, 4) void_ptr_type = ptr_data_type.getPointer(void_data_type, 4) vx_5_symtbl_dt = StructureDataType("VX_5_SYMBOL_IN_TBL", 0x10) vx_5_symtbl_dt.replaceAtOffset(0, unsigned_int_type, 4, "symHashNode", "") vx_5_symtbl_dt.replaceAtOffset(4, char_ptr_type, 4, "symNamePtr", "") vx_5_symtbl_dt.replaceAtOffset(8, void_ptr_type, 4, "symPrt", "") vx_5_symtbl_dt.replaceAtOffset(0x0c, short_data_type, 4, "symGroup", "") vx_5_symtbl_dt.replaceAtOffset(0x0e, byte_data_type, 1, "symType", "") vx_5_symtbl_dt.replaceAtOffset(0x0f, byte_data_type, 1, "End", "") vx_6_symtbl_dt = StructureDataType("VX_6_SYMBOL_IN_TBL", 0x14) vx_6_symtbl_dt.replaceAtOffset(0, unsigned_int_type, 4, "symHashNode", "") vx_6_symtbl_dt.replaceAtOffset(4, char_ptr_type, 4, "symNamePtr", "") vx_6_symtbl_dt.replaceAtOffset(8, void_ptr_type, 4, "symPrt", "") vx_6_symtbl_dt.replaceAtOffset(0x0c, unsigned_int_type, 4, "symRef", "moduleId of module, or predefined SYMREF") vx_6_symtbl_dt.replaceAtOffset(0x10, short_data_type, 4, "symGroup", "") vx_6_symtbl_dt.replaceAtOffset(0x12, byte_data_type, 1, "symType", "")
class KeilRAMInit(object): """ The main flow of the script, put into a class so we can break out logical sections of the flow into methods and store intermediate data in the class instance. """ def run(self): """ The high-level flow """ self.ram_block = memory.getBlock("ram") if not self.ram_block or self.ram_block.isInitialized(): yikes("No uninitialized memory block named 'ram' found") if currentSelection is None or currentSelection.isEmpty(): self.scatterload_function = listing.getFunctionContaining(currentAddress) if not self.scatterload_function: yikes("Please launch the script from within a function") self.find_scatterload_table() else: self.scatterload_table = currentSelection.getFirstRange() print("Scatterload table at", self.scatterload_table) self.create_types() self.parse_scatterload_table() if not (self.data_init_start and self.ram_clear_start): yikes("Data init or RAM clear entry are missing from the scatterload table") print("Initialization data at %s (%d bytes)" % (self.data_init_start, self.data_size_packed)) print("Uncompressed initialized data size: %d bytes" % self.data_size_unpacked) print("Zeroed data at %s (%d bytes)" % (self.ram_clear_start, self.ram_clear_size)) self.uncompress_init_data() self.create_ram_blocks() print(r"All done \o/") def create_types(self): """ Create custom data types if the don't exist yet (why would they?). """ self.function_type = dtm.getDataType("/ScatterLoadSubFunction") if not self.function_type: self.function_type = FunctionDefinitionDataType("ScatterLoadSubFunction") self.function_type.setReturnType(VoidDataType.dataType) self.function_type.setArguments([ ParameterDefinitionImpl("source", PointerDataType(VoidDataType.dataType), None), ParameterDefinitionImpl("destination", PointerDataType(VoidDataType.dataType), None), ParameterDefinitionImpl("dest_size", UnsignedIntegerDataType.dataType, None) ]) self.table_entry_type = dtm.getDataType("/ScatterLoadTableEntry") if not self.table_entry_type: self.table_entry_type = StructureDataType("ScatterLoadTableEntry", 0) self.table_entry_type.add(PointerDataType(VoidDataType.dataType), 0, "source", "Source data for RAM initialization") self.table_entry_type.add(PointerDataType(VoidDataType.dataType), 0, "destination", "Start of target area in RAM") self.table_entry_type.add(UnsignedIntegerDataType.dataType, 0, "dest_size", "Length of target area in RAM, in bytes") self.table_entry_type.add(PointerDataType(self.function_type), 0, "func", "Function to be called") def extract_scatterload_A(self): """ Extract the scatterload table pointers from a function that loads the pointers individually """ load_values = [] for i, insn in enumerate(listing.getInstructions(self.scatterload_function.getEntryPoint(), True)): pair = get_load_data(insn) if pair: load_values.append(pair) if len(load_values) == 2: break if i == 8: return None print("Type A scatterload function identified") retval = [] for pointed, pointer in sorted(load_values): listing.clearCodeUnits(pointer, pointer.add(4), False) listing.createData(pointer, PointerDataType.dataType) retval.append(pointed) return retval def extract_scatterload_B(self): """ Extract the pointers from a function that uses a ldmia instruction to load both pointers at once """ insn_adr = listing.getInstructionAt(self.scatterload_function.getEntryPoint()) insn_ldmia = insn_adr.getNext() ldmia_op1 = insn_ldmia.getOpObjects(1) # We're looking for an adr/ldmia combination that loads two consecutive values into two regs if not (insn_adr.mnemonicString == "adr" and insn_ldmia.mnemonicString == "ldmia" and insn_adr.getRegister(0) == insn_ldmia.getRegister(0) and ldmia_op1 and len(ldmia_op1) == 2): return None print("Type B scatterload function identified") # The stored pointers to the scatterload table are offsets relative to the location of the first pointer offsets = currentAddress.getNewAddress(insn_adr.getOpObjects(1)[0].getValue()) listing.clearCodeUnits(offsets, offsets.add(8), False) listing.createData(offsets, UnsignedIntegerDataType.dataType) listing.createData(offsets.add(4), UnsignedIntegerDataType.dataType) return [offsets.add(offset) for offset in read_uints(offsets, 2)] def find_scatterload_table(self): """ Assuming we're really looking at the __scatterload function, extract the scatterload table location and size. """ table_pointers = self.extract_scatterload_A() or self.extract_scatterload_B() if not table_pointers: print("Cannot identify the current function as a scatterload function :(") print("If you're certain this is it please help the script along:") print(" 1. Find the scatterload table yourself - N*16 bytes large and referenced by this function") print(" 2. Select the entire table and re-run the script") exit(1) scatterload_table_start, scatterload_table_end = table_pointers symbols.createLabel(scatterload_table_start, "Region$$Table$$Base", SourceType.USER_DEFINED) symbols.createLabel(scatterload_table_end, "Region$$Table$$Limit", SourceType.USER_DEFINED) self.scatterload_function.setName("__scatterload", SourceType.USER_DEFINED) self.scatterload_table = AddressRangeImpl(scatterload_table_start, scatterload_table_end.subtract(1)) def parse_scatterload_table(self): """ Go through the scatterload table and identify the calls to unpack the init data and clear the bss section. """ self.data_init_start = None self.data_size_packed = None self.data_size_unpacked = None self.ram_clear_start = None self.ram_clear_size = None if self.scatterload_table.getLength() % 0x10: yikes("Scatterload table size not a multiple of 0x10") scatterload_nentries = self.scatterload_table.getLength() / 0x10 if scatterload_nentries < 2: yikes("Scatterload table too small to contain a decompress and clear entry") # Actually iterating might be unnecessary because the table layout is identical # in all targets I've seen so far, but what do I know. # The one assumption in here is that the unpack call comes _before_ the clear call. for entry in range(scatterload_nentries): addr = self.scatterload_table.getMinAddress().add(entry * 0x10) listing.clearCodeUnits(addr, addr.add(0x10), False) listing.createData(addr, self.table_entry_type) entry = read_uints(addr, 4) function_name = None is_rwdata_init_function = False if entry[1] == self.ram_block.getStart().getOffset(): print("Init data call found:", entry) is_rwdata_init_function = True self.data_init_start = addr.getNewAddress(entry[0]) self.data_size_unpacked = entry[2] elif self.data_init_start and entry[1] == self.ram_block.getStart().getOffset() + self.data_size_unpacked: print("Clear memory call found:", entry) function_name = "__scatterload_zeroinit" self.data_size_packed = entry[0] - self.data_init_start.getOffset() self.ram_clear_start = addr.getNewAddress(entry[1]) self.ram_clear_size = entry[2] function_addr = addr.getNewAddress(entry[3]) function = createFunction(function_addr, function_name) # Using commands for high-level operations is the "Ghidra Way" it seems: # https://github.com/NationalSecurityAgency/ghidra/issues/1126 ApplyFunctionSignatureCmd(function_addr, self.function_type, SourceType.USER_DEFINED, True, False).applyTo(currentProgram) if is_rwdata_init_function: self.rwdata_init_function = function or getFunctionAt(function_addr) def uncompress_init_data(self): """ Uncompress the init data by trying all available decompressors. """ symbols.createLabel(self.data_init_start, "rwdata_init", SourceType.USER_DEFINED).setPrimary() listing.clearCodeUnits(self.data_init_start, self.data_init_start.add(self.data_size_packed), False) listing.createData(self.data_init_start, ArrayDataType(ByteDataType.dataType, self.data_size_packed, 1)) packed_data = read_bytes(self.data_init_start, self.data_size_packed) if self.data_size_packed == self.data_size_unpacked: print("Initialization data packed size equals unpacked size, assuming no compression") self.unpacked_data = packed_data self.rwdata_init_function.setName("__scatterload_copy", SourceType.USER_DEFINED) else: print("Uncompressing initialization data") for core in unpack_cores: self.unpacked_data = unpack(packed_data, self.data_size_unpacked, core) if self.unpacked_data is not None: self.rwdata_init_function.setName(core[1], SourceType.USER_DEFINED) break else: yikes("Failed to uncompress initialization data") def create_ram_blocks(self): """ Split the ram block into parts, and initialize them with our unpacked data and zeros respectively. """ print("Creating and initializing RAM blocks") undef_start = self.ram_clear_start.add(self.ram_clear_size) ram_init = self.ram_block ram_init.setName("ram.init") memory.split(ram_init, self.ram_clear_start) ram_clear = memory.getBlock(self.ram_clear_start) ram_clear.setName("ram.clear") memory.split(ram_clear, undef_start) ram_undef = memory.getBlock(undef_start) ram_undef.setName("ram.undef") ram_clear = memory.convertToInitialized(ram_clear, 0) ram_init = memory.convertToInitialized(ram_init, 0) ram_init.putBytes(ram_init.getStart(), array("b", array("B", self.unpacked_data).tostring()))
'char16': '/char16', 'V3f': '/V3f' } for key, primitive in stuff['primitives'].iteritems(): key = int(key) print('key:%x -> prim:%r' % (key, primitive)) if primitive['name'] in primMap: dt = dtmgr.getDataType(primMap[primitive['name']]) assert dt != None assert dt.length == primitive['size'] print('resolved to %r' % dt) typeMap[key] = dt elif key not in typeMap: print('creating type') dt = StructureDataType(saveCatPath, 'SP' + primitive['name'], primitive['size'], dtmgr) dt.description = 'saveschema %08x' % key dtmgr.addDataType(dt, handler) typeMap[key] = dt else: if typeMap[key].name != 'SP' + primitive['name']: typeMap[key].name = 'SP' + primitive['name'] for key, typ in stuff['types'].iteritems(): key = int(key) print('key:%x -> struct:%s' % (key, typ['name'])) name = typ['name'] if name.startswith('::Game::Save'): name = 'GS' + name[12:] elif name.startswith('::Game::'): name = 'G' + name[8:]
# if there are indeed multiple symbols, use the first one vptr_sym = symbols[0] print("[+] vptr for {} found @ 0x{}, looking for vtable...".format( cname, vptr_sym.address)) vtable_addr = vptr_sym.address.add(alignment + 1) # one after the alignment print("[+] vtable for {} found @ 0x{}, processing entries...".format( cname, vtable_addr)) cur_addr = vtable_addr # create the new datatype (Structure/class) vtable_type_name = "VTABLE_{}".format(cname) vtable_type = StructureDataType(vtable_type_name, 0) cutoff_ctr = 0 while cutoff_ctr < cutoff: data = getDataAt(cur_addr) if not data: cur_addr = cur_addr.add(ptr_size) continue print("[!] no data @ 0x{}, bailing out...".format(cur_addr)) break # no data at this address, skip if data.isPointer(): # it will (hopefully) be a function ptr func_ptr = getFunctionAt(data.value)
from ghidra.program.model.lang import RegisterValue from java.math import BigInteger import xml.etree.ElementTree as ET import os import sys print os.getcwd() tree = ET.parse('ps3.xml') root_xml = tree.getroot() dataTypeManager = currentProgram.getDataTypeManager() memory = currentProgram.getMemory() listing = currentProgram.getListing() libstubstruc = StructureDataType(CategoryPath.ROOT, "_scelibstub", 0) libstubstruc.add(UnsignedCharDataType(), 1, "structsize", "") libstubstruc.add(UnsignedCharDataType(), 1, "reserved1", "") libstubstruc.add(UnsignedShortDataType(), 2, "version", "") libstubstruc.add(UnsignedShortDataType(), 2, "attribute", "") libstubstruc.add(UnsignedShortDataType(), 2, "nfunc", "") libstubstruc.add(UnsignedShortDataType(), 2, "nvar", "") libstubstruc.add(UnsignedShortDataType(), 2, "ntlsvar", "") libstubstruc.add(UnsignedCharDataType(), 4, "reserved2", "") libstubstruc.add(Pointer32DataType(), 4, "libname", "") libstubstruc.add(Pointer32DataType(), 4, "func_nidtable", "") libstubstruc.add(Pointer32DataType(), 4, "func_table", "") libstubstruc.add(Pointer32DataType(), 4, "var_nidtable", "") libstubstruc.add(Pointer32DataType(), 4, "var_table", "") libstubstruc.add(Pointer32DataType(), 4, "tls_nidtable", "") libstubstruc.add(Pointer32DataType(), 4, "tls_table", "")
void_data_type = VoidDataType() unsigned_int_type = UnsignedIntegerDataType() int_type = IntegerDataType() unsigned_long_type = UnsignedLongDataType() short_data_type = ShortDataType() char_ptr_type = ptr_data_type.getPointer(char_data_type, 4) void_ptr_type = ptr_data_type.getPointer(void_data_type, 4) # Prepare VxWorks symbol types vx_5_sym_enum = EnumDataType("Vx5symType", 1) for flag in vx_5_symbol_type_enum: vx_5_sym_enum.add(vx_5_symbol_type_enum[flag], flag) vx_6_sym_enum = EnumDataType("Vx6symType", 1) for flag in vx_6_symbol_type_enum: vx_6_sym_enum.add(vx_6_symbol_type_enum[flag], flag) vx_5_symtbl_dt = StructureDataType("VX_5_SYMBOL_IN_TBL", 0x10) vx_5_symtbl_dt.replaceAtOffset(0, unsigned_int_type, 4, "symHashNode", "") vx_5_symtbl_dt.replaceAtOffset(4, char_ptr_type, 4, "symNamePtr", "") vx_5_symtbl_dt.replaceAtOffset(8, void_ptr_type, 4, "symPrt", "") vx_5_symtbl_dt.replaceAtOffset(0x0c, short_data_type, 4, "symGroup", "") vx_5_symtbl_dt.replaceAtOffset(0x0e, vx_5_sym_enum, 1, "symType", "") vx_5_symtbl_dt.replaceAtOffset(0x0f, byte_data_type, 1, "End", "") vx_6_symtbl_dt = StructureDataType("VX_6_SYMBOL_IN_TBL", 0x14) vx_6_symtbl_dt.replaceAtOffset(0, unsigned_int_type, 4, "symHashNode", "") vx_6_symtbl_dt.replaceAtOffset(4, char_ptr_type, 4, "symNamePtr", "") vx_6_symtbl_dt.replaceAtOffset(8, void_ptr_type, 4, "symPrt", "") vx_6_symtbl_dt.replaceAtOffset(0x0c, unsigned_int_type, 4, "symRef", "moduleId of module, or predefined SYMREF") vx_6_symtbl_dt.replaceAtOffset(0x10, short_data_type, 4, "symGroup", "") vx_6_symtbl_dt.replaceAtOffset(0x12, vx_6_sym_enum, 1, "symType", "")
def create_trace_entry(): """create_trace_entry struct TraceEntry { uint magic; uint unk1; uint unk2; uint unk_magic; char * message; uint linenum; char * file; }; """ handler = DataTypeConflictHandler.REPLACE_HANDLER bi_dtm = BuiltInDataTypeManager.getDataTypeManager() dtm = currentProgram.getDataTypeManager() structure = StructureDataType("TraceEntry", 0) str_ptr = bi_dtm.getPointer(bi_dtm.getDataType("/string")) uint_ty = bi_dtm.getDataType("/uint") structure.add(uint_ty, 4, "magic", "") structure.add(uint_ty, 4, "unk1", "") structure.add(uint_ty, 4, "unk2", "") structure.add(uint_ty, 4, "unk_magic", "") structure.add(str_ptr, 4, "message", "") structure.add(uint_ty, 4, "linenum", "") structure.add(str_ptr, 4, "file", "") dtm.addDataType(structure, handler)
if (len(peripheral.registers) == 0): print("\t\tNo registers.") continue if (not peripheral.address_blocks): continue if (len(peripheral.address_blocks) == 0): continue try: # Iterage through addressBlock of a Peripheral. # For each addressBlock create a pripheral strcuture with the name of the peripheral and the size of the actual addressBlock. # For each addessBlock iterate through the registers of the peripheral and add a register, if the offset mathes to the address range of the current addressBlock. # Enter the addressBlock specific peripheral to Ghidra. # Since all these addressBlock-peripheral entries share the same same, they pop up as one name in Ghidra. length = calculate_peripheral_size(peripheral, 32) # Generate structure for the peripheral peripheral_struct = StructureDataType(peripheral.name, length) dtm.addDataType(peripheral_struct, DataTypeConflictHandler.REPLACE_HANDLER) baseAdr = peripheral.base_address for adrBlock in peripheral.address_blocks: addr = space.getAddress(baseAdr + adrBlock.offset) # Generate peripheral-strcuture for an address block peripheral_blk_struct = StructureDataType(peripheral.name, adrBlock.size) # iterate through all registers in the peripheral and add it to the addressBlock-peripheral structure # when the register is part of this addressBlock. addRegisters(peripheral_blk_struct, peripheral, 32) addRegisters(peripheral_blk_struct, peripheral, 24) addRegisters(peripheral_blk_struct, peripheral, 16)
def createStructure(self, element): """ Convert CastXML XML element into a Ghidra StructureDataType. Args: element (ElementTree): XML element Returns (StructureDataType): Ghidra StructureDataType """ structName = "" if 'name' in element.attrib: structName = element.attrib['name'] if structName == "": structName = "anon_struct" + element.attrib['id'] structByteSize = 0 if 'size' in element.attrib: structBitSize = int(element.attrib['size']) structByteSize = structBitSize / 8 structAlign = 0 if 'align' in element.attrib: structAlign = int(element.attrib['align']) / 8 filePath = self.getFileFromId(element.attrib['file']) categoryPath = self.getCategoryPathFromFile(filePath) print("Struct: {0}".format(structName)) structureDataType = StructureDataType(categoryPath, structName, structByteSize, self.dtMgr) # These will allow Ghidra to pack and align our data types to our program's specs. # Unused for now. Let's respect what we have from CastXML. #structureDataType.setMinimumAlignment(structAlign) #structureDataType.setPackingValue(structAlign) self.recordTypeForId(element.attrib['id'], structureDataType) # Load all base classes if 'bases' in element.attrib: baseElements = element.getchildren() for i, baseElement in enumerate(baseElements): baseTypeElement = self.getTypeInfoElementById( baseElement.attrib['type']) baseType = self.getDataType(baseTypeElement) baseOffset = 0 if 'offset' in baseElement.attrib: baseOffset = int(baseElement.attrib['offset']) baseName = "base" + str(i) + "_" + str(baseOffset) baseLength = baseType.getLength() structureDataType.replaceAtOffset(baseOffset, baseType, baseLength, baseName, hex(baseOffset)) # Add VTable pointer if 'abstract' in element.attrib and 'bases' not in element.attrib: if int(element.attrib['abstract']) == 1: # TODO: generate vtable structure pointerLength = self.getDefaultPointerSize() pointerType = PointerDataType(VoidDataType.dataType, pointerLength) structureDataType.replaceAtOffset(0, pointerType, pointerType.getLength(), "vtable", hex(0)) # Add each field if 'members' in element.attrib: members = element.attrib['members'] memberIds = members.split(" ") bitFieldOffset = -1 # -1 = not set bitFieldTotalSize = 0 for memberId in memberIds: fieldElement = self.getTypeInfoElementById(memberId) if fieldElement.tag != "Field": continue typeElement = self.getTypeInfoElementById( fieldElement.attrib['type']) fieldName = fieldElement.attrib['name'] fieldOffset = int(fieldElement.attrib['offset']) / 8 if fieldOffset >= structByteSize: continue # TODO: check if at end of structure and check if structure already has flexible array if typeElement.tag == "ArrayType" and int( typeElement.attrib['max']) == -1: # TODO: check if valid arrayDataType arrayElement = self.getTypeInfoElementById( typeElement.attrib['type']) arrayDataType = self.getDataType(arrayElement) structureDataType.setFlexibleArrayComponent( arrayDataType, fieldName, hex(fieldOffset)) else: fieldDataType = self.getDataType(typeElement) if 'bits' in fieldElement.attrib: # This is a bitfield byteOffset = fieldOffset if bitFieldOffset == -1: # Store first bitfield byteOffset bitFieldOffset = fieldOffset * 8 byteWidth = structureDataType.getLength() - ( bitFieldOffset / 8) #fieldDataType.getLength() bitFieldTotalSize = byteWidth * 8 bitOffset = int( fieldElement.attrib['offset']) - bitFieldOffset bitSize = int(fieldElement.attrib['bits']) try: structureDataType.insertBitFieldAt( bitFieldOffset / 8, byteWidth, bitOffset, fieldDataType, bitSize, fieldName, hex(bitOffset) + " bits") except JavaException as e: print structName + " -> " + fieldName print "Current bitfield range: " + str( bitOffset) + " - " + str(bitOffset + bitSize) print "bitFieldOffset: " + str(bitFieldOffset) print "bitFieldTotalSize: " + str( bitFieldTotalSize) print "bitFieldDataType: " + str(fieldDataType) print "bitFieldDataTypeSize: " + str( fieldDataType.getLength()) print "byteOffset: " + str(byteOffset) print "byteWidth: " + str(byteWidth) print "bitOffset: " + str(bitOffset) print "bitSize: " + str(bitSize) print e if (bitOffset + bitSize) >= bitFieldTotalSize: # This should be the last bitfield bitFieldOffset = -1 bitFieldTotalSize = 0 else: structureDataType.replaceAtOffset( fieldOffset, fieldDataType, fieldDataType.getLength(), fieldName, hex(fieldOffset) + " bytes") return structureDataType
print("Generating peripherals...") for peripheral in peripherals: print("\t" + peripheral.name) if (len(peripheral.registers) == 0): print("\t\tNo registers.") continue # try: # Iterage registers to get size of peripheral # Most SVDs have an address-block that specifies the size, but # they are often far too large, leading to issues with overlaps. length = calculate_peripheral_size(peripheral, default_register_size) # Generate structure for the peripheral peripheral_struct = StructureDataType(peripheral.name, length) peripheral_start = peripheral.base_address peripheral_end = peripheral_start + length for register in peripheral.registers: register_size = default_register_size if not register._size else register._size r_type = UnsignedIntegerDataType() rs = register_size / 8 if rs == 1: r_type = ByteDataType() elif rs == 2: r_type = UnsignedShortDataType() elif rs == 8: r_type = UnsignedLongLongDataType()
def defineIOExternalAsyncMethod(): dtm = currentProgram.getDataTypeManager() dt = dtm.findDataType(currentProgram.getName() + "/" + "IOExternalAsyncMethod") IOService = dtm.getDataType("/IOService") IOAsyncMethod_def = "uint IOService::IOAsyncMethod(uint asyncRef[8], void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)" uint = dtm.getDataType("/uint") ulonglong = dtm.getDataType("/ulonglong") fdef = parseCSignature(IOAsyncMethod_def) st = StructureDataType("IOExternalAsyncMethod", 0) #BUG: Work with alignement st.setToMachineAlignment() st.add(PointerDataType(IOService), "object", "") st.add(PointerDataType(fdef), "func", "") st.add(uint, "flags", "") st.add(ulonglong, "count0", "") st.add(ulonglong, "count1", "") dtm.addDataType(PointerDataType(st), None)
char_data_type = CharDataType() void_data_type = VoidDataType() unsigned_int_type = UnsignedIntegerDataType() short_data_type = ShortDataType() char_ptr_type = ptr_data_type.getPointer(char_data_type, 4) void_ptr_type = ptr_data_type.getPointer(void_data_type, 4) # Prepare VxWorks symbol types vx_5_sym_enum = EnumDataType("Vx5symType", 1) for flag in vx_5_symbol_type_enum: vx_5_sym_enum.add(vx_5_symbol_type_enum[flag], flag) vx_6_sym_enum = EnumDataType("Vx6symType", 1) for flag in vx_6_symbol_type_enum: vx_6_sym_enum.add(vx_6_symbol_type_enum[flag], flag) # Init VxWorks symbol table structs vx_5_symtbl_dt = StructureDataType("VX_5_SYMBOL_IN_TBL", 0x10) vx_5_symtbl_dt.replaceAtOffset(0, unsigned_int_type, 4, "symHashNode", "") vx_5_symtbl_dt.replaceAtOffset(4, char_ptr_type, 4, "symNamePtr", "") vx_5_symtbl_dt.replaceAtOffset(8, void_ptr_type, 4, "symPrt", "") vx_5_symtbl_dt.replaceAtOffset(0x0c, short_data_type, 4, "symGroup", "") vx_5_symtbl_dt.replaceAtOffset(0x0e, vx_5_sym_enum, 1, "symType", "") vx_5_symtbl_dt.replaceAtOffset(0x0f, byte_data_type, 1, "End", "") vx_6_symtbl_dt = StructureDataType("VX_6_SYMBOL_IN_TBL", 0x14) vx_6_symtbl_dt.replaceAtOffset(0, unsigned_int_type, 4, "symHashNode", "") vx_6_symtbl_dt.replaceAtOffset(4, char_ptr_type, 4, "symNamePtr", "") vx_6_symtbl_dt.replaceAtOffset(8, void_ptr_type, 4, "symPrt", "") vx_6_symtbl_dt.replaceAtOffset(0x0c, unsigned_int_type, 4, "symRef", "moduleId of module, or predefined SYMREF") vx_6_symtbl_dt.replaceAtOffset(0x10, short_data_type, 4, "symGroup", "") vx_6_symtbl_dt.replaceAtOffset(0x12, vx_6_sym_enum, 1, "symType", "")
0x07: "Global Data", 0x08: "Local BSS", 0x09: "Global BSS", 0x12: "Local Common symbol", 0x13: "Global Common symbol", 0x40: "Local Symbols related to a PowerPC SDA section", 0x41: "Global Symbols related to a PowerPC SDA section", 0x80: "Local symbols related to a PowerPC SDA2 section", 0x81: "Global symbols related to a PowerPC SDA2 section" } vx_5_sym_enum = EnumDataType("Vx5symType", 1) for flag in vx_5_symbol_type_enum: vx_5_sym_enum.add(vx_5_symbol_type_enum[flag], flag) vx_5_symtbl_dt = StructureDataType("VX_5_SYMBOL_IN_TBL", 0x10) vx_5_symtbl_dt.replaceAtOffset(0, unsigned_int_type, 4, "symHashNode", "") vx_5_symtbl_dt.replaceAtOffset(4, char_ptr_type, 4, "symNamePtr", "") vx_5_symtbl_dt.replaceAtOffset(8, void_ptr_type, 4, "symPrt", "") vx_5_symtbl_dt.replaceAtOffset(0x0c, short_data_type, 4, "symGroup", "") vx_5_symtbl_dt.replaceAtOffset(0x0e, vx_5_sym_enum, 1, "symType", "") vx_5_symtbl_dt.replaceAtOffset(0x0f, byte_data_type, 1, "End", "") vx_5_sys_symtab = StructureDataType("VX_5_SYSTEM_SYMBOL_TABLE", 0x3C) vx_5_sys_symtab.replaceAtOffset(0x00, void_ptr_type, 4, "objCore", "Pointer to object's class") vx_5_sys_symtab.replaceAtOffset(0x04, void_ptr_type, 4, "nameHashId", "Pointer to HASH_TBL") vx_5_sys_symtab.replaceAtOffset(0x08, char_data_type, 0x28, "symMutex", "symbol table mutual exclusion sem") vx_5_sys_symtab.replaceAtOffset(0x30, void_ptr_type, 4, "symPartId", "memory partition id for symbols") vx_5_sys_symtab.replaceAtOffset(0x34, unsigned_int_type, 4, "sameNameOk", "symbol table name clash policy") vx_5_sys_symtab.replaceAtOffset(0x38, unsigned_int_type, 4, "PART_ID", "current number of symbols in table")
def generateVtableStruct(vtableAddr): mem = currentProgram.getMemory() vtableClassName = structName vtableName = "vtable" + vtableClassName keepgoing = True cAddr = vtableAddr #.add(8) structData = StructureDataType(vtableName, 0) antiFreeze = 0 while True: #print("Checking " + cAddr.toString()) fnToCheck = CUManager.getCodeUnitContaining(cAddr) #print(fnToCheck.getMnemonicString()) if fnToCheck != None and fnToCheck.getMnemonicString() == "addr": #print("Found start of vtable at") cAddr = cAddr.add(4) break if antiFreeze >= 100: print("Something has to have gone wrong...") return cAddr = cAddr.add(4) antiFreeze += 1 while True: fs = getAddress(mem.getInt(cAddr)) valpart = fs.toString() fntoadd = functionManager.getFunctionContaining(getAddress(valpart)) if fntoadd != None: #print("YES, this is an pointer") #print(fntoadd) if fntoadd != None: dt = FunctionDefinitionDataType( fntoadd, False ) #Second parameter is "Formality", I think this strips the "this" parameter, so lets not set this True #dt.setCategoryPath(CategoryPath("/" + vtableName)) fnClass = getClassName(fntoadd.toString()) dt.setCategoryPath(CategoryPath("/vtable" + fnClass)) dtAdded = dataManager.addDataType( dt, DataTypeConflictHandler.REPLACE_HANDLER) ptr = PointerDataType(dtAdded) #ptr.setCategoryPath(CategoryPath("/" + vtableName)) ptr.setCategoryPath(CategoryPath("/vtable" + fnClass)) ptrAdded = dataManager.addDataType( ptr, DataTypeConflictHandler.REPLACE_HANDLER) structData.add(ptrAdded, ptrAdded.getLength(), fntoadd.toString(), "") else: print("Vtable reached the end.") break cAddr = cAddr.add(4) if structData != None: vtableCDataType = dataManager.addDataType( structData, DataTypeConflictHandler.REPLACE_HANDLER) vtableCDataTypePtr = PointerDataType(vtableCDataType) vtableDTtoAdd = dataManager.addDataType( vtableCDataTypePtr, DataTypeConflictHandler.REPLACE_HANDLER) print("Created " + vtableName) else: print("Skipped " + vtableName)
def generateVtableStruct(vtableSymbol): vtableAddr = vtableSymbol.getAddress() nameStartsAt = 5 while True: if vtableSymbol.getName()[nameStartsAt].isdigit(): nameStartsAt += 1 else: break vtableClassName = vtableSymbol.getName()[nameStartsAt:] vtableName = "" structData = None keepgoing = True #cAddr = vtableAddr.add(8) cAddr = vtableAddr #tmp = next(codeUnits) #tmp = next(codeUnits) antiFreeze = 0 while True: #print("Checking " + cAddr.toString()) fnToCheck = CUManager.getCodeUnitContaining(cAddr) #print(fnToCheck.getMnemonicString()) if fnToCheck != None and fnToCheck.getMnemonicString() == "addr": #print("Found start of vtable at") cAddr = cAddr.add(4) break if antiFreeze >= 50: print("Something has to have gone wrong...") return cAddr = cAddr.add(4) antiFreeze += 1 if "google" in vtableClassName and not doGoogle: print("Skipped vtable" + vtableClassName) return if "CryptoPP" in vtableClassName and not doFOSS: print("Skipped vtable" + vtableClassName) return while True: monitor.checkCanceled() fs = getAddress(mem.getInt(cAddr)) valpart = fs.toString() fntoadd = functionManager.getFunctionContaining(getAddress(valpart)) if fntoadd != None: #print("YES, this is an pointer") if vtableName == "": #vtableClassName = getClassName(fntoadd.toString()) vtableName = "vtable" + vtableClassName structData = StructureDataType(vtableName, 0) #print("Making vtable for " + vtableClassName) monitor.setMessage("Observe: Making vtable for " + vtableClassName) #print(fntoadd) if fntoadd != None: dt = FunctionDefinitionDataType( fntoadd, False ) #Second parameter is "Formality", I think this strips the "this" parameter, so lets not set this True #dt.setCategoryPath(CategoryPath("/" + vtableName)) fnClass = getClassName(fntoadd.toString()) dt.setCategoryPath(CategoryPath("/vtable" + fnClass)) dtAdded = dataManager.addDataType( dt, DataTypeConflictHandler.REPLACE_HANDLER) ptr = PointerDataType(dtAdded) #ptr.setCategoryPath(CategoryPath("/" + vtableName)) ptr.setCategoryPath(CategoryPath("/vtable" + fnClass)) ptrAdded = dataManager.addDataType( ptr, DataTypeConflictHandler.REPLACE_HANDLER) structData.add(ptrAdded, ptrAdded.getLength(), fntoadd.toString(), "") else: break cAddr = cAddr.add(4) if structData != None: vtableCDataType = dataManager.addDataType( structData, DataTypeConflictHandler.REPLACE_HANDLER) vtableCDataTypePtr = PointerDataType(vtableCDataType) vtableDTtoAdd = dataManager.addDataType( vtableCDataTypePtr, DataTypeConflictHandler.REPLACE_HANDLER) print("Created " + vtableName) else: print("Skipped " + vtableName)
typeManager = currentProgram.getDataTypeManager() func_manager = currentProgram.getFunctionManager() d = code_manager.getDataAt(vftableAddress) assert(d.isArray()) assert(d.getPrimarySymbol().getParentNamespace().getSymbol().getSymbolType()==SymbolType.CLASS) class_name = d.getPrimarySymbol().getParentNamespace().getName() vftable_classname = naming_prefix+class_name+"_vftable" l = [] typeManager.findDataTypes(vftable_classname,l) if l!=[]: print("Class "+vftable_classname+" already exists. Nothing is changed.") else: category = typeManager.createCategory(CategoryPath(categoryPathString)) vftable_type = StructureDataType(vftable_classname, 0) for i in range(d.getNumComponents()): comp = d.getComponent(i) assert(comp.isPointer()) func_addr = comp.getValue() func = func_manager.getFunctionAt(func_addr) assert(func!=None) func_name = func.getName() func_dt = FunctionDefinitionDataType("TGN_func") func_dt.setGenericCallingConvention(GenericCallingConvention.thiscall) func_dt.setReturnType(DWordDataType()) datatype = PointerDataType(func_dt) vftable_type.insert(i, datatype, datatype.getLength(), func_name, "TGN: Automatically created field") category.addDataType(vftable_type, DataTypeConflictHandler.REPLACE_HANDLER)
# Applies a structure to the current GLOBAL addres # DISCLAIMER: This is meant to be an example. You likely want to use this process in your own script #@category Tate.AutoScripts from ghidra.program.model.data import StructureDataType from ghidra.program.model.data import DWordDataType from ghidra.program.database.data import DataTypeManagerDB from ghidra.program.model.data import DataTypeConflictHandler debug = True applyGlobal = True #make a structure with size 4 struct = StructureDataType("scriptStruct", 0x4) if debug == True: print "struct before" print struct # inserts and expands the data type at arg1 offset # expands structure to size 8 struct.insertAtOffset(0x0, DWordDataType(), 4, "offset 0", None) struct.replaceAtOffset(4, DWordDataType(), 0, "offset 4", None) if debug == True: print "struct after" print struct #assign the structure to the address # when assigning to global, the struct will be auto inserted into the manager