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 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 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 defineIOExternalMethod(): dtm = currentProgram.getDataTypeManager() dt = dtm.findDataType(currentProgram.getName() + "/" + "IOExternalMethod") IOService = dtm.getDataType("/IOService") IOMethod_def = "uint IOService::IOMethod(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)" uint = dtm.getDataType("/uint") ulonglong = dtm.getDataType("/ulonglong") fdef = parseCSignature(IOMethod_def) st = StructureDataType("IOExternalMethod", 0) 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)
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 strToDataType(s): """ Converts a C-Style type like `uint` or `CTFPlayer *` to a Ghidra DataType """ indirection = 0 while s[-1] == '*': s = s[:-1] indirection += 1 s = s.rstrip() t = all_datatypes.get(s, all_datatypes['undefined1']) for i in range(0, indirection): t = PointerDataType(t) return t
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 createPointer(self, element): """ Convert CastXML XML element into a Ghidra PointerDataType. Args: element (ElementTree): XML element Returns (PointerDataType): Ghidra PointerDataType """ pointeeElement = self.getTypeInfoElementById(element.attrib['type']) dataType = self.getDataType(pointeeElement) if dataType == None: dataType = Undefined.getUndefinedDataType(1) print "Invalid DataType returned for PointerType: tag={0} id={1}".format( pointeeElement.tag, pointeeElement.attrib['id']) pointerLength = self.getDefaultPointerSize() if 'size' in element.attrib: pointerLength = int(element.attrib['size']) / 8 pointerType = PointerDataType(dataType, pointerLength) self.recordTypeForId(element.attrib['id'], pointerType) return pointerType
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)
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
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.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)
def get_pointer_type(): """ Get the correct pointer size for the current architecture. """ return PointerDataType(None, currentProgram.getDefaultPointerSize())
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)
0x02: "Local Absolute", 0x03: "Global Absolute", 0x04: "Local .text", 0x05: "Global .text", 0x08: "Local Data", 0x09: "Global Data", 0x10: "Local BSS", 0x11: "Global BSS", 0x20: "Local Common symbol", 0x21: "Global Common symbol", 0x40: "Local Symbols", 0x41: "Global Symbols" } # Init data type 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) # 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)
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)
elif bits <= 16: field_data_type = dataManager.getDataType("/ushort" if unsigned else "/short") field_size = 2 elif bits <= 32: field_data_type = dataManager.getDataType("/uint" if unsigned else "/int") field_size = 4 else: print("ERROR! integer has too many bits! ({})".format(bits)) ''' elif field_type == "float": # TODO: Might some floats not be 32bit? field_data_type = dataManager.getDataType("/float") field_size = 4 elif field_type == "string": # TODO: Is this just plain wrong? field_data_type = PointerDataType( dataManager.getDataType("/TerminatedCString")) field_size = 4 elif field_type == "array": print("SKIPPING array type for field {} of {}".format( field_name, class_name)) continue else: print("ERROR! unknown type ({})".format(field_type)) # Use the trail to build up the offset and field_name field_name = "" field_offset = offset for i in range(1, indentation): name, offset = trail[i] if name is not None: field_name = field_name + name + "_"
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)