Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
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)
  
Ejemplo n.º 3
0
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)