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
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)
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)