Пример #1
0
def struct_decl(node: Cursor, bv: bn.BinaryView):
    struct = bn.Structure()
    struct.width = node.type.get_size()
    struct.alignment = node.type.get_align()
    if node.spelling:
        struct_name = node.spelling
    else:
        # A struct can be defined anonymously and assigned via a typedef, which means the struct_decl node itself
        # will have no spelling.
        # example: typedef struct {
        #                   DWORD Version;
        #                   GUID Guid;
        #                   SYSTEM_POWER_CONDITION PowerCondition;
        #                   DWORD DataLength;
        #                   BYTE Data[1];
        #                 } SET_POWER_SETTING_VALUE, *PSET_POWER_SETTING_VALUE;
        struct_name = node.type.spelling

    bn.log.log_debug(f'struct_decl: Processing struct {node.spelling}')

    # In order to avoid recursion problems with structs, always define the struct name as a binaryNinja forward decl
    bv.define_user_type(struct_name, bn.Type.structure_type(bn.Structure()))

    # check if struct is a forward declaration within the source code - if it is not a definition, then it is a forward
    # decl, and no fields should be defined at this point.
    if node.is_definition():
        for field in node.type.get_fields():
            bn.log.log_debug(f'struct_decl: Processing struct field {field.spelling}')

            if is_recursive_field(field, bv):
                forward_decl_struct = bn.Structure()
                forward_decl_struct_name = field.type.get_pointee().get_declaration().spelling
                bv.define_user_type(forward_decl_struct_name, bn.Type.structure_type(forward_decl_struct))
                t = bv.get_type_by_name(forward_decl_struct_name)
                struct.append(t, forward_decl_struct_name)
            else:
                var_type = bv.get_type_by_name(field.spelling)
                if not var_type:
                    # Need to define the field type
                    var_name, var_type = define_type(field.get_definition(), bv)
                struct.append(var_type, field.spelling)
            bn.log.log_debug(f'struct_decl: Successfully processed  struct field {field.spelling}')

    try:
        if node.kind == CursorKind.UNION_DECL:
            # set type to union
            struct.type = bn.StructureType.UnionStructureType

        bv.define_user_type(struct_name, bn.Type.structure_type(struct))
        bn.log.log_debug(f'struct_decl: Successfully processed struct {struct_name}')
        return struct_name, bn.Type.structure_type(struct)
    except Exception as e:
        bn.log.log_debug(f'struct_decl: Failed Processing struct {struct_name} with exception {e}')
def pre_define_types(bv: bn.BinaryView, library):
    for var_type, var_name in library.pre_load_definition.items():
        t, n = bv.parse_type_string(f'{var_type} {var_name}')
        bv.define_user_type(n, t)

    for forward_decl_struct in library.forward_declarations['struct']:
        struct = bn.Structure()
        bv.define_user_type(forward_decl_struct,
                            bn.Type.structure_type(bn.Structure()))
    for forward_decl_typedef in library.forward_declarations['typedef']:
        print(forward_decl_typedef)
        var_type, var_name = bv.parse_type_string(f'{forward_decl_typedef};')
        bv.define_user_type(var_name, var_type)
Пример #3
0
def define_anonymous_type(node: Cursor, bv: bn.BinaryView) -> bn.Type:
    # An anonymous type must be either a Struct\UNION\ENUM.
    # In order to simplify working with binaryNinja, an anonymized type is de-anonymized:
    # The name of the anonymous type is a hash of its location in the source file prepended by 'anon_'
    bn.log.log_debug(f'define_anonymous_type: Processing {node.type.spelling}')

    struct = bn.Structure()
    struct.width = node.type.get_size()
    struct.alignment = node.type.get_align()
    struct_name = 'anon_' + xxhash.xxh64_hexdigest(node.type.spelling)

    for field in node.type.get_fields():
        bn_field_type = bv.get_type_by_name(field.spelling)
        field_name = field.spelling
        if not bn_field_type:
            # Need to define the field type
            # if field.is_anonymous():
            #    field_name, bn_field_type = define_anonymous_type(field, bv)
            # else:
            field_name, bn_field_type = define_type(field.get_definition(), bv)
        bn.log.log_debug(f'define_anonymous_type: Appending field - {bn_field_type} {field_name}')
        struct.append(bn_field_type, field_name)

    # Check if the underlying struct is a union
    if node.type.kind == TypeKind.ELABORATED:
        if node.type.get_named_type().get_declaration().kind == CursorKind.UNION_DECL:
            # set type to union
            struct.type = bn.StructureType.UnionStructureType

    return struct_name, bn.Type.structure_type(struct)
Пример #4
0
 def test_Struct(self):
     """Struct produced different result"""
     inttype = binja.Type.int(4)
     struct = binja.Structure()
     struct.a = 1
     struct.insert(0, inttype)
     struct.append(inttype)
     struct.replace(0, inttype)
     struct.remove(1)
     retinfo = [str(i) for i in struct.members]
     retinfo += [struct.width]
     struct.width = 16
     retinfo += [struct.width]
     retinfo += [struct.alignment]
     struct.alignment = 8
     retinfo += [struct.alignment]
     retinfo += [struct.packed]
     struct.packed = 1
     retinfo += [struct.packed]
     retinfo += [struct.type]
     retinfo = [str(i) for i in retinfo]
     return retinfo
Пример #5
0
 def test_Struct(self):
     """Struct produced different result"""
     retinfo = []
     inttype = binja.Type.int(4)
     struct = binja.Structure()
     struct.a = 1
     struct.insert(0, inttype)
     struct.append(inttype)
     struct.replace(0, inttype)
     struct.remove(1)
     for i in struct.members:
         retinfo.append("Struct member: " + str(i))
     retinfo.append("Struct width: " + str(struct.width))
     struct.width = 16
     retinfo.append("Struct width after adjustment: " + str(struct.width))
     retinfo.append("Struct alignment: " + str(struct.alignment))
     struct.alignment = 8
     retinfo.append("Struct alignment after adjustment: " +
                    str(struct.alignment))
     retinfo.append("Struct packed: " + str(struct.packed))
     struct.packed = 1
     retinfo.append("Struct packed after adjustment: " + str(struct.packed))
     retinfo.append("Struct type: " + str(struct.type))
     return retinfo
Пример #6
0
    def _construct_binja_type(self,
                              ty: Type,
                              as_specifier: bool = False) -> bn.Type:
        assert (not isinstance(ty, str))
        if ty.uuid in self._s2b_types:
            if as_specifier and ty.name is not None:
                ntrc = bn.NamedTypeReferenceClass.UnknownNamedTypeClass
                if ty.composite_type is not None:
                    if ty.composite_type == CompositeType.CLASS_TYPE:
                        ntrc = bn.NamedTypeReferenceClass.ClassNamedTypeClass
                    elif ty.composite_type == CompositeType.STRUCT_TYPE:
                        ntrc = bn.NamedTypeReferenceClass.StructNamedTypeClass
                    elif ty.composite_type == CompositeType.UNION_TYPE:
                        ntrc = bn.NamedTypeReferenceClass.UnionNamedTypeClass
                    elif ty.composite_type == CompositeType.ENUM_TYPE:
                        ntrc = bn.NamedTypeReferenceClass.EnumNamedTypeClass
                binja_type = bn.Type.named_type(
                    bn.NamedTypeReference(name=ty.name,
                                          type_id=self._generate_typeid(
                                              ty.name),
                                          type_class=ntrc))
            else:
                return self._s2b_types[ty.uuid]

        bv = self._binary_view
        if ty.scalar_type:
            if ty.scalar_type == ScalarType.BASE_TYPE:
                if ty.name in self._base_types:
                    binja_type = self._base_types[ty.name]
                else:
                    try:
                        # If this is a parseable type, do that.
                        binja_type, _ = bv.parse_type_string(ty.name)
                        self._base_types[ty.name] = binja_type
                        self._builtin_types.add(ty.name)
                    except:
                        # Otherwise, create a named type reference.
                        binja_type = bn.Type.named_type(
                            bn.NamedTypeReference(
                                name=ty.name,
                                type_id=self._generate_typeid(ty.name)))
                        self._base_types[ty.name] = binja_type
            elif ty.scalar_type == ScalarType.POINTER_TYPE:
                target_type = self._construct_binja_type(
                    ty.element, as_specifier=as_specifier)
                binja_type = bn.Type.pointer(
                    bv.arch,
                    target_type,
                    ref_type=bn.ReferenceType.PointerReferenceType)
            elif ty.scalar_type == ScalarType.REFERENCE_TYPE:
                target_type = self._construct_binja_type(
                    ty.element, as_specifier=as_specifier)
                binja_type = bn.Type.pointer(
                    bv.arch,
                    target_type,
                    ref_type=bn.ReferenceType.ReferenceReferenceType)
            elif ty.scalar_type == ScalarType.RVALUE_REFERENCE_TYPE:
                target_type = self._construct_binja_type(
                    ty.element, as_specifier=as_specifier)
                binja_type = bn.Type.pointer(
                    bv.arch,
                    target_type,
                    ref_type=bn.ReferenceType.RValueReferenceType)
            elif ty.scalar_type == ScalarType.ARRAY_TYPE:
                element_type = self._construct_binja_type(
                    ty.element, as_specifier=as_specifier)
                count = 0 if ty.array_count is None else ty.array_count
                if count > 65535:
                    count = 0
                binja_type = bn.Type.array(element_type, count)
        elif ty.composite_type:
            if as_specifier and ty.name is not None:
                ntrc = bn.NamedTypeReferenceClass.UnknownNamedTypeClass
                if ty.composite_type == CompositeType.CLASS_TYPE:
                    ntrc = bn.NamedTypeReferenceClass.ClassNamedTypeClass
                elif ty.composite_type == CompositeType.STRUCT_TYPE:
                    ntrc = bn.NamedTypeReferenceClass.StructNamedTypeClass
                elif ty.composite_type == CompositeType.UNION_TYPE:
                    ntrc = bn.NamedTypeReferenceClass.UnionNamedTypeClass
                elif ty.composite_type == CompositeType.ENUM_TYPE:
                    ntrc = bn.NamedTypeReferenceClass.EnumNamedTypeClass
                binja_type = bn.Type.named_type(
                    bn.NamedTypeReference(name=ty.name,
                                          type_id=self._generate_typeid(
                                              ty.name),
                                          type_class=ntrc))
            else:
                if ty.composite_type in [
                        CompositeType.CLASS_TYPE, CompositeType.STRUCT_TYPE
                ]:
                    struct = bn.Structure()
                    struct.type = bn.StructureType.StructStructureType if ty.composite_type == CompositeType.STRUCT_TYPE else bn.StructureType.ClassStructureType
                    if ty.byte_size is not None:
                        struct.width = ty.byte_size
                    for m in ty.members:
                        member_type = self._construct_binja_type(
                            m.element, as_specifier=True)
                        member_name = m.name if m.name is not None else ''
                        if m.offset is not None:
                            struct.insert(m.offset, member_type, member_name)
                    binja_type = bn.Type.structure_type(struct)
                elif ty.composite_type == CompositeType.UNION_TYPE:
                    union = bn.Structure()
                    union.type = bn.StructureType.UnionStructureType
                    if ty.byte_size is not None:
                        union.width = ty.byte_size
                    for m in ty.members:
                        member_type = self._construct_binja_type(
                            m.element, as_specifier=as_specifier)
                        member_name = m.name if m.name is not None else ''
                        if m.offset is not None:
                            union.insert(m.offset, member_type, member_name)
                    binja_type = bn.Type.structure_type(union)
                elif ty.composite_type == CompositeType.ENUM_TYPE:
                    e = bn.Enumeration()
                    for m in ty.members:
                        e.append(m.name, m.offset)
                    binja_type = bn.Type.enumeration_type(
                        bv.arch, e, ty.byte_size)
                elif ty.composite_type == CompositeType.FUNCTION_TYPE:
                    has_variable_args = False
                    ret = self._construct_binja_type(ty.element,
                                                     as_specifier=True)
                    params = []
                    for param in ty.members:
                        if param.element == Type.variadic():
                            has_variable_args = True
                        else:
                            params.append(
                                self._construct_binja_type(param.element,
                                                           as_specifier=True))
                    binja_type = bn.Type.function(
                        ret, params, variable_arguments=has_variable_args)
                elif ty.composite_type == CompositeType.PTR_TO_MEMBER_TYPE:
                    binja_type = self._construct_binja_type(ty.members[1],
                                                            as_specifier=True)
        elif ty.name is not None:
            ntrc = bn.NamedTypeReferenceClass.TypedefNamedTypeClass
            binja_type = bn.Type.named_type(
                bn.NamedTypeReference(name=ty.name,
                                      type_id=self._generate_typeid(ty.name),
                                      type_class=ntrc))
        else:
            if ty.element is None:
                print(ty.__dict__)
            assert (ty.element is not None)
            binja_type = self._construct_binja_type(
                ty.element, as_specifier=as_specifier).mutable_copy()
            if ty.is_constant:
                binja_type.const = True
            if ty.is_volatile:
                binja_type.volatile = True

        return binja_type