Source code for binaryninja.lineardisassembly

# Copyright (c) 2015-2024 Vector 35 Inc
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import ctypes
from typing import Optional, List

import binaryninja
from . import _binaryninjacore as core
from . import highlight
from . import function as _function
from . import basicblock
from . import binaryview
from .enums import LinearViewObjectIdentifierType


[docs] class LinearDisassemblyLine: def __init__(self, line_type, func, block, contents): self.type = line_type self.function = func self.block = block self.contents = contents def __repr__(self): return repr(self.contents) def __str__(self): return str(self.contents)
[docs] class LinearViewObjectIdentifier: def __init__(self, name, start=None, end=None): self._name = name self._start = start self._end = end def __repr__(self): return "<LinearViewObjectIdentifier: " + str(self) + ">" def __str__(self): if not self.has_address: return self._name if self.has_range: return "%s 0x%x-0x%x" % (self._name, self._start, self._end) return "%s 0x%x" % (self._name, self._start) def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented return (self._name, self._start, self._end) == (other._name, other._start, other._end) def __ne__(self, other): if not isinstance(other, self.__class__): return NotImplemented return not (self == other) def __hash__(self): return hash((self._name, self._start, self._end)) def _to_core_struct(self, obj=None): if obj is None: result = core.BNLinearViewObjectIdentifier() else: result = obj result.name = self.name if self.has_range: result.type = LinearViewObjectIdentifierType.AddressRangeLinearViewObject result.start = self.start result.end = self.end elif self.has_address: result.type = LinearViewObjectIdentifierType.AddressLinearViewObject result.start = self.start result.end = self.start else: result.type = LinearViewObjectIdentifierType.SingleLinearViewObject result.start = 0 result.end = 0 return result @property def name(self): return self._name @property def address(self): return self._start @property def start(self): return self._start @property def end(self): return self._end @property def has_address(self): return self._start is not None @property def has_range(self): return self._start is not None and self._end is not None @staticmethod def _from_api_object(obj): if obj.type == LinearViewObjectIdentifierType.AddressLinearViewObject: result = LinearViewObjectIdentifier(obj.name, obj.start) elif obj.type == LinearViewObjectIdentifierType.AddressRangeLinearViewObject: result = LinearViewObjectIdentifier(obj.name, obj.start, obj.end) else: result = LinearViewObjectIdentifier(obj.name) return result
[docs] class LinearViewObject: def __init__(self, handle, parent=None): self.handle = handle self._parent = parent def __del__(self): if core is not None: core.BNFreeLinearViewObject(self.handle) def __repr__(self): return "<LinearViewObject: " + str(self) + ">" def __len__(self): return self.end - self.start def __str__(self): result = str(self.identifier) if self._parent is not None: result = str(self._parent) + "/" + result return result @property def first_child(self): result = core.BNGetFirstLinearViewObjectChild(self.handle) if not result: return None return LinearViewObject(result, self) @property def last_child(self): result = core.BNGetLastLinearViewObjectChild(self.handle) if not result: return None return LinearViewObject(result, self) @property def previous(self): if self._parent is None: return None result = core.BNGetPreviousLinearViewObjectChild(self._parent.handle, self.handle) if not result: return None return LinearViewObject(result, self._parent) @property def next(self): if self._parent is None: return None result = core.BNGetNextLinearViewObjectChild(self._parent.handle, self.handle) if not result: return None return LinearViewObject(result, self._parent) @property def start(self): return core.BNGetLinearViewObjectStart(self.handle) @property def end(self): return core.BNGetLinearViewObjectEnd(self.handle) @property def parent(self): return self._parent @property def identifier(self): ident = core.BNGetLinearViewObjectIdentifier(self.handle) result = LinearViewObjectIdentifier._from_api_object(ident) core.BNFreeLinearViewObjectIdentifier(ident) return result @property def cursor(self): root = self while root.parent is not None: root = root.parent return LinearViewCursor(root) @property def ordering_index(self): if self.parent is None: return 0 return self.parent.ordering_index_for_child(self) @property def ordering_index_total(self): return core.BNGetLinearViewObjectOrderingIndexTotal(self.handle)
[docs] def child_for_address(self, addr): result = core.BNGetLinearViewObjectChildForAddress(self.handle, addr) if not result: return None return LinearViewObject(result, self)
[docs] def child_for_identifier(self, ident): ident_obj = ident._to_core_struct() result = core.BNGetLinearViewObjectChildForIdentifier(self.handle, ident_obj) if not result: return None return LinearViewObject(result, self)
[docs] def child_for_ordering_index(self, idx): result = core.BNGetLinearViewObjectChildForOrderingIndex(self.handle, idx) if not result: return None return LinearViewObject(result, self)
[docs] def compare_children(self, a, b): return core.BNCompareLinearViewObjectChildren(self.handle, a.handle, b.handle)
[docs] def get_lines(self, prev_obj, next_obj) -> List['LinearDisassemblyLine']: if prev_obj is not None: prev_obj = prev_obj.handle if next_obj is not None: next_obj = next_obj.handle count = ctypes.c_ulonglong(0) return LinearViewCursor._make_lines( core.BNGetLinearViewObjectLines(self.handle, prev_obj, next_obj, count), count.value )
[docs] def ordering_index_for_child(self, child): return core.BNGetLinearViewObjectOrderingIndexForChild(self.handle, child.handle)
[docs] @staticmethod def disassembly( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewDisassembly(view.handle, _settings))
[docs] @staticmethod def lifted_il( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewLiftedIL(view.handle, _settings))
[docs] @staticmethod def llil( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewLowLevelIL(view.handle, _settings))
[docs] @staticmethod def llil_ssa_form( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewLowLevelILSSAForm(view.handle, _settings))
[docs] @staticmethod def mlil( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewMediumLevelIL(view.handle, _settings))
[docs] @staticmethod def mlil_ssa_form( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewMediumLevelILSSAForm(view.handle, _settings))
[docs] @staticmethod def mmlil( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewMappedMediumLevelIL(view.handle, _settings))
[docs] @staticmethod def mmlil_ssa_form( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewMappedMediumLevelILSSAForm(view.handle, _settings))
[docs] @staticmethod def hlil( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewHighLevelIL(view.handle, _settings))
[docs] @staticmethod def hlil_ssa_form( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewHighLevelILSSAForm(view.handle, _settings))
[docs] @staticmethod def language_representation( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None, language: str = "Pseudo C" ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewLanguageRepresentation(view.handle, _settings, language))
[docs] @staticmethod def data_only( view: 'binaryview.BinaryView', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewDataOnly(view.handle, _settings))
[docs] @staticmethod def single_function_disassembly( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionDisassembly(func.handle, _settings))
[docs] @staticmethod def single_function_lifted_il( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionLiftedIL(func.handle, _settings))
[docs] @staticmethod def single_function_llil( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionLowLevelIL(func.handle, _settings))
[docs] @staticmethod def single_function_llil_ssa_form( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionLowLevelILSSAForm(func.handle, _settings))
[docs] @staticmethod def single_function_mlil( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionMediumLevelIL(func.handle, _settings))
[docs] @staticmethod def single_function_mlil_ssa_form( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionMediumLevelILSSAForm(func.handle, _settings))
[docs] @staticmethod def single_function_mmlil( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionMappedMediumLevelIL(func.handle, _settings))
[docs] @staticmethod def single_function_mmlil_ssa_form( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionMappedMediumLevelILSSAForm(func.handle, _settings))
[docs] @staticmethod def single_function_hlil( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionHighLevelIL(func.handle, _settings))
[docs] @staticmethod def single_function_hlil_ssa_form( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionHighLevelILSSAForm(func.handle, _settings))
[docs] @staticmethod def single_function_language_representation( func: '_function.Function', settings: Optional['_function.DisassemblySettings'] = None, language: str = "Pseudo C" ) -> 'LinearViewObject': _settings = settings if _settings is not None: _settings = _settings.handle return LinearViewObject(core.BNCreateLinearViewSingleFunctionLanguageRepresentation(func.handle, _settings, language))
[docs] class LinearViewCursor: def __init__(self, root_object, handle=None): if handle is not None: self.handle = handle else: self.handle = core.BNCreateLinearViewCursor(root_object.handle) def __del__(self): if core is not None: core.BNFreeLinearViewCursor(self.handle) def __repr__(self): return "<LinearViewCursor: " + str(self.current_object) + ">" def __str__(self): return str(self.current_object) def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented return LinearViewCursor.compare(self, other) == 0 def __ne__(self, other): if not isinstance(other, self.__class__): return NotImplemented return LinearViewCursor.compare(self, other) != 0 def __lt__(self, other): if not isinstance(other, self.__class__): return NotImplemented return LinearViewCursor.compare(self, other) < 0 def __le__(self, other): if not isinstance(other, self.__class__): return NotImplemented return LinearViewCursor.compare(self, other) <= 0 def __gt__(self, other): if not isinstance(other, self.__class__): return NotImplemented return LinearViewCursor.compare(self, other) > 0 def __ge__(self, other): if not isinstance(other, self.__class__): return NotImplemented return LinearViewCursor.compare(self, other) >= 0 def __cmp__(self, other): if not isinstance(other, self.__class__): return NotImplemented return LinearViewCursor.compare(self, other) @property def before_begin(self): return core.BNIsLinearViewCursorBeforeBegin(self.handle) @property def after_end(self): return core.BNIsLinearViewCursorAfterEnd(self.handle) @property def valid(self): return not (self.before_begin or self.after_end) @property def current_object(self): count = ctypes.c_ulonglong(0) path = core.BNGetLinearViewCursorPathObjects(self.handle, count) assert path is not None, "core.BNGetLinearViewCursorPathObjects returned None" result = None for i in range(0, count.value): result = LinearViewObject(core.BNNewLinearViewObjectReference(path[i]), result) core.BNFreeLinearViewCursorPathObjects(path, count.value) return result @property def path(self): count = ctypes.c_ulonglong(0) path = core.BNGetLinearViewCursorPath(self.handle, count) assert path is not None, "core.BNGetLinearViewCursorPath returned None" result = [] for i in range(0, count.value): result.append(LinearViewObjectIdentifier._from_api_object(path[i])) core.BNFreeLinearViewCursorPath(path, count.value) return result @property def path_objects(self): count = ctypes.c_ulonglong(0) path = core.BNGetLinearViewCursorPathObjects(self.handle, count) assert path is not None, "core.BNGetLinearViewCursorPathObjects returned None" result = [] parent = None for i in range(0, count.value): obj = LinearViewObject(core.BNNewLinearViewObjectReference(path[i]), parent) result.append(obj) parent = obj core.BNFreeLinearViewCursorPathObjects(path, count.value) return result @property def ordering_index(self): return core.BNGetLinearViewCursorOrderingIndex(self.handle) @property def ordering_index_total(self): return core.BNGetLinearViewCursorOrderingIndexTotal(self.handle)
[docs] def seek_to_begin(self): core.BNSeekLinearViewCursorToBegin(self.handle)
[docs] def seek_to_end(self): core.BNSeekLinearViewCursorToEnd(self.handle)
[docs] def seek_to_address(self, addr): core.BNSeekLinearViewCursorToAddress(self.handle, addr)
[docs] def seek_to_path(self, path, addr=None): if isinstance(path, LinearViewCursor): if addr is None: return core.BNSeekLinearViewCursorToCursorPath(self.handle, path.handle) return core.BNSeekLinearViewCursorToCursorPathAndAddress(self.handle, path.handle, addr) path_objs = (core.BNLinearViewObjectIdentifier * len(path))() for i in range(0, len(path)): path[i]._to_core_struct(path_objs[i]) if addr is None: return core.BNSeekLinearViewCursorToPath(self.handle, path_objs, len(path)) return core.BNSeekLinearViewCursorToPathAndAddress(self.handle, path_objs, len(path), addr)
[docs] def seek_to_ordering_index(self, idx): core.BNSeekLinearViewCursorToOrderingIndex(self.handle, idx)
[docs] def previous(self): return core.BNLinearViewCursorPrevious(self.handle)
[docs] def next(self): return core.BNLinearViewCursorNext(self.handle)
@staticmethod def _make_lines(lines, count: int) -> List['LinearDisassemblyLine']: assert lines is not None, "core returned None for LinearDisassembly lines" try: result = [] for i in range(0, count): func = None block = None if lines[i].function: func = _function.Function(None, core.BNNewFunctionReference(lines[i].function)) if lines[i].block: core_block = core.BNNewBasicBlockReference(lines[i].block) assert core_block is not None, "core.BNNewBasicBlockReference returned None" block = basicblock.BasicBlock(core_block, None) color = highlight.HighlightColor._from_core_struct(lines[i].contents.highlight) addr = lines[i].contents.addr tokens = _function.InstructionTextToken._from_core_struct( lines[i].contents.tokens, lines[i].contents.count ) contents = _function.DisassemblyTextLine(tokens, addr, color=color) result.append(LinearDisassemblyLine(lines[i].type, func, block, contents)) return result finally: core.BNFreeLinearDisassemblyLines(lines, count) @property def lines(self): count = ctypes.c_ulonglong(0) return LinearViewCursor._make_lines(core.BNGetLinearViewCursorLines(self.handle, count), count.value)
[docs] def duplicate(self): return LinearViewCursor(None, handle=core.BNDuplicateLinearViewCursor(self.handle))
[docs] @staticmethod def compare(a, b): return core.BNCompareLinearViewCursors(a.handle, b.handle)