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')
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
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)))
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"))
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
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
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
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"))
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
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)
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}' )
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))
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))
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
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
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
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]))
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)
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
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
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
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
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
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])
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
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
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
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))
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 ) )
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()