def STRUCT_DECL_handler(self, current_node_hash): with self.driver.session() as session: struct_name = session.run("MATCH (binja_struct:STRUCT_DECL {Hash: {current_node_hash}}) " "RETURN binja_struct.TypeName as struct_name", current_node_hash=current_node_hash).peek()['struct_name'] result = session.run("MATCH (binja_struct:STRUCT_DECL {Hash: {current_node_hash}})-[:FieldDef]->" "(struct_field:StructFieldDecl) " "RETURN struct_field.Hash as field_hash, " " struct_field.TypeDefinition as type_definition," " struct_field.TypeName as type_name ", current_node_hash=current_node_hash) if result.peek(): # Structs can be recursively defined. In order to avoid such a situation the binja_struct is # immediately inserted into the cache instead of waiting for the full definition. self.type_definition_cache[current_node_hash] = True print(f'struct_name: {struct_name} Hash: {current_node_hash}') binja_struct = types.Structure() self.bv.define_user_type(struct_name, Type.structure_type(types.Structure())) for record in result: if self.insert_type_definition_into_binaryView('StructFieldDecl', record['field_hash']): self.type_definition_cache[record['field_hash']] = True else: print("Failed to insert definition for binja_struct field ", record['field_hash']) return False try: # add binja_struct member print(f'binja_struct def: {record["type_definition"]} , name: {record["type_name"]}') type_string = record['type_definition'] + ' ' + record['type_name'] if record['type_definition'].startswith('AnonUnion'): type_string = 'union' + ' ' + type_string elif record['type_definition'].startswith('AnonStruct'): type_string = 'struct' + ' ' + type_string print('type_string: ', type_string) var_type, name = self.bv.parse_type_string(type_string) binja_struct.append(var_type, str(name)) except Exception as e: print("STRUCT_DECL_handler: Failed to add a binja_struct member" + str(e)) return False else: print("Struct has no target, current binja_struct hash: ", current_node_hash) return False try: self.bv.define_user_type(struct_name, Type.structure_type(binja_struct)) return True except Exception as e: print("STRUCT_DECL_handler: Failed to define Struct. " + str(e)) return False
def UNION_DECL_handler(self, current_node_hash): with self.driver.session() as session: union_name = session.run("MATCH (union:UNION_DECL {Hash: {current_node_hash}}) " "RETURN union.TypeName as union_name", current_node_hash=current_node_hash).peek()['union_name'] result = session.run("MATCH (union:UNION_DECL {Hash: {current_node_hash}})-[:FieldDef]->" "(union_field) " "RETURN union_field.Hash as field_hash, " " labels(union_field)[0] as field_label, " " union_field.TypeDefinition as type_definition," " union_field.TypeName as type_name ", current_node_hash=current_node_hash) if result.peek(): # Unions can be recursively defined. In order to avoid such a situation the struct is # immediately inserted into the cache instead of waiting for the full definition. self.type_definition_cache[current_node_hash] = True struct = types.Structure() # set type to union struct.type = types.StructureType.UnionStructureType self.bv.define_user_type(union_name, Type.structure_type(types.Structure())) for record in result: if self.insert_type_definition_into_binaryView(record['field_label'], record['field_hash']): self.type_definition_cache[record['field_hash']] = True else: print("Failed to insert definition for union field ", record['field_hash']) return False try: # add struct member if record['type_definition'] == 'PointerTo': type_string = record['type_name'] else: type_string = record['type_definition'] + ' ' + record['type_name'] var_type, name = self.bv.parse_type_string(type_string) struct.append(var_type, str(name)) except Exception as e: print("UNION_DECL_handler: Failed to add union member. " + str(e)) return False else: print("Union has no target, current Union hash: ", current_node_hash) return False try: self.bv.define_user_type(union_name, Type.structure_type(struct)) return True except Exception as e: print("UNION_DECL_handler: Failed to define union. " + str(e)) return False
def _lookup_type(type_string: str, view: BinaryView): if type_string in basic_types: return basic_types[type_string] elif type_string == '*': return Type.pointer(view.arch, Type.char()) elif type_string.startswith('@'): if type_string[2:-1] in view.types: return Type.pointer( view.arch, Type.named_type_from_type( type_string[2:-1], view.types[type_string[2:-1]] ) ) elif type_string != '@?' and type_string != '@': if type_string[2:-1]: new_type = Type.named_type_from_type( type_string[2:-1], Type.structure_type(Structure())) view.define_user_type(type_string[2:-1], new_type) else: new_type = Type.void() return Type.pointer(view.arch, new_type) else: return Type.pointer(view.arch, Type.void()) elif type_string.startswith('#'): return Type.pointer(view.arch, Type.void()) elif type_string == ':': return view.types['SEL'] else: return Type.pointer(view.arch, Type.void())
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 visit_MLIL_CONST(self, expr): view = expr.function.source_function.view class_symbol = view.get_symbol_at(expr.constant) if class_symbol is None: return log_debug(class_symbol.name) class_match = re.match( r'_OBJC_(META)?CLASS_\$_(?P<classname>[_A-Za-z0-9=/]+)(@GOT)?', class_symbol.name ) class_name = class_match.group('classname') class_type = view.types.get(class_name) if class_type is None: view.define_user_type(class_name, Type.structure_type(Structure())) class_type = view.types.get(class_name) return Type.pointer( view.arch, Type.named_type_from_type(class_name, class_type) )
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 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 _parse_structure(type_string: str, view: BinaryView) -> Type: type_name = ''.join( takewhile(lambda i: i != '=', type_string) ) type_string = type_string[len(type_name)+1:] fields = [] while type_string: if type_string[0] == '{': field_type, type_string = _parse_structure(type_string[1:], view) fields.append(field_type) elif type_string[0] == '}': type_string = type_string[1:] break elif type_string[0] == '[': array_size = ''.join(takewhile(str.isdigit, type_string[1:])) array_type = ''.join( takewhile(lambda i: i != ']', type_string[1:]) ) type_string = type_string[len(array_size)+len(array_type)+2:] fields.append( Type.array(_lookup_type(array_type, view), int(array_size)) ) elif type_string[0] == ']': type_string = type_string[1:] continue elif _lookup_type(type_string[0], view): fields.append(_lookup_type(type_string[0], view)) type_string = type_string[1:] else: log_debug(f"Not sure what is going on with this type: {type_string!r}") raise NotImplementedError(f"{type_string!r}") parsed_struct = Structure() for field in fields: parsed_struct.append(field) log_debug(f"Created {type_name}={parsed_struct}") view.define_user_type(type_name, Type.structure_type(parsed_struct)) return ( Type.named_type_from_type( type_name, view.types.get(type_name) ), type_string )
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 from_address(cls, address: int, view: BinaryView) -> Protocol: if address == 0: return None from .class_t import Class from_bytes = partial(int.from_bytes, byteorder=("little" if view.endianness == Endianness.LittleEndian else "big")) protocol_t = Type.named_type_from_type( 'protocol_t', view.get_type_by_name('protocol_t')) if not view.get_data_var_at(address): view.define_user_data_var(address, protocol_t) members = { m.name: from_bytes(view.read(address + m.offset, m.type.width)) for m in view.get_type_by_name('protocol_t').structure.members } members['isa'] = Class.from_address(members['isa'], view) members['name'] = (view.get_ascii_string_at(members['name'], 1).value if members['name'] != 0 else '') if members['name'] not in view.types: view.define_user_type(members['name'], Type.structure_type(Structure())) members['protocols'] = ProtocolList.from_address( members['protocols'], view) members['instanceMethods'] = MethodList.from_address( members['instanceMethods'], members['name'], view) members['optionalInstanceMethods'] = MethodList.from_address( members['optionalInstanceMethods'], members['name'], view) new_protocol = cls(address, **members) view.session_data['Protocols'][new_protocol.name] = new_protocol return new_protocol
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 import_structures(self, structs): """ Import structures into BN database :param structs: Dict containing structure/type info """ for struct_name, struct_info in structs.items(): struct = types.Structure() for member_name, member_info in struct_info['members'].items(): try: typ, _ = self.bv.parse_type_string('{}'.format( member_info['type'])) except SyntaxError: print('Failed to apply type ({}) to member ({}): ({})'.format( member_info['type'], member_name, struct_name)) typ, _ = self.bv.parse_type_string('uint8_t [{}]'.format( member_info['size'])) struct.insert(int(member_info['offset']), typ, member_name) self.bv.define_user_type(struct_name, Type.structure_type(struct))
def define_type(self): structure = Structure() structure.type = StructureType.ClassStructureType structure.width = self.vtable.instanceSize structure.insert(0, Type.pointer(self._view.arch, Type.void()), 'isa') classes = [self] current_superclass = self.superclass while current_superclass: classes.append(current_superclass) current_superclass = current_superclass.superclass while classes: current_class = classes.pop() if current_class.vtable.ivars is None: continue ivar_list = current_class.vtable.ivars for name, ivar in ivar_list.ivars.items(): structure.insert(ivar.offset, ivar.type, name) self._view.define_user_type(self.vtable.name, Type.structure_type(structure))
from binaryninja import ( Architecture, FunctionParameter, Platform, QualifiedName, Type, TypeLibrary, Structure ) advapi32_x86 = TypeLibrary.new(Architecture["x86"], "advapi32.dll") advapi32_x86.add_platform(Platform["windows-x86"]) BOOL = Type.int(4, altname="BOOL") HCRYPTPROV_type = Type.structure_type(Structure()) HCRYPTPROV = Type.named_type_from_type( "HCRYPTPROV", HCRYPTPROV_type ) LPCSTR_type = Type.pointer(Architecture["x86"], Type.char()) LPCSTR = Type.named_type_from_type('LPCSTR', LPCSTR_type) DWORD = Type.int(4, sign=False, altname="DWORD") advapi32_x86.add_named_type("HCRYPTPROV", HCRYPTPROV_type) CryptAcquireContextA = Type.function( BOOL, [ FunctionParameter(