Example #1
0
	def update_memory_view(self):
		if self.adapter == None:
			raise Exception('missing adapter')
		if self.memory_view == None:
			raise Exception('missing memory_view')

		addr_regs = {}
		reg_addrs = {}

		for reg in self.adapter.reg_list():
			addr = self.adapter.reg_read(reg)
			reg_symbol_name = '$' + reg

			if addr not in addr_regs.keys():
				addr_regs[addr] = [reg_symbol_name]
			else:
				addr_regs[addr].append(reg_symbol_name)
			reg_addrs[reg] = addr

		for symbol in self.old_symbols:
			# Symbols are immutable so just destroy the old one
			self.memory_view.undefine_auto_symbol(symbol)

		for dv in self.old_dvs:
			self.memory_view.undefine_data_var(dv)

		self.old_symbols = []
		self.old_dvs = set()
		new_dvs = set()

		for (reg, addr) in reg_addrs.items():
			symbol_name = '$' + reg
			self.memory_view.define_auto_symbol(Symbol(SymbolType.ExternalSymbol, addr, symbol_name, namespace=symbol_name))
			self.old_symbols.append(self.memory_view.get_symbol_by_raw_name(symbol_name, namespace=symbol_name))
			new_dvs.add(addr)

		for new_dv in new_dvs:
			self.memory_view.define_data_var(new_dv, Type.int(8))
			self.old_dvs.add(new_dv)

		# Special struct for stack frame
		if self.bv.arch.name == 'x86_64':
			width = reg_addrs['rbp'] - reg_addrs['rsp'] + self.bv.arch.address_size
			if width > 0:
				if width > 0x1000:
					width = 0x1000
				struct = Structure()
				struct.type = StructureType.StructStructureType
				struct.width = width
				for i in range(0, width, self.bv.arch.address_size):
					var_name = "var_{:x}".format(width - i)
					struct.insert(i, Type.pointer(self.bv.arch, Type.void()), var_name)
				self.memory_view.define_data_var(reg_addrs['rsp'], Type.structure_type(struct))
				self.memory_view.define_auto_symbol(Symbol(SymbolType.ExternalSymbol, reg_addrs['rsp'], "$stack_frame", raw_name="$stack_frame"))

				self.old_symbols.append(self.memory_view.get_symbol_by_raw_name("$stack_frame"))
				self.old_dvs.add(reg_addrs['rsp'])
		else:
			raise NotImplementedError('only x86_64 so far')
Example #2
0
    def update_memory_view(self):
        if self.adapter == None:
            raise Exception('missing adapter')
        if self.memory_view == None:
            raise Exception('missing memory_view')

        for symbol in self.old_symbols:
            # Symbols are immutable so just destroy the old one
            self.memory_view.undefine_auto_symbol(symbol)

        for dv in self.old_dvs:
            self.memory_view.undefine_data_var(dv)

        self.old_symbols = []
        self.old_dvs = set()
        new_dvs = set()

        for (reg, addr) in self.registers:
            bits = self.registers.bits(reg)
            symbol_name = '$' + reg
            self.memory_view.define_auto_symbol(
                Symbol(SymbolType.ExternalSymbol,
                       addr,
                       symbol_name,
                       namespace=symbol_name))
            self.old_symbols.append(
                self.memory_view.get_symbol_by_raw_name(symbol_name,
                                                        namespace=symbol_name))
            self.memory_view.define_data_var(addr,
                                             Type.int(bits // 8, sign=False))
            self.old_dvs.add(addr)

        # Special struct for stack frame
        if self.remote_arch.name == 'x86_64':
            width = self.registers['rbp'] - self.registers[
                'rsp'] + self.remote_arch.address_size
            if width > 0:
                if width > 0x1000:
                    width = 0x1000
                struct = Structure()
                struct.type = StructureType.StructStructureType
                struct.width = width
                for i in range(0, width, self.remote_arch.address_size):
                    var_name = "var_{:x}".format(width - i)
                    struct.insert(i, Type.pointer(self.remote_arch,
                                                  Type.void()), var_name)
                self.memory_view.define_data_var(self.registers['rsp'],
                                                 Type.structure_type(struct))
                self.memory_view.define_auto_symbol(
                    Symbol(SymbolType.ExternalSymbol,
                           self.registers['rsp'],
                           "$stack_frame",
                           raw_name="$stack_frame"))

                self.old_symbols.append(
                    self.memory_view.get_symbol_by_raw_name("$stack_frame"))
                self.old_dvs.add(self.registers['rsp'])
        else:
            pass
Example #3
0
    def _apply_header_types(self, image_base: int, num_of_sections: int):
        """Import and apply the TE header and section header types

        :param image_base: Virtual base address
        :param num_of_sections: Number of sections (for header region size calculation)
        """

        t, name = self.parse_type_string("""struct {
             uint32_t VirtualAddress;
             uint32_t Size;
            } EFI_IMAGE_DATA_DIRECTORY;""")

        self.define_user_type(name, t)
        header, name = self.parse_type_string("""struct {
             char Signature[2];
             uint16_t Machine;
             uint8_t NumberOfSections;
             uint8_t Subsystem;
             uint16_t StrippedSize;
             uint32_t AddressOfEntryPoint;
             uint32_t BaseOfCode;
             uint64_t ImageBase;
             EFI_IMAGE_DATA_DIRECTORY DataDirectory[2];
            } EFI_TE_IMAGE_HEADER;""")
        self.define_user_type(name, header)
        section_header, name = self.parse_type_string("""struct {
                char Name[8];
                union {
                    uint32_t  PhysicalAddress;
                    uint32_t  VirtualSize;
                } Misc;
                uint32_t  VirtualAddress;
                uint32_t  SizeOfRawData;
                uint32_t  PointerToRawData;
                uint32_t  PointerToRelocations;
                uint32_t  PointerToLinenumbers;
                uint16_t  NumberOfRelocations;
                uint16_t  NumberOfLinenumbers;
                uint32_t  Characteristics;
            } EFI_IMAGE_SECTION_HEADER;""")
        self.define_user_type(name, section_header)
        self.define_user_data_var(image_base, header)
        self.define_user_symbol(
            Symbol(SymbolType.DataSymbol, image_base, 'gTEImageHdr'))

        for i in range(TERSE_IMAGE_HEADER_SIZE,
                       num_of_sections * (SECTION_HEADER_SIZE + 1),
                       SECTION_HEADER_SIZE):
            self.define_user_data_var(image_base + i, section_header)
            self.define_user_symbol(
                Symbol(SymbolType.DataSymbol, image_base + i,
                       'gSectionHdr{}'.format(i - 40)))
Example #4
0
 def create_functions(self):
     for idx in range(4, 252, 4):
         addr = struct.unpack('>I', self.raw[idx:idx + 4])[0]
         self.add_function(addr)
         if idx == 4:
             self.add_entry_point(addr)
             self.define_auto_symbol(
                 Symbol(SymbolType.FunctionSymbol, addr, "_start"))
         elif idx == 112:
             self.define_auto_symbol(
                 Symbol(SymbolType.FunctionSymbol, addr, "hblank"))
         elif idx == 120:
             self.define_auto_symbol(
                 Symbol(SymbolType.FunctionSymbol, addr, "vblank"))
Example #5
0
    def init(self):
        data = self.parent_view

        ram_size = Settings().get_integer('arch.m16c.ramSize') * 1024

        seg_rw_ = (SegmentFlag.SegmentReadable | SegmentFlag.SegmentWritable)
        seg_r_x = (SegmentFlag.SegmentReadable | SegmentFlag.SegmentExecutable)
        seg_code = SegmentFlag.SegmentContainsCode
        seg_data = SegmentFlag.SegmentContainsData
        self.add_auto_segment(0x00000, 0x00400, 0, 0, seg_rw_)
        self.add_auto_segment(0x00400, ram_size, 0, 0, seg_rw_ | seg_data)
        self.add_auto_segment(0x100000 - len(data), len(data), data.start,
                              len(data), seg_r_x | seg_code | seg_data)

        sec_default = SectionSemantics.DefaultSectionSemantics
        sec_ro_code = SectionSemantics.ReadOnlyCodeSectionSemantics
        sec_ro_data = SectionSemantics.ReadOnlyDataSectionSemantics
        sec_rw_data = SectionSemantics.ReadWriteDataSectionSemantics
        self.add_auto_section('.sfr', 0x00000, 0x00400, sec_default)
        self.add_auto_section('.data', 0x00400, ram_size, sec_rw_data)
        self.add_auto_section('.text', 0x100000 - len(data), len(data),
                              sec_ro_code)
        self.add_auto_section('.rodata', 0x100000 - len(data), len(data),
                              sec_ro_data)

        for vector_addr, vector_name in zip(range(0xFFFDC, 0x100000, 4),
                                            self.vector_names):
            vector, = struct.unpack("<L", self.read(vector_addr, 4))
            symbol = Symbol(SymbolType.FunctionSymbol, vector & 0xFFFFF,
                            vector_name)
            self.define_auto_symbol(symbol)

        return True
Example #6
0
def create_vtable(view, vtable_name, vtable_address, max_funcs = 64):
    pointer_t = BinjaStruct.Pointer(view)

    funcs = list()

    for i in range(max_funcs):
        func_pointer_address = vtable_address + (i * view.address_size)
        func_address, _ = pointer_t.read(view, func_pointer_address)

        if func_address is None:
            break

        if not view.is_offset_executable(func_address):
            break

        func = view.get_function_at(func_pointer_address)

        if func is None:
            if i and view.get_code_refs(func_pointer_address, view.address_size):
                break

        funcs.append(func_address)

    if funcs:
        view.define_user_symbol(Symbol(SymbolType.DataSymbol, vtable_address, vtable_name))
        view.define_user_data_var(vtable_address, Type.array(Type.pointer(view.arch, Type.void(), const = True), len(funcs)))

    return funcs
Example #7
0
    def __create_class_name_type(bv: BinaryView, vmt: DelphiVMT, out_struct: types.Structure) -> bool:
        vmt_offsets = vmt.vmt_offsets

        if not vmt.seek_to_vmt_offset(vmt_offsets.cVmtClassName):
            return False

        class_name_ptr = vmt.read_ptr()

        if class_name_ptr is None:
            return False

        if not vmt.seek_to_code(class_name_ptr):
            return False

        class_name_len = vmt.read8()

        if class_name_len is None:
            return False

        class_name_struct = types.Structure()
        class_name_struct.append(Type.int(1, False), 'length')
        class_name_struct.append(Type.array(Type.char(), class_name_len), 'value')
        struct_type = Type.structure_type(class_name_struct)

        bv.define_user_data_var(class_name_ptr, struct_type)
        out_struct.append(Type.pointer(bv.arch, struct_type), 'cVmtClassName')

        # Create Symbole for class name
        class_name_sym = Symbol(SymbolType.DataSymbol, class_name_ptr, f'{vmt.class_name}Name')
        bv.define_user_symbol(class_name_sym)

        return True
Example #8
0
def _define_classes(view: BinaryView, class_t: Type):
    __objc_data = view.sections.get('__objc_data')

    if __objc_data is None:
        raise KeyError('This binary has no __objc_data section')

    for addr in range(__objc_data.start, __objc_data.end, class_t.width):
        current_class = Class.from_address(addr, view)

        log_debug(f"Created {current_class}")

    __objc_classrefs = view.sections.get('__objc_classrefs')

    if __objc_classrefs is None:
        raise KeyError('This binary has no __objc_classrefs section')

    for addr in range(__objc_classrefs.start, __objc_classrefs.end,
                      view.address_size):
        view.define_user_data_var(addr, Type.pointer(view.arch, class_t))

        class_addr = int.from_bytes(
            view.read(addr, view.address_size),
            "little" if view.endianness is Endianness.LittleEndian else "big")

        class_ = view.session_data['ClassList'].get(
            class_addr) if class_addr else None

        if class_ is not None:
            log_debug(f"{addr:x} points to {class_!r}")
            view.define_user_symbol(
                Symbol(SymbolType.DataSymbol, addr,
                       f"_OBJC_CLASS_$_{class_.vtable.name}@GOT"))
Example #9
0
    def init(self):
        self.arch = Architecture['EVM']
        self.platform = Architecture['EVM'].standalone_platform
        self.max_function_size_for_analysis = 0

        file_size = len(self.raw)

        # Find swarm hashes and make them data
        evm_bytes = self.raw.read(0, file_size)

        # code is everything that isn't a swarm hash
        code = IntervalSet([Interval(0, file_size)])

        log_debug('Finding swarm hashes')
        swarm_hashes = self.find_swarm_hashes(evm_bytes)
        for start, sz in swarm_hashes:
            self.add_auto_segment(
                start, sz, start, sz,
                (SegmentFlag.SegmentContainsData
                 | SegmentFlag.SegmentDenyExecute | SegmentFlag.SegmentReadable
                 | SegmentFlag.SegmentDenyWrite))

            code -= IntervalSet([Interval(start, start + sz)])

        for interval in code:
            if isinstance(interval, int):
                continue
            self.add_auto_segment(
                interval.lower_bound, interval.upper_bound,
                interval.lower_bound, interval.upper_bound,
                (SegmentFlag.SegmentReadable | SegmentFlag.SegmentExecutable))

        log_debug('Building CFG with evm_cfg_builder')
        cfg = CFG(evm_bytes, remove_metadata=False)
        log_debug('Finished building CFG with evm_cfg_builder')
        Function.set_default_session_data('cfg', cfg)

        log_debug("registering VsaNotification")
        self.register_notification(VsaNotification())

        log_debug("specifiying entry point and functions")
        self.add_entry_point(0)

        for function in cfg.functions:
            function_start = (function._start_addr +
                              1 if function._start_addr != 0 else 0)

            self.define_auto_symbol(
                Symbol(SymbolType.FunctionSymbol, function_start,
                       function.name))

            self.add_function(function_start)

        # disable linear sweep
        Settings().set_bool('analysis.linearSweep.autorun',
                            False,
                            view=self,
                            scope=SettingsScope.SettingsUserScope)

        return True
Example #10
0
    def from_address(cls, address: int, class_name: str, view: BinaryView):
        if address == 0:
            return None

        from_bytes = get_from_bytes(view)

        ivar_t_type = view.types['ivar_t']
        ivar_t = Type.named_type_from_type(
            'ivar_t', ivar_t_type
        )

        members = get_structure_members(address, ivar_t_type, view)
        member_dict = {m.name: m for m in ivar_t_type.structure.members}

        # x64 uses uint64_t for offset, but everything else
        # uses uint32_t
        ivar_offset_type = (
            member_dict['offset'].type.target
            if view.arch != Architecture['x86_64']
            else Type.int(8, False)
        )
        ivar_offset_type.const = True

        if view.get_data_var_at(address) is None:
            view.define_user_data_var(address, ivar_t)

        if members['name'] != 0:
            name_string = view.get_ascii_string_at(members['name'], 1)
            if name_string is not None:
                members['name'] = name_string.value
        else:
            members['name'] = ''

        if members['type']:
            type_string = view.get_ascii_string_at(members['type'], 1).value
            members['type'] = _lookup_type(type_string, view)

        if not members['type']:
            members['type'] = Type.pointer(view.arch, Type.void())

        if members['offset']:
            view.define_user_data_var(members['offset'], ivar_offset_type)
            view.define_user_symbol(
                Symbol(
                    SymbolType.DataSymbol,
                    members['offset'],
                    f'{members["name"]}_offset',
                    namespace=class_name
                )
            )
            members['offset'] = from_bytes(
                view.read(members['offset'],
                          member_dict['offset'].type.target.width)
            )
        else:
            members['offset'] = None

        return cls(address, **members)
Example #11
0
    def _set_if_uefi_core_type(self, instr: HighLevelILInstruction):
        """Using HLIL, scrutinize the instruction to determine if it's a move of a local variable to a global variable.
        If it is, check if the source operand type is a UEFI core type and apply the type to the destination global
        variable.

        :param instr: High level IL instruction object
        """

        if instr.operation != HighLevelILOperation.HLIL_ASSIGN:
            return

        if instr.dest.operation != HighLevelILOperation.HLIL_DEREF:
            return

        if instr.dest.src.operation != HighLevelILOperation.HLIL_CONST_PTR:
            return

        if instr.src.operation != HighLevelILOperation.HLIL_VAR:
            return

        _type = instr.src.var.type
        if len(_type.tokens) == 1 and str(_type.tokens[0]) == 'EFI_HANDLE':
            self.bv.define_user_symbol(
                Symbol(SymbolType.DataSymbol, instr.dest.src.constant,
                       'gImageHandle'))
        elif len(_type.tokens) > 2 and str(
                _type.tokens[2]) == 'EFI_BOOT_SERVICES':
            self.bv.define_user_symbol(
                Symbol(SymbolType.DataSymbol, instr.dest.src.constant, 'gBS'))
        elif len(_type.tokens) > 2 and str(
                _type.tokens[2]) == 'EFI_RUNTIME_SERVICES':
            self.bv.define_user_symbol(
                Symbol(SymbolType.DataSymbol, instr.dest.src.constant, 'gRS'))
        elif len(_type.tokens) > 2 and str(
                _type.tokens[2]) == 'EFI_SYSTEM_TABLE':
            self.bv.define_user_symbol(
                Symbol(SymbolType.DataSymbol, instr.dest.src.constant, 'gST'))
        else:
            return

        self.bv.define_user_data_var(instr.dest.src.constant,
                                     instr.src.var.type)
        print(
            f'Found global assignment - offset:0x{hex(instr.dest.src.constant)} type:{instr.src.var.type}'
        )
Example #12
0
    def import_names(self, names, sections):
        """
        Import names into BN database

        :param names: Dict containing symbol info
        :param sections: Dict containing section info
        """

        for addr, name in names.items():
            addr = self.adjust_addr(sections, int(addr))
            if addr is None:
                continue

            if self.bv.get_function_at(addr):
                self.bv.define_user_symbol(
                    Symbol(SymbolType.FunctionSymbol, addr, name))
            else:
                self.bv.define_user_symbol(
                    Symbol(SymbolType.DataSymbol, addr, name))
Example #13
0
 def apply_data_symbols(self, symbols: list, kallsyms_text_start: int,
                        binary_text_start: int):
     """Creates data variables and applies symbols
     """
     for typ in ['d', 'D']:
         for name, addr in symbols[typ].items():
             addr = adjust_addr(binary_text_start, kallsyms_text_start,
                                addr)
             if name is not None:
                 self.view.define_user_symbol(
                     Symbol(SymbolType.DataSymbol, addr, name))
Example #14
0
def _import_symbols_from_json(bv, symbols, symbol_type, emit_status=None):
    changed = False
    for d in symbols:
        addr = int(d['addr'], 16)
        name = d['name']
        existing = bv.get_symbol_at(addr)
        if existing is not None:
            if name == existing.name:
                continue
            else:
                bv.define_user_symbol(Symbol(symbol_type, addr, name))
                changed = True
                if emit_status:
                    emit_status(f'rename {existing.name} => {name}')
        else:
            bv.define_user_symbol(Symbol(symbol_type, addr, name))
            changed = True
            if emit_status:
                emit_status(f'name {existing.name}')
    return changed
Example #15
0
def define_vtable(bv, address, end):
    # Name and define the vtable tree
    bv.set_comment_at(address, "auto defined vTable")  # good to know
    bv.define_user_data_var(address, types.Type.int(
        bv.arch.address_size))  # set to DWORD/QWORD
    bv.define_user_symbol(
        Symbol(SymbolType.DataSymbol, address,
               "vtable_" + str(hex(address))[2:] + "_0"))  # give name

    # get children
    for j in range(address + bv.arch.address_size, end, bv.arch.address_size):
        if is_valid_child(bv, j):
            #print("Found vtable_" + str(hex(j))[2:] + "_" + str(hex(j-address))[2:] + " at " + str(hex(j)))
            bv.define_user_data_var(j, types.Type.int(
                bv.arch.address_size))  # set to DWORD/QWORD
            bv.define_user_symbol(
                Symbol(
                    SymbolType.DataSymbol, j, "vtable_" + str(hex(j))[2:] +
                    "_" + str(hex(j - address))[2:]))  # give name
        else:
            break
Example #16
0
    def from_address(cls, address: int, view: BinaryView) -> Class:
        if address == 0:
            return None
        elif address in view.session_data['ClassList']:
            return view.session_data['ClassList'][address]
        else:
            new_class = cls(address, view, None, None, None, {}, {})
            view.session_data['ClassList'][address] = new_class

        from_bytes = get_from_bytes(view)

        members = get_structure_members(address,
                                        view.get_type_by_name('class_t'), view)

        isa = Class.from_address(members['isa'], view)
        new_class.isa = isa

        superclass = Class.from_address(members['superclass'], view)
        new_class.superclass = superclass

        vtable = ClassRO.from_address(members['vtable'], view,
                                      new_class.is_meta)
        new_class.vtable = vtable

        class_t = Type.named_type_from_type('class_t',
                                            view.get_type_by_name('class_t'))

        view.define_user_data_var(address, class_t)

        if not new_class.is_meta:
            view.session_data['ClassNames'][vtable.name] = new_class
        else:
            view.session_data['ClassNames'][f"{vtable.name}_meta"] = new_class

        if not new_class.is_meta:
            new_class.define_type()
            symbol_name = f'_OBJC_CLASS_$_{vtable.name}'
        else:
            symbol_name = f'_OBJC_METACLASS_$_{vtable.name}'

        view.define_user_symbol(
            Symbol(SymbolType.DataSymbol, address, symbol_name))

        if vtable and vtable.baseMethods is not None:
            new_class._methods = vtable.baseMethods.methods

        if vtable and vtable.baseProtocols is not None:
            new_class._protocols = vtable.baseProtocols.protocols

        return new_class
Example #17
0
        def run(self):
            binary = pefile.PE(self.binary.name)

            names = dict()
            for entry in binary.DIRECTORY_ENTRY_IMPORT:
                for imp in entry.imports:
                    names[imp.address] = "{}!{}".format(
                        entry.dll[:-4], imp.name)
            for symbol in self.bv.get_symbols_of_type(
                    SymbolType.ImportAddressSymbol):
                if "Ordinal_" in symbol.name and symbol.address in names:
                    bv.define_user_symbol(
                        Symbol(symbol.type, symbol.address,
                               names[symbol.address]))
Example #18
0
    def from_address(cls,
                     address: int,
                     self_type: str,
                     view: BinaryView,
                     is_class=False):
        if address == 0:
            return None

        if self_type not in view.types:
            view.define_user_type(self_type, Type.structure_type(Structure()))

        method_t_type = view.get_type_by_name('method_t')
        method_t = Type.named_type_from_type('method_t', method_t_type)

        if view.get_data_var_at(address) is None:
            view.define_user_data_var(address, method_t)

        members = get_structure_members(address, method_t_type, view)

        members['name'] = (view.get_ascii_string_at(members['name'], 1).value
                           if members['name'] else '')

        members['types'] = parse_function_type(
            view.get_ascii_string_at(members['types'], 1).value
            if members['types'] else '', self_type, view, is_class)

        members['imp'] = view.get_function_at(members['imp'])

        if members['imp'] is not None:
            if not is_class:
                method_name = f'-[{self_type} {members["name"]}]'
            else:
                method_name = f'+[{self_type} {members["name"]}]'

            if view.symbols.get(method_name):
                namespace = f'{members["imp"].start}'
            else:
                namespace = None

            view.define_user_symbol(
                Symbol(SymbolType.FunctionSymbol,
                       members['imp'].start,
                       method_name,
                       namespace=namespace))

            if members['types'] is not None:
                members['imp'].function_type = members['types']

        return cls(address, **members)
Example #19
0
def rename_caller(callee: Function, caller: Function, parami: int):
    i: MediumLevelILInstruction
    for i in filter(iscall, caller.mlil.instructions):
        if i.operands[1].constant == callee.start:
            i = i.operands[2][parami]
            if i.operation == mlilop.MLIL_CONST_PTR:
                name: str = caller.view.get_string_at(i.constant).value.split('(', 1)[0]
                caller.view.define_auto_symbol(Symbol(
                    caller.symbol.type,
                    caller.symbol.address,
                    short_name=name
                ))
                # just use the first one
                # a few wrong ones are fine imo
                break
Example #20
0
    def _add_vmt_methods(bv: BinaryView, vmt: DelphiVMT, out_struct: types.Structure) -> bool:
        offset_ptr_size = vmt.offset_ptr_size

        if not vmt.seek_to_vmt_offset(vmt.vmt_offsets.cVmtParent + offset_ptr_size):
            return False

        for _ in range(len(vmt.virtual_methods)):
            value = vmt.read_ptr()

            if value == 0:
                continue

            if value not in vmt.virtual_methods:
                prev_offset = vmt.br_offset - offset_ptr_size
                raise RuntimeError(
                    f'Invalid method address detected at 0x{prev_offset:08x} ({vmt.class_name})')

            # Create function if not exists
            if bv.get_function_at(value) is None:
                bv.create_user_function(value)

            function = bv.get_function_at(value)

            # Set method name if not already set
            function_name = function.name
            method_name = vmt.virtual_methods[value]

            if function_name.startswith('sub_'):
                bv.define_user_symbol(Symbol(
                    SymbolType.FunctionSymbol,
                    value,
                    method_name
                ))

            # Add field to structure
            field_type = Type.pointer(
                bv.arch,
                Type.function(
                    function.return_type,
                    [(Type.void() if x.type is None else x.type) for x in function.parameter_vars],
                    function.calling_convention
                )
            )

            field_name = method_name.split('.')[-1]
            out_struct.append(field_type, field_name)

        return True
Example #21
0
    def init(self):
        self.arch = Architecture['EVM']
        self.platform = Architecture['EVM'].standalone_platform
        self.add_entry_point(0)

        file_size = len(self.raw)

        # Find swarm hashes and make them data
        bytes = self.raw.read(0, file_size)

        # code is everything that isn't a swarm hash
        code = IntervalSet([Interval(0, file_size)])

        swarm_hashes = self.find_swarm_hashes(bytes)
        for start, sz in swarm_hashes:
            self.add_auto_segment(
                start - len(EVM_HEADER), sz, start, sz,
                SegmentFlag.SegmentContainsData
                | SegmentFlag.SegmentDenyExecute | SegmentFlag.SegmentReadable
                | SegmentFlag.SegmentDenyWrite)

            code -= IntervalSet([Interval(start, start + sz)])

        print "Code Segments: {}".format(code)

        for interval in code:
            self.add_auto_segment(
                interval.lower_bound, interval.upper_bound - len(EVM_HEADER),
                len(EVM_HEADER), interval.upper_bound,
                (SegmentFlag.SegmentReadable | SegmentFlag.SegmentExecutable))

        self.define_auto_symbol(
            Symbol(SymbolType.FunctionSymbol, 0, '_dispatcher'))

        invalidJumpCallbackNotification = InvalidJumpCallback()
        self.register_notification(invalidJumpCallbackNotification)

        dispatcherCallbackNotification = DispatcherCallback()
        self.register_notification(dispatcherCallbackNotification)

        dynamicJumpCallbackNotification = DynamicJumpCallback()
        self.register_notification(dynamicJumpCallbackNotification)

        # disable linear sweep
        self.store_metadata("ephemeral",
                            {"binaryninja.analysis.autorunLinearSweep": False})

        return True
Example #22
0
 def _explore_ins(self, bb):
     addr = bb.start
     for ins in bb.__iter__():
         details, size = ins
         if str(details[0]).startswith('PUSH'):
             operand = details[1]
             op_text = operand.text
             op_value = operand.value
             if op_text in knownHashes:
                 txt = knownHashes[op_text]
                 self.func.view.define_user_symbol(
                     Symbol(SymbolType.ImportedFunctionSymbol, op_value,
                            '{} -> {}'.format(op_text, txt)))
                 self.func.set_int_display_type(
                     addr, op_value, 0,
                     IntegerDisplayType.PointerDisplayType)
                 self.hashes_found += 1
         addr += size
Example #23
0
    def create_vmt_struct(bv: BinaryView, vmt: DelphiVMT) -> bool:
        if not vmt.is_valid:
            return False

        vmt_struct = types.Structure()

        if not BNHelpers._add_vmt_fields(bv, vmt, vmt_struct):
            return False

        if not BNHelpers._add_vmt_methods(bv, vmt, vmt_struct):
            return False

        struct_type = Type.structure_type(vmt_struct)
        bv.define_user_data_var(vmt.start, struct_type)
        # bv.define_user_type(f'vmt{vmt.class_name}', struct_type)

        # Create Symbole for VMT
        vmt_sym = Symbol(SymbolType.DataSymbol, vmt.start, f'vmt{vmt.class_name}')
        bv.define_user_symbol(vmt_sym)
        return True
Example #24
0
    def _apply_guid_name_if_data(self, name: str, address: int):
        """Check if there is a function at the address. If not, then apply the EFI_GUID type and name it

        :param name: Name/symbol to apply to the GUID
        :param address: Address of the GUID
        """

        print(
            f'Found {name} at 0x{hex(address)} ({uuid.UUID(bytes_le=self.guids[name])})'
        )

        # Just to avoid a unlikely false positive and screwing up disassembly
        if self.bv.get_functions_at(address) != []:
            print(
                f'There is code at {address}, not applying GUID type and name')
            return

        self.bv.define_user_symbol(
            Symbol(SymbolType.DataSymbol, address, 'g' + name))
        t = self.bv.parse_type_string("EFI_GUID")
        self.bv.define_user_data_var(address, t[0])
Example #25
0
    def init(self):
        self.arch = Architecture['EVM']
        self.platform = Architecture['EVM'].standalone_platform
        self.add_entry_point(0)

        file_size = len(self.raw)
        self.add_auto_segment(
            0, file_size - len(EVM_HEADER), len(EVM_HEADER), file_size,
            (SegmentFlag.SegmentReadable | SegmentFlag.SegmentExecutable))

        self.define_auto_symbol(
            Symbol(SymbolType.FunctionSymbol, 0, '_dispatcher'))

        invalidJumpCallbackNotification = InvalidJumpCallback()
        self.register_notification(invalidJumpCallbackNotification)

        dispatcherCallbackNotification = DispatcherCallback()
        self.register_notification(dispatcherCallbackNotification)

        dynamicJumpCallbackNotification = DynamicJumpCallback()
        self.register_notification(dynamicJumpCallbackNotification)
        return True
Example #26
0
    def init(self):
        try:
            self.platform = Platform['microcorruption-msp430']
            self.arch = Architecture['msp430']

            self.entry_addr = struct.unpack('<H', self.raw.read(0xfffe, 2))[0]
            
            self.add_auto_segment(
                0, self.entry_addr, 0, self.entry_addr,
                SegmentFlag.SegmentReadable | SegmentFlag.SegmentWritable
            )
            self.add_auto_segment(
                self.entry_addr, 0x10000 - self.entry_addr,
                self.entry_addr, 0x10000 - self.entry_addr,
                SegmentFlag.SegmentExecutable | SegmentFlag.SegmentReadable
            )

            self.add_entry_point(self.entry_addr)

            path = os.path.dirname(self.file.original_filename)
            filename = os.path.basename(self.file.original_filename)
            sym_path = os.path.join(path, os.path.splitext(filename)[0] + '.sym')

            if os.path.exists(sym_path) and not self.symbols:
                with open(sym_path, 'r') as f:
                    for line in f:
                        addr, symbol = line.split(' ')[:2]
                        addr = int(addr, 16)
                        symbol = symbol.strip()
                        self.define_auto_symbol(Symbol(SymbolType.FunctionSymbol, addr, symbol))

        except:
            log_error(traceback.format_exc())
            return False

        return True
Example #27
0
def analyze_jumps(view, func):
    dispatch_functions = []

    # We'll reference these when determining if we need to create a function
    mlil_jumps = (
        MediumLevelILOperation.MLIL_JUMP_TO, MediumLevelILOperation.MLIL_JUMP
    )

    dispatcher = func.medium_level_il

    il_bb_lookup = build_bb_lookup_table(dispatcher)

    # Iterate over all of the MLIL instructions and find all the JUMPI
    # instructions.
    current_bb = dispatcher.basic_blocks[0]
    il = None
    while current_bb:
        if il is not None:
            current_bb = il_bb_lookup[il.false]

        il = current_bb[-1]

        if il.operation == MediumLevelILOperation.MLIL_IF:
            # add the fallback function
            if current_bb == dispatcher.basic_blocks[0]:
                true = dispatcher[il.true]
                if true.operation == MediumLevelILOperation.MLIL_JUMP_TO:
                    dispatch_functions.append(
                        (true.dest.constant+1, "_fallback")
                    )

            visitor = EVMVisitor(lookup=il_bb_lookup)
            visit_result = visitor.visit(il)

            if visit_result is None:
                continue

            value, hash_constant = visit_result

            if value < len(view):
                continue

            # Locate the definition of the hash value so we can set
            # the int display type of the hash to a pointer. This
            # will let us display the hash name there as a different
            # color.
            stack_offset = dispatcher.source_function.get_reg_value_at(
                hash_constant.address, 'sp'
            ).offset

            hash_il = get_stack_def_for_offset(hash_constant, stack_offset)

            if hash_il is None:
                stack_offset += 8
                hash_il = get_stack_def_for_offset(hash_constant, stack_offset)

            hash_value = '#{:08x}'.format(value)

            # XXX: knownHashes uses a string of the hex as a key, it
            # is probably faster to use an int
            hash_hex = hex(value).replace('L', '')

            # Find the method name if it's known. Otherwise, just use
            # the hash.
            if hash_hex in knownHashes:
                method_name = knownHashes[hash_hex]
            else:
                method_name = hash_value

            # Skip this one if there's already a symbol for the hash.
            # This will keep us from updating the function with the
            # Function.set_int_display_type later on, which will stop
            # us from triggering our own callback repeatedly
            if view.get_symbol_at(value) is not None:
                continue

            # We use SymbolType.ImportedFunctionSymbol because it will
            # change the font color to orange. Gives it a little "pop"!
            #
            # ...yeah that's some stack humor for you.
            view.define_user_symbol(
                Symbol(
                    SymbolType.ImportedFunctionSymbol,
                    value,
                    '{} -> {}'.format(
                        hash_value, method_name
                    )
                )
            )

            if hash_il is not None:
                # Change the hash operand to display the Symbol.
                dispatcher.source_function.set_int_display_type(
                    hash_il.address,
                    hash_constant.constant,
                    0,
                    IntegerDisplayType.PointerDisplayType
                )

            # The dispatched function is down the True branch.
            target = dispatcher[il.true]

            # Make a function at the instruction following the
            # JUMPDEST instruction. This makes the control flow graph
            # "fall through" to the function, pruning those basic blocks
            # from the dispatcher function.
            if target.operation in mlil_jumps:
                dispatch_functions.append(
                    (target.dest.constant + 1, method_name)
                )

        else:
            current_bb = None

    # Go over all the functions we noted above and actually create the function
    # there. We do this last to make sure that view.mlil_instructions doesn't
    # get messed with while we're iterating over it.
    for addr, method_name in dispatch_functions:
        view.create_user_function(addr)
        dispatch_function = view.get_function_at(addr)
        dispatch_function.name = method_name
Example #28
0
 def create_datatype_and_name(self, addr, name, _type):
     self.define_user_data_var(addr, _type)
     self.define_auto_symbol(Symbol(SymbolType.DataSymbol, addr, name))
Example #29
0
def parse_added_methods(view: BinaryView, class_addMethod: int):
    log_debug(f"parse_added_methods(view, {class_addMethod:x})")
    xrefs = view.get_code_refs(class_addMethod)

    for xref in xrefs:
        mlil = xref.function.mlil
        log_debug(f"{xref.address:x} Getting add_method_call")
        add_method_call = xref.function.get_low_level_il_at(xref.address).mlil

        log_debug(f"{xref.address:x} {add_method_call.operation!r}")
        if add_method_call.operation not in (
                MediumLevelILOperation.MLIL_CALL,
                MediumLevelILOperation.MLIL_CALL_UNTYPED):
            continue

        class_param = add_method_call.params[0]
        if class_param.operation != MediumLevelILOperation.MLIL_VAR:
            log_debug(f"class_param is {class_param.operation!r}")
            continue

        cls_ = class_param.src.type

        log_debug(f"Checking {cls_!r}")
        if cls_.target is not None and cls_.target.named_type_reference is not None:
            class_name = cls_.target.named_type_reference.name
        else:
            log_debug(f"cls_ is {cls_}->{cls_.target}")
            continue

        log_debug("Getting selector_param")
        selector_param = add_method_call.params[1]
        if selector_param.operation == MediumLevelILOperation.MLIL_CONST:
            selector_ptr = selector_param
        elif selector_param.operation != MediumLevelILOperation.MLIL_VAR:
            log_debug(f"selector_param {selector_param.operation!r}")
            continue
        else:
            selector_ptr = None

            log_debug("Getting get_method_call")
            get_method_call = mlil.get_ssa_var_definition(
                selector_param.ssa_form.src)

            while get_method_call.operation != MediumLevelILOperation.MLIL_CALL:
                if get_method_call.operation != MediumLevelILOperation.MLIL_SET_VAR:
                    log_debug(f"get_method_call {get_method_call.operation!r}")
                    break

                if get_method_call.src.operation != MediumLevelILOperation.MLIL_VAR:
                    log_debug(f"get_method_call.src {get_method_call.src!r}")
                    break

                get_method_call = mlil.get_ssa_var_definition(
                    get_method_call.ssa_form.src.src
                )
                log_debug(f"{get_method_call!r}")
            else:
                log_debug(f"Found {get_method_call!r}")
                selector_ptr = get_method_call.params[1]

        if selector_ptr is None:
            log_debug("selector_ptr is None")
            continue

        if selector_ptr.operation not in (
                MediumLevelILOperation.MLIL_CONST,
                MediumLevelILOperation.MLIL_CONST_PTR):
            log_debug(f"selector_ptr {selector_ptr.operation!r}")
            continue

        selector_str = view.get_ascii_string_at(selector_ptr.constant, 1)

        if selector_str is None:
            log_debug("selector_str is None")
            continue

        selector = selector_str.value

        method_string = f"-[{class_name} {selector}]"

        log_debug(f"method_string is {method_string}")

        method_ptr = add_method_call.params[2]

        if method_ptr.operation not in (
                MediumLevelILOperation.MLIL_CONST,
                MediumLevelILOperation.MLIL_CONST_PTR):
            log_debug(f"method_ptr.operation {method_ptr.operation!r}")
            continue

        log_debug("Defining {method_string} @ {method_ptr.constant}")
        view.define_user_symbol(
            Symbol(
                SymbolType.FunctionSymbol,
                method_ptr.constant,
                method_string
            )
        )
Example #30
0
binaryninja_api_path = "/Applications/Binary Ninja.app/Contents/Resources/python"
sys.path.append(binaryninja_api_path)
import binaryninja
from binaryninja import PluginCommandContext, PluginCommand
from binaryninja import SymbolType, Symbol
chal =  "ConsoleApplication1-Virtual.bndb"
print "Analyzing {0}".format(chal)
bv = binaryninja.BinaryViewType.get_view_of_file(chal)
bv.update_analysis_and_wait()
badnames = ""
bn = []
nmap ={}
for f in bv.functions:
    badnames+=f.name + "\n"
    bn.append(f.name)
    nmap[f.name] = f.start
x = {"input":badnames}
r = requests.post("https://demangler.com/raw", data=x)  
index = 0
lines = r.text.split("\n")
for l in lines:
    if (index < len(bn)-1):
        name = bn[index]
        if l != name:
            #print("  {0:s}\n->{1:s}".format(l,bn[index]))
            address = nmap[name]
            symbol_type = SymbolType.FunctionSymbol
            symbol = l
            bv.define_user_symbol(Symbol(symbol_type, address, symbol))
    index += 1
bv.save_auto_snapshot()