diff options
Diffstat (limited to 'python/__init__.py')
| -rw-r--r-- | python/__init__.py | 5521 |
1 files changed, 63 insertions, 5458 deletions
diff --git a/python/__init__.py b/python/__init__.py index e07bd7c5..dcbb8276 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -18,5485 +18,90 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -import _binaryninjacore as core -import ctypes, traceback, json, struct, threading - -_plugin_init = False -def _init_plugins(): - global _plugin_init - if not _plugin_init: - _plugin_init = True - core.BNInitCorePlugins() - core.BNInitUserPlugins() - if not core.BNIsLicenseValidated(): - raise RuntimeError, "License is not valid. Please supply a valid license." - -class DataBuffer: - def __init__(self, contents = "", handle = None): - if handle is not None: - self.handle = core.handle_of_type(handle, core.BNDataBuffer) - elif (type(contents) is int) or (type(contents) is long): - self.handle = core.BNCreateDataBuffer(None, contents) - elif isinstance(contents, DataBuffer): - self.handle = core.BNDuplicateDataBuffer(contents.handle) - else: - self.handle = core.BNCreateDataBuffer(contents, len(contents)) - - def __del__(self): - core.BNFreeDataBuffer(self.handle) - - def __len__(self): - return int(core.BNGetDataBufferLength(self.handle)) - - def __getitem__(self, i): - if isinstance(i, tuple): - result = "" - source = str(self) - for s in i: - result += source[s] - return result - elif isinstance(i, slice): - if i.step is not None: - i = i.indices(len(self)) - start = i[0] - stop = i[1] - if stop <= start: - return "" - buf = ctypes.create_string_buffer(stop - start) - ctypes.memmove(buf, core.BNGetDataBufferContentsAt(self.handle, start), stop - start) - return buf.raw - else: - return str(self)[i] - elif i < 0: - if i >= -len(self): - return chr(core.BNGetDataBufferByte(self.handle, int(len(self) + i))) - raise IndexError, "index out of range" - elif i < len(self): - return chr(core.BNGetDataBufferByte(self.handle, int(i))) - else: - raise IndexError, "index out of range" - - def __setitem__(self, i, value): - if isinstance(i, slice): - if i.step is not None: - raise IndexError, "step not supported on assignment" - i = i.indices(len(self)) - start = i[0] - stop = i[1] - if stop < start: - stop = start - if len(value) != (stop - start): - data = str(self) - data = data[0:start] + value + data[stop:] - core.BNSetDataBufferContents(self.handle, data, len(data)) - else: - value = str(value) - buf = ctypes.create_string_buffer(value) - ctypes.memmove(core.BNGetDataBufferContentsAt(self.handle, start), buf, len(value)) - elif i < 0: - if i >= -len(self): - if len(value) != 1: - raise ValueError, "expected single byte for assignment" - value = str(value) - buf = ctypes.create_string_buffer(alue) - ctypes.memmove(core.BNGetDataBufferContentsAt(self.handle, int(len(self) + i)), buf, 1) - else: - raise IndexError, "index out of range" - elif i < len(self): - if len(value) != 1: - raise ValueError, "expected single byte for assignment" - value = str(value) - buf = ctypes.create_string_buffer(value) - ctypes.memmove(core.BNGetDataBufferContentsAt(self.handle, int(i)), buf, 1) - else: - raise IndexError, "index out of range" - - def __str__(self): - buf = ctypes.create_string_buffer(len(self)) - ctypes.memmove(buf, core.BNGetDataBufferContents(self.handle), len(self)) - return buf.raw - - def __repr__(self): - return repr(str(self)) - - def escape(self): - return core.BNDataBufferToEscapedString(self.handle) - - def unescape(self): - return DataBuffer(handle = core.BNDecodeEscapedString(str(self))) - - def base64_encode(self): - return core.BNDataBufferToBase64(self.handle) - - def base64_decode(self): - return DataBuffer(handle = core.BNDecodeBase64(str(self))) - - def zlib_compress(self): - buf = core.BNZlibCompress(self.handle) - if buf is None: - return None - return DataBuffer(handle = buf) - - def zlib_decompress(self): - buf = core.BNZlibDecompress(self.handle) - if buf is None: - return None - return DataBuffer(handle = buf) - -class NavigationHandler(object): - def _register(self, handle): - self._cb = core.BNNavigationHandler() - self._cb.context = 0 - self._cb.getCurrentView = self._cb.getCurrentView.__class__(self._get_current_view) - self._cb.getCurrentOffset = self._cb.getCurrentOffset.__class__(self._get_current_offset) - self._cb.navigate = self._cb.navigate.__class__(self._navigate) - core.BNSetFileMetadataNavigationHandler(handle, self._cb) - - def _get_current_view(self, ctxt): - try: - view = self.get_current_view() - except: - log_error(traceback.format_exc()) - view = "" - return core.BNAllocString(view) - - def _get_current_offset(self, ctxt): - try: - return self.get_current_offset() - except: - log_error(traceback.format_exc()) - return 0 - - def _navigate(self, ctxt, view, offset): - try: - return self.navigate(view, offset) - except: - log_error(traceback.format_exc()) - return False - -class FileMetadata(object): - def __init__(self, filename = None, handle = None): - if handle is not None: - self.handle = core.handle_of_type(handle, core.BNFileMetadata) - else: - _init_plugins() - self.handle = core.BNCreateFileMetadata() - if filename is not None: - core.BNSetFilename(self.handle, str(filename)) - self.__dict__['navigation'] = None - - def __del__(self): - if self.navigation is not None: - core.BNSetFileMetadataNavigationHandler(self.handle, None) - core.BNFreeFileMetadata(self.handle) - - @property - def filename(self): - """Backing filename""" - return core.BNGetFilename(self.handle) - - @filename.setter - def filename(self, value): - core.BNSetFilename(self.handle, str(value)) - - @property - def modified(self): - """Boolean result of whether the file is modified""" - return core.BNIsFileModified(self.handle) - - @modified.setter - def modified(self, value): - if value: - core.BNMarkFileModified(self.handle) - else: - core.BNMarkFileSaved(self.handle) - - @property - def analysis_changed(self): - """Boolean result of whether the auto-analysis results have changed (read-only)""" - return core.BNIsAnalysisChanged(self.handle) - - @property - def has_database(self): - """Whether the FileMetadata is backed by a database""" - return core.BNIsBackedByDatabase(self.handle) - - @property - def view(self): - return core.BNGetCurrentView(self.handle) - - @view.setter - def view(self, value): - core.BNNavigate(self.handle, str(value), core.BNGetCurrentOffset(self.handle)) - - @property - def offset(self): - """Current offset into the file""" - return core.BNGetCurrentOffset(self.handle) - - @offset.setter - def offset(self, value): - core.BNNavigate(self.handle, core.BNGetCurrentView(self.handle), value) - - @property - def raw(self): - view = core.BNGetFileViewOfType(self.handle, "Raw") - if view is None: - return None - return BinaryView(self, handle = view) - - @property - def saved(self): - """Set to mark file as saved""" - return not core.BNIsFileModified(self.handle) - - @saved.setter - def saved(self, value): - if value: - core.BNMarkFileSaved(self.handle) - else: - core.BNMarkFileModified(self.handle) - - def close(self): - core.BNCloseFile(self.handle) - - def begin_undo_actions(self): - core.BNBeginUndoActions(self.handle) - - def commit_undo_actions(self): - core.BNCommitUndoActions(self.handle) - - def undo(self): - core.BNUndo(self.handle) - - def redo(self): - core.BNRedo(self.handle) - - def navigate(self, view, offset): - return core.BNNavigate(self.handle, str(view), offset) - - def create_database(self, filename): - return core.BNCreateDatabase(self.raw.handle, str(filename)) - - def open_existing_database(self, filename): - view = core.BNOpenExistingDatabase(self.handle, str(filename)) - if view is None: - return None - return BinaryView(self, handle = view) - - def save_auto_snapshot(self): - return core.BNSaveAutoSnapshot(self.raw.handle) - - def get_view_of_type(self, name): - view = core.BNGetFileViewOfType(self.handle, str(name)) - if view is None: - view_type = core.BNGetBinaryViewTypeByName(str(name)) - if view_type is None: - return None - view = core.BNCreateBinaryViewOfType(view_type, self.raw.handle) - if view is None: - return None - return BinaryView(self, handle = view) - - def __setattr__(self, name, value): - if name == "navigation": - value._register(self.handle) - self.__dict__["navigation"] = value - else: - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - -class FileAccessor: - def __init__(self): - self._cb = core.BNFileAccessor() - self._cb.context = 0 - self._cb.getLength = self._cb.getLength.__class__(self._get_length) - self._cb.read = self._cb.read.__class__(self._read) - self._cb.write = self._cb.write.__class__(self._write) - - def __len__(self): - return self.get_length() - - def _get_length(self, ctxt): - try: - return self.get_length() - except: - log_error(traceback.format_exc()) - return 0 - - def _read(self, ctxt, dest, offset, length): - try: - data = self.read(offset, length) - if data is None: - return 0 - if len(data) > length: - data = data[0:length] - ctypes.memmove(dest, data, len(data)) - return len(data) - except: - log_error(traceback.format_exc()) - return 0 - - def _write(self, ctxt, offset, src, length): - try: - data = ctypes.create_string_buffer(length) - ctypes.memmove(data, src, length) - return self.write(offset, data.raw) - except: - log_error(traceback.format_exc()) - return 0 - -class CoreFileAccessor(FileAccessor): - def __init__(self, accessor): - self._cb.context = accessor.context - self._cb.getLength = accessor.getLength - self._cb.read = accessor.read - self._cb.write = accessor.write - - def get_length(self): - return self._cb.getLength(self._cb.context) - - def read(self, offset, length): - data = ctypes.create_string_buffer(length) - length = self._cb.read(self._cb.context, data, offset, length) - return data.raw[0:length] - - def write(self, offset, value): - value = str(value) - data = ctypes.create_string_buffer(value) - return self._cb.write(self._cb.context, offset, data, len(value)) - -class BinaryDataNotification: - def data_written(self, view, offset, length): - pass - - def data_inserted(self, view, offset, length): - pass - - def data_removed(self, view, offset, length): - pass - - def function_added(self, view, func): - pass - - def function_removed(self, view, func): - pass - - def function_updated(self, view, func): - pass - - def string_found(self, view, string_type, offset, length): - pass - - def string_removed(self, view, string_type, offset, length): - pass - -class UndoAction: - name = None - action_type = None - _registered = False - _registered_cb = None - - def __init__(self, view): - self._cb = core.BNUndoAction() - if not self.__class__._registered: - raise TypeError, "undo action type not registered" - action_type = self.__class__.action_type - if isinstance(action_type, str): - self._cb.type = BNActionType_by_name[action_type] - else: - self._cb.type = action_type - self._cb.context = 0 - self._cb.undo = self._cb.undo.__class__(self._undo) - self._cb.redo = self._cb.redo.__class__(self._redo) - self._cb.serialize = self._cb.serialize.__class__(self._serialize) - self.view = view - - @classmethod - def register(cls): - _init_plugins() - if cls.name is None: - raise ValueError, "undo action 'name' not defined" - if cls.action_type is None: - raise ValueError, "undo action 'action_type' not defined" - cb_type = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_char_p, ctypes.POINTER(core.BNUndoAction)) - cls._registered_cb = cb_type(cls._deserialize) - core.BNRegisterUndoActionType(cls.name, 0, cls._registered_cb) - cls._registered = True - - @classmethod - def _deserialize(cls, ctxt, data, result): - try: - action = cls.deserialize(json.loads(data)) - if action is None: - return False - result.context = action._cb.context - result.undo = action._cb.undo - result.redo = action._cb.redo - result.serialize = action._cb.serialize - return True - except: - log_error(traceback.format_exc()) - return False - - def _undo(self, ctxt, view): - try: - self.undo() - except: - log_error(traceback.format_exc()) - return False - - def _redo(self, ctxt, view): - try: - self.redo() - except: - log_error(traceback.format_exc()) - return False - - def _serialize(self, ctxt): - try: - return json.dumps(self.serialize()) - except: - log_error(traceback.format_exc()) - return "null" - -class StringReference: - def __init__(self, string_type, start, length): - self.type = string_type - self.start = start - self.length = length - - def __repr__(self): - return "<%s: %#x, len %#x>" % (self.type, self.start, self.length) - -class BinaryDataNotificationCallbacks: - def __init__(self, view, notify): - self.view = view - self.notify = notify - self._cb = core.BNBinaryDataNotification() - self._cb.context = 0 - self._cb.dataWritten = self._cb.dataWritten.__class__(self._data_written) - self._cb.dataInserted = self._cb.dataInserted.__class__(self._data_inserted) - self._cb.dataRemoved = self._cb.dataRemoved.__class__(self._data_removed) - self._cb.functionAdded = self._cb.functionAdded.__class__(self._function_added) - self._cb.functionRemoved = self._cb.functionRemoved.__class__(self._function_removed) - self._cb.functionUpdated = self._cb.functionUpdated.__class__(self._function_updated) - self._cb.stringFound = self._cb.stringFound.__class__(self._string_found) - self._cb.stringRemoved = self._cb.stringRemoved.__class__(self._string_removed) - - def _register(self): - core.BNRegisterDataNotification(self.view.handle, self._cb) - - def _unregister(self): - core.BNUnregisterDataNotification(self.view.handle, self._cb) - - def _data_written(self, ctxt, view, offset, length): - try: - self.notify.data_written(self.view, offset, length) - except: - log_error(traceback.format_exc()) - - def _data_inserted(self, ctxt, view, offset, length): - try: - self.notify.data_inserted(self.view, offset, length) - except: - log_error(traceback.format_exc()) - - def _data_removed(self, ctxt, view, offset, length): - try: - self.notify.data_removed(self.view, offset, length) - except: - log_error(traceback.format_exc()) - - def _function_added(self, ctxt, view, func): - try: - self.notify.function_added(self.view, Function(self.view, core.BNNewFunctionReference(func))) - except: - log_error(traceback.format_exc()) - - def _function_removed(self, ctxt, view, func): - try: - self.notify.function_removed(self.view, Function(self.view, core.BNNewFunctionReference(func))) - except: - log_error(traceback.format_exc()) - - def _function_updated(self, ctxt, view, func): - try: - self.notify.function_updated(self.view, Function(self.view, core.BNNewFunctionReference(func))) - except: - log_error(traceback.format_exc()) - - def _string_found(self, ctxt, view, string_type, offset, length): - try: - self.notify.string_found(self.view, core.BNStringType_names[string_type], offset, length) - except: - log_error(traceback.format_exc()) - - def _string_removed(self, ctxt, view, string_type, offset, length): - try: - self.notify.string_removed(self.view, core.BNStringType_names[string_type], offset, length) - except: - log_error(traceback.format_exc()) - -class _BinaryViewTypeMetaclass(type): - @property - def list(self): - """List all BinaryView types (read-only)""" - _init_plugins() - count = ctypes.c_ulonglong() - types = core.BNGetBinaryViewTypes(count) - result = [] - for i in xrange(0, count.value): - result.append(BinaryViewType(types[i])) - core.BNFreeBinaryViewTypeList(types) - return result - - def __getitem__(self, value): - _init_plugins() - view_type = core.BNGetBinaryViewTypeByName(str(value)) - if view_type is None: - raise KeyError, "'%s' is not a valid view type" % str(value) - return BinaryViewType(view_type) - - def __setattr__(self, name, value): - try: - type.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - -class BinaryViewType(object): - __metaclass__ = _BinaryViewTypeMetaclass - - def __init__(self, handle): - self.handle = core.handle_of_type(handle, core.BNBinaryViewType) - - @property - def name(self): - """Binary View name (read-only)""" - return core.BNGetBinaryViewTypeName(self.handle) - - @property - def long_name(self): - """ Binary VIew long name (read-only)""" - return core.BNGetBinaryViewTypeLongName(self.handle) - - def __repr__(self): - return "<view type: '%s'>" % self.name - - def create(self, data): - view = core.BNCreateBinaryViewOfType(self.handle, data.handle) - if view is None: - return None - return BinaryView(data.file, handle = view) - - def open(self, src, file_metadata = None): - data = BinaryView.open(src, file_metadata) - if data is None: - return None - return self.create(data) - - def is_valid_for_data(self, data): - return core.BNIsBinaryViewTypeValidForData(self.handle, data.handle) - - def register_arch(self, ident, arch): - core.BNRegisterArchitectureForViewType(self.handle, ident, arch.handle) - - def get_arch(self, ident): - arch = core.BNGetArchitectureForViewType(self.handle, ident) - if arch is None: - return None - return Architecture(arch) - - def register_platform(self, ident, arch, platform): - core.BNRegisterPlatformForViewType(self.handle, ident, arch.handle, platform.handle) - - def register_default_platform(self, arch, platform): - core.BNRegisterDefaultPlatformForViewType(self.handle, arch.handle, platform.handle) - - def get_platform(self, ident, arch): - platform = core.BNGetPlatformForViewType(self.handle, ident, arch.handle) - if platform is None: - return None - return Platform(None, platform) - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - -class AnalysisCompletionEvent(object): - def __init__(self, view, callback): - self.view = view - self.callback = callback - self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._notify) - self.handle = core.BNAddAnalysisCompletionEvent(self.view.handle, None, self._cb) - - def __del__(self): - core.BNFreeAnalysisCompletionEvent(self.handle) - - def _notify(self, ctxt): - try: - self.callback() - except: - log_error(traceback.format_exc()) - - def _empty_callback(self): - pass - - def cancel(self): - self.callback = self._empty_callback - core.BNCancelAnalysisCompletionEvent(self.handle) - -class AnalysisProgress(object): - def __init__(self, state, count, total): - self.state = state - self.count = count - self.total = total - - def __str__(self): - if self.state == core.DisassembleState: - return "Disassembling (%d/%d)" % (self.count, self.total) - if self.state == core.AnalyzeState: - return "Analyzing (%d/%d)" % (self.count, self.total) - return "Idle" - - def __repr__(self): - return "<progress: %s>" % str(self) - -class BinaryView(object): - name = None - """Binary View name""" - long_name = None - """Binary View long name""" - _registered = False - _registered_cb = None - view_type = None - """Binary View type""" - - def __init__(self, file_metadata = None, handle = None): - if handle is not None: - self.handle = core.handle_of_type(handle, core.BNBinaryView) - if file_metadata is None: - self.file = FileMetadata(handle = core.BNGetFileForView(handle)) - else: - self.file = file_metadata - elif self.__class__ is BinaryView: - _init_plugins() - if file_metadata is None: - file_metadata = FileMetadata() - self.handle = core.BNCreateBinaryDataView(file_metadata.handle) - self.file = FileMetadata(handle = core.BNNewFileReference(file_metadata)) - else: - _init_plugins() - if not self.__class__._registered: - raise TypeError, "view type not registered" - self._cb = core.BNCustomBinaryView() - self._cb.context = 0 - self._cb.init = self._cb.init.__class__(self._init) - self._cb.read = self._cb.read.__class__(self._read) - self._cb.write = self._cb.write.__class__(self._write) - self._cb.insert = self._cb.insert.__class__(self._insert) - self._cb.remove = self._cb.remove.__class__(self._remove) - self._cb.getModification = self._cb.getModification.__class__(self._get_modification) - self._cb.isValidOffset = self._cb.isValidOffset.__class__(self._is_valid_offset) - self._cb.isOffsetReadable = self._cb.isOffsetReadable.__class__(self._is_offset_readable) - self._cb.isOffsetWritable = self._cb.isOffsetWritable.__class__(self._is_offset_writable) - self._cb.isOffsetExecutable = self._cb.isOffsetExecutable.__class__(self._is_offset_executable) - self._cb.getNextValidOffset = self._cb.getNextValidOffset.__class__(self._get_next_valid_offset) - self._cb.getStart = self._cb.getStart.__class__(self._get_start) - self._cb.getLength = self._cb.getLength.__class__(self._get_length) - self._cb.getEntryPoint = self._cb.getEntryPoint.__class__(self._get_entry_point) - self._cb.isExecutable = self._cb.isExecutable.__class__(self._is_executable) - self._cb.getDefaultEndianness = self._cb.getDefaultEndianness.__class__(self._get_default_endianness) - self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size) - self._cb.save = self._cb.save.__class__(self._save) - self.file = file_metadata - self.handle = core.BNCreateCustomBinaryView(self.__class__.name, file_metadata.handle, self._cb) - self.notifications = {} - - @classmethod - def register(cls): - _init_plugins() - if cls.name is None: - raise ValueError, "view 'name' not defined" - if cls.long_name is None: - cls.long_name = cls.name - cls._registered_cb = core.BNCustomBinaryViewType() - cls._registered_cb.context = 0 - cls._registered_cb.create = cls._registered_cb.create.__class__(cls._create) - cls._registered_cb.isValidForData = cls._registered_cb.isValidForData.__class__(cls._is_valid_for_data) - cls.view_type = BinaryViewType(core.BNRegisterBinaryViewType(cls.name, cls.long_name, cls._registered_cb)) - cls._registered = True - - @classmethod - def _create(cls, ctxt, data): - try: - file_metadata = FileMetadata(handle = core.BNGetFileForView(data)) - view = cls(BinaryView(file_metadata, handle = core.BNNewViewReference(data))) - if view is None: - return None - return ctypes.cast(core.BNNewViewReference(view.handle), ctypes.c_void_p).value - except: - log_error(traceback.format_exc()) - return None - - @classmethod - def _is_valid_for_data(cls, ctxt, data): - try: - return cls.is_valid_for_data(BinaryView(None, handle = core.BNNewViewReference(data))) - except: - log_error(traceback.format_exc()) - return False - - @classmethod - def open(cls, src, file_metadata = None): - _init_plugins() - if isinstance(src, FileAccessor): - if file_metadata is None: - file_metadata = FileMetadata() - view = core.BNCreateBinaryDataViewFromFile(file_metadata.handle, src._cb) - else: - if file_metadata is None: - file_metadata = FileMetadata(str(src)) - view = core.BNCreateBinaryDataViewFromFilename(file_metadata.handle, str(src)) - if view is None: - return None - result = BinaryView(file_metadata, handle = view) - return result - - @classmethod - def new(cls, data = None, file_metadata = None): - _init_plugins() - if file_metadata is None: - file_metadata = FileMetadata() - if data is None: - view = core.BNCreateBinaryDataView(file_metadata.handle) - else: - buf = DataBuffer(data) - view = core.BNCreateBinaryDataViewFromBuffer(file_metadata.handle, buf.handle) - if view is None: - return None - result = BinaryView(file_metadata, handle = view) - return result - - def __del__(self): - for i in self.notifications.values(): - i._unregister() - core.BNFreeBinaryView(self.handle) - - @property - def modified(self): - return self.file.modified - - @modified.setter - def modified(self, value): - self.file.modified = value - - @property - def analysis_changed(self): - """Whether analysis has changed (read-only)""" - return self.file.analysis_changed - - @property - def has_database(self): - """Whether the BinaryView has a database (read-only)""" - return self.file.has_database - - @property - def view(self): - return self.file.view - - @view.setter - def view(self, value): - self.file.view = value - - @property - def offset(self): - return self.file.offset - - @offset.setter - def offset(self, value): - self.file.offset = value - - @property - def start(self): - """Start offset of the binary (read-only)""" - return core.BNGetStartOffset(self.handle) - - @property - def end(self): - """End offset of the binary (read-only)""" - return core.BNGetEndOffset(self.handle) - - @property - def entry_point(self): - """Entry point of the binary (read-only)""" - return core.BNGetEntryPoint(self.handle) - - @property - def arch(self): - arch = core.BNGetDefaultArchitecture(self.handle) - if arch is None: - return None - return Architecture(handle = arch) - - @arch.setter - def arch(self, value): - if value is None: - core.BNSetDefaultArchitecture(self.handle, None) - else: - core.BNSetDefaultArchitecture(self.handle, value.handle) - - @property - def platform(self): - platform = core.BNGetDefaultPlatform(self.handle) - if platform is None: - return None - return Platform(self.arch, handle = platform) - - @platform.setter - def platform(self, value): - if value is None: - core.BNSetDefaultPlatform(self.handle, None) - else: - core.BNSetDefaultPlatform(self.handle, value.handle) - - @property - def endianness(self): - """Endianness of the binary (read-only)""" - return core.BNGetDefaultEndianness(self.handle) - - @property - def address_size(self): - """Address size of the binary (read-only)""" - return core.BNGetViewAddressSize(self.handle) - - @property - def executable(self): - """Whether the binary is an executable (read-only)""" - return core.BNIsExecutableView(self.handle) - - @property - def functions(self): - """List of functions (read-only)""" - count = ctypes.c_ulonglong(0) - funcs = core.BNGetAnalysisFunctionList(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(Function(self, core.BNNewFunctionReference(funcs[i]))) - core.BNFreeFunctionList(funcs, count.value) - return result - - @property - def has_functions(self): - """Boolean whether the binary has functions (read-only)""" - return core.BNHasFunctions(self.handle) - - @property - def entry_function(self): - """Entry function (read-only)""" - func = core.BNGetAnalysisEntryPoint(self.handle) - if func is None: - return None - return Function(self, func) - - @property - def symbols(self): - """Dict of symbols (read-only)""" - count = ctypes.c_ulonglong(0) - syms = core.BNGetSymbols(self.handle, count) - result = {} - for i in xrange(0, count.value): - sym = Symbol(None, None, None, handle = core.BNNewSymbolReference(syms[i])) - result[sym.raw_name] = sym - core.BNFreeSymbolList(syms, count.value) - return result - - @property - def type(self): - """View type (read-only)""" - return core.BNGetViewType(self.handle) - - @property - def available_types(self): - """Available types (read-only)""" - count = ctypes.c_ulonglong(0) - types = core.BNGetBinaryViewTypesForData(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(BinaryViewType(types[i])) - core.BNFreeBinaryViewTypeList(types) - return result - - @property - def strings(self): - """List of strings (read-only)""" - return self.get_strings() - - @property - def saved(self): - return self.file.saved - - @saved.setter - def saved(self, value): - self.file.saved = value - - @property - def analysis_progress(self): - """Status of current analysis (read-only)""" - result = core.BNGetAnalysisProgress(self.handle) - return AnalysisProgress(result.state, result.count, result.total) - - def __len__(self): - return int(core.BNGetViewLength(self.handle)) - - def __getitem__(self, i): - if isinstance(i, tuple): - result = "" - for s in i: - result += self.__getitem__(s) - return result - elif isinstance(i, slice): - if i.step is not None: - raise IndexError, "step not implemented" - i = i.indices(self.end) - start = i[0] - stop = i[1] - if stop <= start: - return "" - return str(self.read(start, stop - start)) - elif i < 0: - if i >= -len(self): - value = str(self.read(int(len(self) + i), 1)) - if len(value) == 0: - return IndexError, "index not readable" - return value - raise IndexError, "index out of range" - elif (i >= self.start) and (i < self.end): - value = str(self.read(int(i), 1)) - if len(value) == 0: - return IndexError, "index not readable" - return value - else: - raise IndexError, "index out of range" - - def __setitem__(self, i, value): - if isinstance(i, slice): - if i.step is not None: - raise IndexError, "step not supported on assignment" - i = i.indices(self.end) - start = i[0] - stop = i[1] - if stop < start: - stop = start - if len(value) != (stop - start): - self.remove(start, stop - start) - self.insert(start, value) - else: - self.write(start, value) - elif i < 0: - if i >= -len(self): - if len(value) != 1: - raise ValueError, "expected single byte for assignment" - if self.write(int(len(self) + i), value) != 1: - raise IndexError, "index not writable" - else: - raise IndexError, "index out of range" - elif (i >= self.start) and (i < self.end): - if len(value) != 1: - raise ValueError, "expected single byte for assignment" - if self.write(int(i), value) != 1: - raise IndexError, "index not writable" - else: - raise IndexError, "index out of range" - - def __repr__(self): - start = self.start - length = len(self) - if start != 0: - size = "start %#x, len %#x" % (start, length) - else: - size = "len %#x" % length - filename = self.file.filename - if len(filename) > 0: - return "<%s view: '%s', %s>" % (self.type, filename, size) - return "<%s view: %s>" % (self.type, size) - - def _init(self, ctxt): - try: - return self.init() - except: - log_error(traceback.format_exc()) - return False - - def _read(self, ctxt, dest, offset, length): - try: - data = self.perform_read(offset, length) - if data is None: - return 0 - if len(data) > length: - data = data[0:length] - ctypes.memmove(dest, str(data), len(data)) - return len(data) - except: - log_error(traceback.format_exc()) - return 0 - - def _write(self, ctxt, offset, src, length): - try: - data = ctypes.create_string_buffer(length) - ctypes.memmove(data, src, length) - return self.perform_write(offset, data.raw) - except: - log_error(traceback.format_exc()) - return 0 - - def _insert(self, ctxt, offset, src, length): - try: - data = ctypes.create_string_buffer(length) - ctypes.memmove(data, src, length) - return self.perform_insert(offset, data.raw) - except: - log_error(traceback.format_exc()) - return 0 - - def _remove(self, ctxt, offset, length): - try: - return self.perform_remove(offset, length) - except: - log_error(traceback.format_exc()) - return 0 - - def _get_modification(self, ctxt, offset): - try: - return self.perform_get_modification(offset) - except: - log_error(traceback.format_exc()) - return core.Original - - def _is_valid_offset(self, ctxt, offset): - try: - return self.perform_is_valid_offset(offset) - except: - log_error(traceback.format_exc()) - return False - - def _is_offset_readable(self, ctxt, offset): - try: - return self.perform_is_offset_readable(offset) - except: - log_error(traceback.format_exc()) - return False - - def _is_offset_writable(self, ctxt, offset): - try: - return self.perform_is_offset_writable(offset) - except: - log_error(traceback.format_exc()) - return False - - def _is_offset_executable(self, ctxt, offset): - try: - return self.perform_is_offset_executable(offset) - except: - log_error(traceback.format_exc()) - return False - - def _get_next_valid_offset(self, ctxt, offset): - try: - return self.perform_get_next_valid_offset(offset) - except: - log_error(traceback.format_exc()) - return offset - - def _get_start(self, ctxt): - try: - return self.perform_get_start() - except: - log_error(traceback.format_exc()) - return 0 - - def _get_length(self, ctxt): - try: - return self.perform_get_length() - except: - log_error(traceback.format_exc()) - return 0 - - def _get_entry_point(self, ctxt): - try: - return self.perform_get_entry_point() - except: - log_error(traceback.format_exc()) - return 0 - - def _is_executable(self, ctxt): - try: - return self.perform_is_executable() - except: - log_error(traceback.format_exc()) - return False - - def _get_default_endianness(self, ctxt): - try: - return self.perform_get_default_endianness() - except: - log_error(traceback.format_exc()) - return core.LittleEndian - - def _get_address_size(self, ctxt): - try: - return self.perform_get_address_size() - except: - log_error(traceback.format_exc()) - return 8 - - def _save(self, ctxt, file_accessor): - try: - return self.perform_save(CoreFileAccessor(file_accessor)) - except: - log_error(traceback.format_exc()) - return False - - def init(self): - return True - - def perform_write(self, offset, data): - return 0 - - def perform_insert(self, offset, data): - return 0 - - def perform_remove(self, offset, length): - return 0 - - def perform_get_modification(self, offset): - return core.Original - - def perform_is_valid_offset(self, offset): - data = self.read(offset, 1) - return (data is not None) and (len(data) == 1) - - def perform_is_offset_readable(self, offset): - return self.is_valid_offset(offset) - - def perform_is_offset_writable(self, offset): - return self.is_valid_offset(offset) - - def perform_is_offset_executable(self, offset): - return self.is_valid_offset(offset) - - def perform_get_next_valid_offset(self, offset): - if offset < self.perform_get_start(): - return self.perform_get_start() - return offset - - def perform_get_start(self): - return 0 - - def perform_get_entry_point(self): - return 0 - - def perform_is_executable(self): - return False - - def perform_get_default_endianness(self): - return core.LittleEndian - - def create_database(self, filename): - return self.file.create_database(filename) - - def save_auto_snapshot(self): - return self.file.save_auto_snapshot() - - def get_view_of_type(self, name): - return self.file.get_view_of_type(name) - - def begin_undo_actions(self): - self.file.begin_undo_actions() - - def add_undo_action(self, action): - core.BNAddUndoAction(self.handle, action.__class__.name, action._cb) - - def commit_undo_actions(self): - self.file.commit_undo_actions() - - def undo(self): - self.file.undo() - - def redo(self): - self.file.redo() - - def navigate(self, view, offset): - self.file.navigate(view, offset) - - def read(self, offset, length): - buf = DataBuffer(handle = core.BNReadViewBuffer(self.handle, offset, length)) - return str(buf) - - def write(self, offset, data): - buf = DataBuffer(data) - return core.BNWriteViewBuffer(self.handle, offset, buf.handle) - - def insert(self, offset, data): - buf = DataBuffer(data) - return core.BNInsertViewBuffer(self.handle, offset, buf.handle) - - def remove(self, offset, length): - return core.BNRemoveViewData(self.handle, offset, length) - - def get_modification(self, offset, length = None): - if length is None: - return core.BNGetModification(self.handle, offset) - data = (core.BNModificationStatus * length)() - length = core.BNGetModificationArray(self.handle, offset, data, length); - return data[0:length] - - def is_valid_offset(self, offset): - return core.BNIsValidOffset(self.handle, offset) - - def is_offset_readable(self, offset): - return core.BNIsOffsetReadable(self.handle, offset) - - def is_offset_writable(self, offset): - return core.BNIsOffsetWritable(self.handle, offset) - - def is_offset_executable(self, offset): - return core.BNIsOffsetExecutable(self.handle, offset) - - def save(self, dest): - if isinstance(dest, FileAccessor): - return core.BNSaveToFile(self.handle, dest._cb) - return core.BNSaveToFilename(self.handle, str(dest)) - - def register_notification(self, notify): - cb = BinaryDataNotificationCallbacks(self, notify) - cb._register() - self.notifications[notify] = cb - - def unregister_notification(self, notify): - if notify in self.notifications: - self.notifications[notify]._unregister() - del self.notifications[notify] - - def add_function(self, platform, addr): - core.BNAddFunctionForAnalysis(self.handle, platform.handle, addr) - - def add_entry_point(self, platform, addr): - core.BNAddEntryPointForAnalysis(self.handle, platform.handle, addr) - - def remove_function(self, func): - core.BNRemoveAnalysisFunction(self.handle, func.handle) - - def create_user_function(self, platform, addr): - core.BNCreateUserFunction(self.handle, platform.handle, addr) - - def update_analysis(self): - core.BNUpdateAnalysis(self.handle) - - def update_analysis_and_wait(self): - class WaitEvent: - def __init__(self): - self.cond = threading.Condition() - self.done = False - - def complete(self): - self.cond.acquire() - self.done = True - self.cond.notify() - self.cond.release() - - def wait(self): - self.cond.acquire() - while not self.done: - self.cond.wait() - self.cond.release() - - wait = WaitEvent() - event = AnalysisCompletionEvent(self, lambda: wait.complete()) - core.BNUpdateAnalysis(self.handle) - wait.wait() - - def abort_analysis(self): - core.BNAbortAnalysis(self.handle) - - def get_function_at(self, platform, addr): - func = core.BNGetAnalysisFunction(self.handle, platform.handle, addr) - if func is None: - return None - return Function(self, func) - - def get_functions_at(self, addr): - count = ctypes.c_ulonglong(0) - funcs = core.BNGetAnalysisFunctionsForAddress(self.handle, addr, count) - result = [] - for i in xrange(0, count.value): - result.append(Function(self, core.BNNewFunctionReference(funcs[i]))) - core.BNFreeFunctionList(funcs, count.value) - return result - - def get_recent_function_at(self, addr): - func = core.BNGetRecentAnalysisFunctionForAddress(self.handle, addr) - if func is None: - return None - return Function(self, func) - - def get_basic_blocks_at(self, addr): - count = ctypes.c_ulonglong(0) - blocks = core.BNGetBasicBlocksForAddress(self.handle, addr, count) - result = [] - for i in xrange(0, count.value): - result.append(BasicBlock(self, core.BNNewBasicBlockReference(blocks[i]))) - core.BNFreeBasicBlockList(blocks, count.value) - return result - - def get_recent_basic_block_at(self, addr): - block = core.BNGetRecentBasicBlockForAddress(self.handle, addr) - if block is None: - return None - return BasicBlock(self, block) - - def get_code_refs(self, addr, length = None): - count = ctypes.c_ulonglong(0) - if length is None: - refs = core.BNGetCodeReferences(self.handle, addr, count) - else: - refs = core.BNGetCodeReferencesInRange(self.handle, addr, length, count) - result = [] - for i in xrange(0, count.value): - if refs[i].func: - func = Function(self, core.BNNewFunctionReference(refs[i].func)) - else: - func = None - if refs[i].arch: - arch = Architecture(refs[i].arch) - else: - arch = None - addr = refs[i].addr - result.append(ReferenceSource(func, arch, addr)) - core.BNFreeCodeReferences(refs, count.value) - return result - - def get_symbol_at(self, addr): - sym = core.BNGetSymbolByAddress(self.handle, addr) - if sym is None: - return None - return Symbol(None, None, None, handle = sym) - - def get_symbol_by_raw_name(self, name): - sym = core.BNGetSymbolByRawName(self.handle, name) - if sym is None: - return None - return Symbol(None, None, None, handle = sym) - - def get_symbols_by_name(self, name): - count = ctypes.c_ulonglong(0) - syms = core.BNGetSymbolsByName(self.handle, name, count) - result = [] - for i in xrange(0, count.value): - result.append(Symbol(None, None, None, handle = core.BNNewSymbolReference(syms[i]))) - core.BNFreeSymbolList(syms, count.value) - return result - - def get_symbols(self, start = None, length = None): - count = ctypes.c_ulonglong(0) - if start is None: - syms = core.BNGetSymbols(self.handle, count) - else: - syms = core.BNGetSymbolsInRange(self.handle, start, length, count) - result = [] - for i in xrange(0, count.value): - result.append(Symbol(None, None, None, handle = core.BNNewSymbolReference(syms[i]))) - core.BNFreeSymbolList(syms, count.value) - return result - - def get_symbols_of_type(self, sym_type, start = None, length = None): - if isinstance(sym_type, str): - sym_type = core.BNSymbolType_by_name[sym_type] - count = ctypes.c_ulonglong(0) - if start is None: - syms = core.BNGetSymbolsOfType(self.handle, sym_type, count) - else: - syms = core.BNGetSymbolsOfTypeInRange(self.handle, sym_type, start, length, count) - result = [] - for i in xrange(0, count.value): - result.append(Symbol(None, None, None, handle = core.BNNewSymbolReference(syms[i]))) - core.BNFreeSymbolList(syms, count.value) - return result - - def define_auto_symbol(self, sym): - core.BNDefineAutoSymbol(self.handle, sym.handle) - - def undefine_auto_symbol(self, sym): - core.BNUndefineAutoSymbol(self.handle, sym.handle) - - def define_user_symbol(self, sym): - core.BNDefineUserSymbol(self.handle, sym.handle) - - def undefine_user_symbol(self, sym): - core.BNUndefineUserSymbol(self.handle, sym.handle) - - def define_imported_function(self, import_addr_sym, func): - core.BNDefineImportedFunction(self.handle, import_addr_sym.handle, func.handle) - - def is_never_branch_patch_available(self, arch, addr): - return core.BNIsNeverBranchPatchAvailable(self.handle, arch.handle, addr) - - def is_always_branch_patch_available(self, arch, addr): - return core.BNIsAlwaysBranchPatchAvailable(self.handle, arch.handle, addr) - - def is_invert_branch_patch_available(self, arch, addr): - return core.BNIsInvertBranchPatchAvailable(self.handle, arch.handle, addr) - - def is_skip_and_return_zero_patch_available(self, arch, addr): - return core.BNIsSkipAndReturnZeroPatchAvailable(self.handle, arch.handle, addr) - - def is_skip_and_return_value_patch_available(self, arch, addr): - return core.BNIsSkipAndReturnValuePatchAvailable(self.handle, arch.handle, addr) - - def convert_to_nop(self, arch, addr): - return core.BNConvertToNop(self.handle, arch.handle, addr) - - def always_branch(self, arch, addr): - return core.BNAlwaysBranch(self.handle, arch.handle, addr) - - def never_branch(self, arch, addr): - return core.BNConvertToNop(self.handle, arch.handle, addr) - - def invert_branch(self, arch, addr): - return core.BNInvertBranch(self.handle, arch.handle, addr) - - def skip_and_return_value(self, arch, addr, value): - return core.BNSkipAndReturnValue(self.handle, arch.handle, addr, value) - - def get_instruction_length(self, arch, addr): - return core.BNGetInstructionLength(self.handle, arch.handle, addr) - - def notify_data_written(self, offset, length): - core.BNNotifyDataWritten(self.handle, offset, length) - - def notify_data_inserted(self, offset, length): - core.BNNotifyDataInserted(self.handle, offset, length) - - def notify_data_removed(self, offset, length): - core.BNNotifyDataRemoved(self.handle, offset, length) - - def get_strings(self, start = None, length = None): - count = ctypes.c_ulonglong(0) - if start is None: - strings = core.BNGetStrings(self.handle, count) - else: - strings = core.BNGetStringsInRange(self.handle, start, length, count) - result = [] - for i in xrange(0, count.value): - result.append(StringReference(core.BNStringType_names[strings[i].type], strings[i].start, strings[i].length)) - core.BNFreeStringList(strings) - return result - - def add_analysis_completion_event(self, callback): - return AnalysisCompletionEvent(self, callback) - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - -class BinaryReader(object): - def __init__(self, data, endian = None): - self.handle = core.BNCreateBinaryReader(data.handle) - if endian is None: - core.BNSetBinaryReaderEndianness(self.handle, data.endianness) - else: - core.BNSetBinaryReaderEndianness(self.handle, endian) - - def __del__(self): - core.BNFreeBinaryReader(self.handle) - - @property - def endianness(self): - return core.BNGetBinaryReaderEndianness(self.handle) - - @endianness.setter - def endianness(self, value): - core.BNSetBinaryReaderEndianness(self.handle, value) - - @property - def offset(self): - return core.BNGetReaderPosition(self.handle) - - @offset.setter - def offset(self, value): - core.BNSeekBinaryReader(self.handle, value) - - @property - def eof(self): - """Boolean, is end of file (read-only)""" - return core.BNIsEndOfFile(self.handle) - - def read(self, length): - dest = ctypes.create_string_buffer(length) - if not core.BNReadData(self.handle, dest, length): - return None - return dest.raw - - def read8(self): - result = ctypes.c_ubyte() - if not core.BNRead8(self.handle, result): - return None - return result.value - - def read16(self): - result = ctypes.c_ushort() - if not core.BNRead16(self.handle, result): - return None - return result.value - - def read32(self): - result = ctypes.c_uint() - if not core.BNRead32(self.handle, result): - return None - return result.value - - def read64(self): - result = ctypes.c_ulonglong() - if not core.BNRead64(self.handle, result): - return None - return result.value - - def read16le(self): - result = self.read(2) - if (result is None) or (len(result) != 2): - return None - return struct.unpack("<H", result)[0] - - def read32le(self): - result = self.read(4) - if (result is None) or (len(result) != 4): - return None - return struct.unpack("<I", result)[0] - - def read64le(self): - result = self.read(8) - if (result is None) or (len(result) != 8): - return None - return struct.unpack("<Q", result)[0] - - def read16be(self): - result = self.read(2) - if (result is None) or (len(result) != 2): - return None - return struct.unpack(">H", result)[0] - - def read32be(self): - result = self.read(4) - if (result is None) or (len(result) != 4): - return None - return struct.unpack(">I", result)[0] - - def read64be(self): - result = self.read(8) - if (result is None) or (len(result) != 8): - return None - return struct.unpack(">Q", result)[0] - - def seek(self, offset): - core.BNSeekBinaryReader(self.handle, offset) - - def seek_relative(self, offset): - core.BNSeekBinaryReaderRelative(self.handle, offset) - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - -class BinaryWriter: - def __init__(self, data, endian = None): - self.handle = core.BNCreateBinaryWriter(data.handle) - if endian is None: - core.BNSetBinaryWriterEndianness(self.handle, data.endianness) - else: - core.BNSetBinaryWriterEndianness(self.handle, endian) - - def __del__(self): - core.BNFreeBinaryWriter(self.handle) - - @property - def endianness(self): - return core.BNGetBinaryWriterEndianness(self.handle) - - @endianness.setter - def endianness(self, value): - core.BNSetBinaryWriterEndianness(self.handle, value) - - @property - def offset(self): - return core.BNGetWriterPosition(self.handle) - - @offset.setter - def offset(self, value): - core.BNSeekBinaryWriter(self.handle, value) - - def write(self, value): - value = str(value) - buf = ctypes.create_string_buffer(len(value)) - ctypes.memmove(buf, value, len(value)) - return core.BNWriteData(self.handle, buf, len(value)) - - def write8(self, value): - return core.BNWrite8(self.handle, value) - - def write16(self, value): - return core.BNWrite16(self.handle, value) - - def write32(self, value): - return core.BNWrite32(self.handle, value) - - def write64(self, value): - return core.BNWrite64(self.handle, value) - - def write16le(self, value): - value = struct.pack("<H", value) - return self.write(value) - - def write32le(self, value): - value = struct.pack("<I", value) - return self.write(value) - - def write64le(self, value): - value = struct.pack("<Q", value) - return self.write(value) - - def write16be(self, value): - value = struct.pack(">H", value) - return self.write(value) - - def write32be(self, value): - value = struct.pack(">I", value) - return self.write(value) - - def write64be(self, value): - value = struct.pack(">Q", value) - return self.write(value) - - def seek(self, offset): - core.BNSeekBinaryWriter(self.handle, offset) - - def seek_relative(self, offset): - core.BNSeekBinaryWriterRelative(self.handle, offset) - -class Symbol(object): - def __init__(self, sym_type, addr, short_name, full_name = None, raw_name = None, handle = None): - if handle is not None: - self.handle = core.handle_of_type(handle, core.BNSymbol) - else: - if isinstance(sym_type, str): - sym_type = core.BNSymbolType_by_name[sym_type] - if full_name is None: - full_name = short_name - if raw_name is None: - raw_name = full_name - self.handle = core.BNCreateSymbol(sym_type, short_name, full_name, raw_name, addr) - - def __del__(self): - core.BNFreeSymbol(self.handle) - - @property - def type(self): - """Symbol type (read-only)""" - return core.BNSymbolType_names[core.BNGetSymbolType(self.handle)] - - @property - def name(self): - """Symbol name (read-only)""" - return core.BNGetSymbolRawName(self.handle) - - @property - def short_name(self): - """Symbol short name (read-only)""" - return core.BNGetSymbolShortName(self.handle) - - @property - def full_name(self): - """Symbol full name (read-only)""" - return core.BNGetSymbolFullName(self.handle) - - @property - def raw_name(self): - """Symbol raw name (read-only)""" - return core.BNGetSymbolRawName(self.handle) - - @property - def address(self): - """Symbol address (read-only)""" - return core.BNGetSymbolAddress(self.handle) - - @property - def auto(self): - return core.BNIsSymbolAutoDefined(self.handle) - - @auto.setter - def auto(self, value): - core.BNSetSymbolAutoDefined(self.handle, value) - - def __repr__(self): - return "<%s: \"%s\" @ %#x>" % (self.type, self.full_name, self.address) - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - -class Type(object): - def __init__(self, handle): - self.handle = handle - - def __del__(self): - core.BNFreeType(self.handle) - - @property - def type_class(self): - """Type class (read-only)""" - return BNTypeClass_names[core.BNGetTypeClass(self.handle)] - - @property - def width(self): - """Type width (read-only)""" - return core.BNGetTypeWidth(self.handle) - - @property - def alignment(self): - """Type alignment (read-only)""" - return core.BNGetTypeAlignment(self.handle) - - @property - def signed(self): - """Wether type is signed (read-only)""" - return core.BNIsTypeSigned(self.handle) - - @property - def const(self): - """Whether type is const (read-only)""" - return core.BNIsTypeConst(self.handle) - - @property - def modified(self): - """Whether type is modified (read-only)""" - return core.BNIsTypeFloatingPoint(self.handle) - - @property - def target(self): - """Target (read-only)""" - result = core.BNGetChildType(self.handle) - if result is None: - return None - return Type(result) - - @property - def element_type(self): - """Target (read-only)""" - result = core.BNGetChildType(self.handle) - if result is None: - return None - return Type(result) - - @property - def return_value(self): - """Return value (read-only)""" - result = core.BNGetChildType(self.handle) - if result is None: - return None - return Type(result) - - @property - def calling_convention(self): - """Calling convention (read-only)""" - result = core.BNGetTypeCallingConvention(self.handle) - if result is None: - return None - return CallingConvention(None, result) - - @property - def parameters(self): - """Type parameters list (read-only)""" - count = ctypes.c_ulonglong() - params = core.BNGetTypeParameters(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append((Type(core.BNNewTypeReference(params[i].type)), params[i].name)) - core.BNFreeTypeParameterList(params, count.value) - return result - - @property - def has_variable_arguments(self): - """Whether type has variable arguments (read-only)""" - return core.BNTypeHasVariableArguments(self.handle) - - @property - def can_return(self): - """Whether type can return (read-only)""" - return core.BNFunctionTypeCanReturn(self.handle) - - @property - def structure(self): - """Structure of the type (read-only)""" - result = core.BNGetTypeStructure(self.handle) - if result is None: - return None - return Structure(result) - - @property - def enumeration(self): - """Type enumeration (read-only)""" - result = core.BNGetTypeEnumeration(self.handle) - if result is None: - return None - return Enumeration(result) - - @property - def count(self): - """Type count (read-only)""" - return core.BNGetTypeElementCount(self.handle) - - def __str__(self): - return core.BNGetTypeString(self.handle) - - def __repr__(self): - return "<type: %s>" % str(self) - - def get_string_before_name(self): - return core.BNGetTypeStringBeforeName(self.handle) - - def get_string_after_name(self): - return core.BNGetTypeStringAfterName(self.handle) - - @classmethod - def void(cls): - return Type(core.BNCreateVoidType()) - - @classmethod - def bool(self): - return Type(core.BNCreateBoolType()) - - @classmethod - def int(self, width, sign = True): - return Type(core.BNCreateIntegerType(width, sign)) - - @classmethod - def float(self, width): - return Type(core.BNCreateFloatType(width)) - - @classmethod - def structure_type(self, s): - return Type(core.BNCreateStructureType(s.handle)) - - @classmethod - def enumeration_type(self, arch, e, width = None): - if width is None: - width = arch.default_int_size - return Type(core.BNCreateEnumerationType(e.handle, width)) - - @classmethod - def pointer(self, arch, t, const = False): - return Type(core.BNCreatePointerType(arch.handle, t.handle, const)) - - @classmethod - def array(self, t, count): - return Type(core.BNCreateArrayType(t.handle, count)) - - @classmethod - def function(self, ret, params, calling_convention = None, variable_arguments = False): - param_buf = (core.BNNameAndType * len(params))() - for i in xrange(0, len(params)): - if isinstance(params[i], Type): - param_buf[i].name = ""; - param_buf[i].type = params[i].handle - else: - param_buf[i].name = params[i][1] - param_buf[i].type = params[i][0] - if calling_convention is not None: - calling_convention = calling_convention.handle - return Type(core.BNCreateFunctionType(ret.handle, calling_convention, param_buf, len(params), - variable_arguments)) - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - -class StructureMember: - def __init__(self, t, name, offset): - self.type = t - self.name = name - self.offset = offset - - def __repr__(self): - if len(name) == 0: - return "<member: %s, offset %#x>" % (str(self.type), self.offset) - return "<%s %s%s, offset %#x>" % (self.type.get_string_before_name(), self.name, - self.type.get_string_after_name(), self.offset) - -class Structure(object): - def __init__(self, handle = None): - if handle is None: - self.handle = core.BNCreateStructure() - else: - self.handle = handle - - def __del__(self): - core.BNFreeStructure(self.handle) - - @property - def name(self): - return core.BNGetStructureName(self.handle) - - @name.setter - def name(self, value): - core.BNSetStructureName(self.handle, value) - - @property - def members(self): - """Structure member list (read-only)""" - count = ctypes.c_ulonglong() - members = core.BNGetStructureMembers(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(StructureMember(Type(core.BNNewTypeReference(members[i].type)), - members[i].name, members[i].offset)) - core.BNFreeStructureMemberList(members, count.value) - return result - - @property - def width(self): - """Structure width (read-only)""" - return core.BNGetStructureWidth(self.handle) - - @property - def alignment(self): - """Structure alignment (read-only)""" - return core.BNGetStructureAlignment(self.handle) - - @property - def packed(self): - return core.BNIsStructurePacked(self.handle) - - @packed.setter - def packed(self, value): - core.BNSetStructurePacked(self.handle, value) - - @property - def union(self): - return core.BNIsStructureUnion(self.handle) - - @union.setter - def union(self, value): - core.BNSetStructureUnion(self.handle, value) - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __repr__(self): - if len(self.name) > 0: - return "<struct: %s>" % self.name - return "<struct: size %#x>" % self.width - - def append(self, t, name = ""): - core.BNAddStructureMember(self.handle, t.handle, name) - - def insert(self, offset, t, name = ""): - core.BNAddStructureMemberAtOffset(self.handle, t.handle, name, offset) - - def remove(self, i): - core.BNRemoveStructureMember(self.handle, i) - -class EnumerationMember: - def __init__(self, name, value, default): - self.name = name - self.value = value - self.default = default - - def __repr__(self): - return "<%s = %#x>" % (self.name, self.value) - -class Enumeration(object): - def __init__(self, handle = None): - if handle is None: - self.handle = core.BNCreateEnumeration() - else: - self.handle = handle - - def __del__(self): - core.BNFreeEnumeration(self.handle) - - @property - def name(self): - return core.BNGetEnumerationName(self.handle) - - @name.setter - def name(self, value): - core.BNSetEnumerationName(self.handle, value) - - @property - def members(self): - """Enumeration member list (read-only)""" - count = ctypes.c_ulonglong() - members = core.BNGetEnumerationMembers(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(EnumerationMember(members[i].name, members[i].value, members[i].isDefault)) - core.BNFreeEnumerationMemberList(members, count.value) - return result - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __repr__(self): - if len(self.name) > 0: - return "<enum: %s>" % self.name - return "<enum: %s>" % repr(self.members) - - def append(self, name, value = None): - if value is None: - core.BNAddEnumerationMember(self.handle, name) - else: - core.BNAddEnumerationMemberWithValue(self.handle, name, value) - -class LookupTableEntry: - def __init__(self, from_values, to_value): - self.from_values = from_values - self.to_value = to_value - - def __repr__(self): - return "[%s] -> %#x" % (', '.join(["%#x" % i for i in self.from_values]), self.to_value) - -class RegisterValue: - def __init__(self, arch, value): - self.type = value.state - if value.state == EntryValue: - self.reg = arch.get_reg_name(value.reg) - elif value.state == OffsetFromEntryValue: - self.reg = arch.get_reg_name(value.reg) - self.offset = value.value - elif value.state == ConstantValue: - self.value = value.value - elif value.state == StackFrameOffset: - self.offset = value.value - elif value.state == SignedRangeValue: - self.offset = value.value - self.start = value.rangeStart - self.end = value.rangeEnd - self.step = value.rangeStep - if self.start & (1 << 63): - self.start |= ~((1 << 63) - 1) - if self.end & (1 << 63): - self.end |= ~((1 << 63) - 1) - elif value.state == UnsignedRangeValue: - self.offset = value.value - self.start = value.rangeStart - self.end = value.rangeEnd - self.step = value.rangeStep - elif value.state == LookupTableValue: - self.table = [] - self.mapping = {} - for i in xrange(0, value.rangeEnd): - from_list = [] - for j in xrange(0, value.table[i].fromCount): - from_list.append(value.table[i].fromValues[j]) - self.mapping[value.table[i].fromValues[j]] = value.table[i].toValue - self.table.append(LookupTableEntry(from_list, value.table[i].toValue)) - elif value.state == OffsetFromUndeterminedValue: - self.offset = value.value - - def __repr__(self): - if self.type == EntryValue: - return "<entry %s>" % self.reg - if self.type == OffsetFromEntryValue: - return "<entry %s + %#x>" % (self.reg, self.offset) - if self.type == ConstantValue: - return "<const %#x>" % self.value - if self.type == StackFrameOffset: - return "<stack frame offset %#x>" % self.offset - if (self.type == SignedRangeValue) or (self.type == UnsignedRangeValue): - if self.step == 1: - return "<range: %#x to %#x>" % (self.start, self.end) - return "<range: %#x to %#x, step %#x>" % (self.start, self.end, self.step) - if self.type == LookupTableValue: - return "<table: %s>" % ', '.join([repr(i) for i in self.table]) - if self.type == OffsetFromUndeterminedValue: - return "<undetermined with offset %#x>" % self.offset - return "<undetermined>" - -class StackVariable: - def __init__(self, ofs, name, t): - self.offset = ofs - self.name = name - self.type = t - - def __repr__(self): - return "<var@%x: %s %s>" % (self.offset, self.type, self.name) - - def __str__(self): - return self.name - -class StackVariableReference: - def __init__(self, src_operand, t, name, start_ofs, ref_ofs): - self.source_operand = src_operand - self.type = t - self.name = name - self.starting_offset = start_ofs - self.referenced_offset = ref_ofs - if self.source_operand == 0xffffffff: - self.source_operand = None - - def __repr__(self): - if self.source_operand is None: - if self.referenced_offset != self.starting_offset: - return "<ref to %s%+#x>" % (self.name, self.referenced_offset - self.starting_offset) - return "<ref to %s>" % self.name - if self.referenced_offset != self.starting_offset: - return "<operand %d ref to %s%+#x>" % (self.source_operand, self.name, self.referenced_offset) - return "<operand %d ref to %s>" % (self.source_operand, self.name) - -class IndirectBranchInfo: - def __init__(self, source_arch, source_addr, dest_arch, dest_addr, auto_defined): - self.source_arch = source_arch - self.source_addr = source_addr - self.dest_arch = dest_arch - self.dest_addr = dest_addr - self.auto_defined = auto_defined - - def __repr__(self): - return "<branch %s:%#x -> %s:%#x>" % (self.source_arch.name, self.source_addr, self.dest_arch.name, self.dest_addr) - -class Function(object): - def __init__(self, view, handle): - self._view = view - self.handle = core.handle_of_type(handle, core.BNFunction) - - def __del__(self): - core.BNFreeFunction(self.handle) - - @property - def view(self): - """Function view (read-only)""" - return self._view - - @property - def arch(self): - """Function architecture (read-only)""" - arch = core.BNGetFunctionArchitecture(self.handle) - if arch is None: - return None - return Architecture(arch) - - @property - def start(self): - """Function start (read-only)""" - return core.BNGetFunctionStart(self.handle) - - @property - def symbol(self): - """Function symbol(read-only)""" - sym = core.BNGetFunctionSymbol(self.handle) - if sym is None: - return None - return Symbol(None, None, None, handle = sym) - - @property - def auto(self): - """Whether function was automatically discovered (read-only)""" - return core.BNWasFunctionAutomaticallyDiscovered(self.handle) - - @property - def can_return(self): - """Whether function can return (read-only)""" - return core.BNCanFunctionReturn(self.handle) - - @property - def explicitly_defined_type(self): - """Whether function has explicitly defined types (read-only)""" - return core.BNHasExplicitlyDefinedType(self.handle) - - @property - def basic_blocks(self): - """List of basic blocks (read-only)""" - count = ctypes.c_ulonglong() - blocks = core.BNGetFunctionBasicBlockList(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i]))) - core.BNFreeBasicBlockList(blocks, count.value) - return result - - @property - def comments(self): - """Dict of comments (read-only)""" - count = ctypes.c_ulonglong() - addrs = core.BNGetCommentedAddresses(self.handle, count) - result = {} - for i in xrange(0, count.value): - result[addrs[i]] = self.get_comment_at(addrs[i]) - core.BNFreeAddressList(addrs) - return result - - @property - def indirect_branches(self): - count = ctypes.c_ulonglong() - branches = core.BNGetIndirectBranches(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(IndirectBranchInfo(Architecture(branches[i].sourceArch), branches[i].sourceAddr, Architecture(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) - core.BNFreeIndirectBranchList(branches) - return result - - @property - def low_level_il(self): - """Function low level IL (read-only)""" - return LowLevelILFunction(self.arch, core.BNNewLowLevelILFunctionReference( - core.BNGetFunctionLowLevelIL(self.handle)), self) - - @property - def lifted_il(self): - """Function lifted IL (read-only)""" - return LowLevelILFunction(self.arch, core.BNNewLowLevelILFunctionReference( - core.BNGetFunctionLiftedIL(self.handle)), self) - - @property - def type(self): - """Function type (read-only)""" - return Type(core.BNGetFunctionType(self.handle)) - - @property - def stack_layout(self): - """List of function stack (read-only)""" - count = ctypes.c_ulonglong() - v = core.BNGetStackLayout(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(StackVariable(v[i].offset, v[i].name, Type(handle = core.BNNewTypeReference(v[i].type)))) - result.sort(key = lambda x: x.offset) - core.BNFreeStackLayout(v, count.value) - return result - - @property - def indirect_branches(self): - """List of indirect branches (read-only)""" - count = ctypes.c_ulonglong() - branches = core.BNGetIndirectBranches(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(IndirectBranchInfo(Architecture(branches[i].sourceArch), branches[i].sourceAddr, Architecture(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) - core.BNFreeIndirectBranchList(branches) - return result - - def __iter__(self): - count = ctypes.c_ulonglong() - blocks = core.BNGetFunctionBasicBlockList(self.handle, count) - for i in xrange(0, count.value): - yield BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i])) - core.BNFreeBasicBlockList(blocks, count.value) - raise StopIteration - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __repr__(self): - arch = self.arch - if arch: - return "<func: %s@%#x>" % (arch.name, self.start) - else: - return "<func: %#x>" % self.start - - def mark_recent_use(self): - core.BNMarkFunctionAsRecentlyUsed(self.handle) - - def get_comment_at(self, addr): - return core.BNGetCommentForAddress(self.handle, addr) - - def set_comment(self, addr, comment): - core.BNSetCommentForAddress(self.handle, addr, comment) - - def get_low_level_il_at(self, arch, addr): - return core.BNGetLowLevelILForInstruction(self.handle, arch.handle, addr) - - def get_low_level_il_exits_at(self, arch, addr): - count = ctypes.c_ulonglong() - exits = core.BNGetLowLevelILExitsForInstruction(self.handle, arch.handle, addr, count) - result = [] - for i in xrange(0, count.value): - result.append(exits[i]) - core.BNFreeLowLevelILInstructionList(exits) - return result - - def get_reg_value_at(self, arch, addr, reg): - if isinstance(reg, str): - reg = arch.regs[reg].index - value = core.BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg) - result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_reg_value_after(self, arch, addr, reg): - if isinstance(reg, str): - reg = arch.regs[reg].index - value = core.BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg) - result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_reg_value_at_low_level_il_instruction(self, i, reg): - if isinstance(reg, str): - reg = self.arch.regs[reg].index - value = core.BNGetRegisterValueAtLowLevelILInstruction(self.handle, i, reg) - result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_reg_value_after_low_level_il_instruction(self, i, reg): - if isinstance(reg, str): - reg = self.arch.regs[reg].index - value = core.BNGetRegisterValueAfterLowLevelILInstruction(self.handle, i, reg) - result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_stack_contents_at(self, arch, addr, offset, size): - value = core.BNGetStackContentsAtInstruction(self.handle, arch.handle, addr, offset, size) - result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_stack_contents_after(self, arch, addr, offset, size): - value = core.BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, offset, size) - result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_stack_contents_at_low_level_il_instruction(self, i, offset, size): - value = core.BNGetStackContentsAtLowLevelILInstruction(self.handle, i, offset, size) - result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_stack_contents_after_low_level_il_instruction(self, i, offset, size): - value = core.BNGetStackContentsAfterInstruction(self.handle, i, offset, size) - result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_parameter_at(self, arch, addr, func_type, i): - if func_type is not None: - func_type = func_type.handle - value = core.BNGetParameterValueAtInstruction(self.handle, arch.handle, addr, func_type, i) - result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_parameter_at_low_level_il_instruction(self, instr, func_type, i): - if func_type is not None: - func_type = func_type.handle - value = core.BNGetParameterValueAtLowLevelILInstruction(self.handle, instr, func_type, i) - result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_regs_read_by(self, arch, addr): - count = ctypes.c_ulonglong() - regs = core.BNGetRegistersReadByInstruction(self.handle, arch.handle, addr, count) - result = [] - for i in xrange(0, count.value): - result.append(arch.get_reg_name(regs[i])) - core.BNFreeRegisterList(regs) - return result - - def get_regs_written_by(self, arch, addr): - count = ctypes.c_ulonglong() - regs = core.BNGetRegistersWrittenByInstruction(self.handle, arch.handle, addr, count) - result = [] - for i in xrange(0, count.value): - result.append(arch.get_reg_name(regs[i])) - core.BNFreeRegisterList(regs) - return result - - def get_stack_vars_referenced_by(self, arch, addr): - count = ctypes.c_ulonglong() - refs = core.BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, count) - result = [] - for i in xrange(0, count.value): - result.append(StackVariableReference(refs[i].sourceOperand, Type(core.BNNewTypeReference(refs[i].type)), - refs[i].name, refs[i].startingOffset, refs[i].referencedOffset)) - core.BNFreeStackVariableReferenceList(refs, count.value) - return result - def get_lifted_il_at(self, arch, addr): - return core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr) - - def get_lifted_il_flag_uses_for_definition(self, i, flag): - if isinstance(flag, str): - flag = self.arch._flags[flag] - count = ctypes.c_ulonglong() - instrs = core.BNGetLiftedILFlagUsesForDefinition(self.handle, i, flag, count) - result = [] - for i in xrange(0, count.value): - result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) - return result - - def get_lifted_il_flag_definitions_for_use(self, i, flag): - if isinstance(flag, str): - flag = self.arch._flags[flag] - count = ctypes.c_ulonglong() - instrs = core.BNGetLiftedILFlagDefinitionsForUse(self.handle, i, flag, count) - result = [] - for i in xrange(0, count.value): - result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) - return result - - def get_flags_read_by_lifted_il_instruction(self, i): - count = ctypes.c_ulonglong() - flags = core.BNGetFlagsReadByLiftedILInstruction(self.handle, i, count) - result = [] - for i in xrange(0, count.value): - result.append(self.arch._flags_by_index[flags[i]]) - core.BNFreeRegisterList(flags) - return result - - def get_flags_written_by_lifted_il_instruction(self, i): - count = ctypes.c_ulonglong() - flags = core.BNGetFlagsWrittenByLiftedILInstruction(self.handle, i, count) - result = [] - for i in xrange(0, count.value): - result.append(self.arch._flags_by_index[flags[i]]) - core.BNFreeRegisterList(flags) - return result - - def create_graph(self): - return FunctionGraph(self._view, core.BNCreateFunctionGraph(self.handle)) - - def apply_imported_types(self, sym): - core.BNApplyImportedTypes(self.handle, sym.handle) - - def apply_auto_discovered_type(self, func_type): - core.BNApplyAutoDiscoveredFunctionType(self.handle, func_type.handle) - - def set_auto_indirect_branches(self, source_arch, source, branches): - branch_list = (core.BNArchitectureAndAddress * len(branches))() - for i in xrange(len(branches)): - branch_list[i].arch = branches[i][0].handle - branch_list[i].address = branches[i][1] - core.BNSetAutoIndirectBranches(self.handle, source_arch.handle, source, branch_list, len(branches)) - - def set_user_indirect_branches(self, source_arch, source, branches): - branch_list = (core.BNArchitectureAndAddress * len(branches))() - for i in xrange(len(branches)): - branch_list[i].arch = branches[i][0].handle - branch_list[i].address = branches[i][1] - core.BNSetUserIndirectBranches(self.handle, source_arch.handle, source, branch_list, len(branches)) - - def get_indirect_branches_at(self, arch, addr): - count = ctypes.c_ulonglong() - branches = core.BNGetIndirectBranchesAt(self.handle, arch.handle, addr, count) - result = [] - for i in xrange(0, count.value): - result.append(IndirectBranchInfo(Architecture(branches[i].sourceArch), branches[i].sourceAddr, Architecture(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) - core.BNFreeIndirectBranchList(branches) - return result - - def get_block_annotations(self, arch, addr): - count = ctypes.c_ulonglong(0) - lines = core.BNGetFunctionBlockAnnotations(self.handle, arch.handle, addr, count) - result = [] - for i in xrange(0, count.value): - tokens = [] - for j in xrange(0, lines[i].count): - token_type = core.BNInstructionTextTokenType_names[lines[i].tokens[j].type] - text = lines[i].tokens[j].text - value = lines[i].tokens[j].value - tokens.append(InstructionTextToken(token_type, text, value)) - result.append(tokens) - core.BNFreeInstructionTextLines(lines, count.value) - return result - -class BasicBlockEdge: - def __init__(self, branch_type, target, arch): - self.type = core.BNBranchType_names[branch_type] - if self.type != "UnresolvedBranch": - self.target = target - self.arch = arch - - def __repr__(self): - if self.type == "UnresolvedBranch": - return "<%s>" % self.type - elif self.arch: - return "<%s: %s@%#x>" % (self.type, self.arch.name, self.target) - else: - return "<%s: %#x>" % (self.type, self.target) - -class BasicBlock(object): - def __init__(self, view, handle): - self.view = view - self.handle = core.handle_of_type(handle, core.BNBasicBlock) - - def __del__(self): - core.BNFreeBasicBlock(self.handle) - - @property - def function(self): - """Basic block function (read-only)""" - func = core.BNGetBasicBlockFunction(self.handle) - if func is None: - return None - return Function(self.view, func) - - @property - def arch(self): - """Basic block architecture (read-only)""" - arch = core.BNGetBasicBlockArchitecture(self.handle) - if arch is None: - return None - return Architecture(arch) - - @property - def start(self): - """Basic block start (read-only)""" - return core.BNGetBasicBlockStart(self.handle) - - @property - def end(self): - """Basic block end (read-only)""" - return core.BNGetBasicBlockEnd(self.handle) - - @property - def length(self): - """Basic block length (read-only)""" - return core.BNGetBasicBlockLength(self.handle) - - @property - def outgoing_edges(self): - """List of basic block outgoing edges (read-only)""" - count = ctypes.c_ulonglong(0) - edges = core.BNGetBasicBlockOutgoingEdges(self.handle, count) - result = [] - for i in xrange(0, count.value): - branch_type = edges[i].type - target = edges[i].target - if edges[i].arch: - arch = Architecture(edges[i].arch) - else: - arch = None - result.append(BasicBlockEdge(branch_type, target, arch)) - core.BNFreeBasicBlockOutgoingEdgeList(edges) - return result - - @property - def has_undetermined_outgoing_edges(self): - """Whether basic block has undetermined outgoing edges (read-only)""" - return core.BNBasicBlockHasUndeterminedOutgoingEdges(self.handle) - - @property - def annotations(self): - """List of automatic annotations for the start of this block (read-only)""" - return self.function.get_block_annotations(self.arch, self.start) - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __len__(self): - return int(core.BNGetBasicBlockLength(self.handle)) - - def __repr__(self): - arch = self.arch - if arch: - return "<block: %s@%#x-%#x>" % (arch.name, self.start, self.end) - else: - return "<block: %#x-%#x>" % (self.start, self.end) - - def __iter__(self): - start = self.start - end = self.end - - idx = start - while idx < end: - data = self.view.read(idx, 16) - inst_info = self.view.arch.get_instruction_info(data, idx) - inst_text = self.view.arch.get_instruction_text(data, idx) - - yield inst_text - idx += inst_info.length - raise StopIteration - - def mark_recent_use(): - core.BNMarkBasicBlockAsRecentlyUsed(self.handle) - -class LowLevelILBasicBlock(BasicBlock): - def __init__(self, view, handle, owner): - super(LowLevelILBasicBlock, self).__init__(view, handle) - self.il_function = owner - - def __iter__(self): - for idx in xrange(self.start, self.end): - yield self.il_function[idx] - raise StopIteration - -class FunctionGraphTextLine: - def __init__(self, addr, tokens): - self.address = addr - self.tokens = tokens - - def __str__(self): - result = "" - for token in self.tokens: - result += token.text - return result - - def __repr__(self): - return "<%#x: %s>" % (self.address, str(self)) - -class FunctionGraphEdge: - def __init__(self, branch_type, arch, target, points): - self.type = branch_type - self.arch = arch - self.target = target - self.points = points - - def __repr__(self): - if self.arch: - return "<%s: %s@%#x>" % (self.type, self.arch.name, self.target) - return "<%s: %#x>" % (self.type, self.target) - -class FunctionGraphBlock(object): - def __init__(self, handle): - self.handle = handle - - def __del__(self): - core.BNFreeFunctionGraphBlock(self.handle) - - @property - def arch(self): - """Function graph block architecture (read-only)""" - arch = core.BNGetFunctionGraphBlockArchitecture(self.handle) - if arch is None: - return None - return Architecture(arch) - - @property - def start(self): - """Function graph block start (read-only)""" - return core.BNGetFunctionGraphBlockStart(self.handle) - - @property - def end(self): - """Function graph block end (read-only)""" - return core.BNGetFunctionGraphBlockEnd(self.handle) - - @property - def x(self): - """Function graph block X (read-only)""" - return core.BNGetFunctionGraphBlockX(self.handle) - - @property - def y(self): - """Function graph block Y (read-only)""" - return core.BNGetFunctionGraphBlockY(self.handle) - - @property - def width(self): - """Function graph block width (read-only)""" - return core.BNGetFunctionGraphBlockWidth(self.handle) - - @property - def height(self): - """Function graph block height (read-only)""" - return core.BNGetFunctionGraphBlockHeight(self.handle) - - @property - def lines(self): - """Function graph block list of lines (read-only)""" - count = ctypes.c_ulonglong() - lines = core.BNGetFunctionGraphBlockLines(self.handle, count) - result = [] - for i in xrange(0, count.value): - addr = lines[i].addr - tokens = [] - for j in xrange(0, lines[i].count): - token_type = core.BNInstructionTextTokenType_names[lines[i].tokens[j].type] - text = lines[i].tokens[j].text - value = lines[i].tokens[j].value - tokens.append(InstructionTextToken(token_type, text, value)) - result.append(FunctionGraphTextLine(addr, tokens)) - core.BNFreeFunctionGraphBlockLines(lines, count.value) - return result - - @property - def outgoing_edges(self): - """Function graph block list of outgoing edges (read-only)""" - count = ctypes.c_ulonglong() - edges = core.BNGetFunctionGraphBlockOutgoingEdges(self.handle, count) - result = [] - for i in xrange(0, count.value): - branch_type = core.BNBranchType_names[edges[i].type] - target = edges[i].target - arch = None - if edges[i].arch is not None: - arch = Architecture(edges[i].arch) - points = [] - for j in xrange(0, edges[i].pointCount): - points.append((edges[i].points[j].x, edges[i].points[j].y)) - result.append(FunctionGraphEdge(branch_type, arch, target, points)) - core.BNFreeFunctionGraphBlockOutgoingEdgeList(edges, count.value) - return result - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __repr__(self): - arch = self.arch - if arch: - return "<graph block: %s@%#x-%#x>" % (arch.name, self.start, self.end) - else: - return "<graph block: %#x-%#x>" % (self.start, self.end) - -class FunctionGraph(object): - def __init__(self, view, handle): - self.view = view - self.handle = handle - self._on_complete = None - self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._complete) - - def __del__(self): - self.abort() - core.BNFreeFunctionGraph(self.handle) - - @property - def function(self): - """Function for a function graph(read-only)""" - func = core.BNGetFunctionForFunctionGraph(self.handle) - if func is None: - return None - return Function(self.view, func) - - @property - def complete(self): - """Whether function graph layout is complete (read-only)""" - return core.BNIsFunctionGraphLayoutComplete(self.handle) - - @property - def type(self): - """Function graph type (read-only)""" - return core.BNFunctionGraphType_names[core.BNGetFunctionGraphType(self.handle)] - - @property - def blocks(self): - """List of basic blocks in function (read-only)""" - count = ctypes.c_ulonglong() - blocks = core.BNGetFunctionGraphBlocks(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]))) - core.BNFreeFunctionGraphBlockList(blocks, count.value) - return result - - @property - def width(self): - """Function graph width (read-only)""" - return core.BNGetFunctionGraphWidth(self.handle) - - @property - def height(self): - """Function graph height (read-only)""" - return core.BNGetFunctionGraphHeight(self.handle) - - @property - def horizontal_block_margin(self): - return core.BNGetHorizontalFunctionGraphBlockMargin(self.handle) - - @horizontal_block_margin.setter - def horizontal_block_margin(self, value): - core.BNSetFunctionGraphBlockMargins(self.handle, value, self.vertical_block_margin) - - @property - def vertical_block_margin(self): - return core.BNGetVerticalFunctionGraphBlockMargin(self.handle) - - @vertical_block_margin.setter - def vertical_block_margin(self, value): - core.BNSetFunctionGraphBlockMargins(self.handle, self.horizontal_block_margin, value) - - @property - def max_symbol_width(self): - return core.BNGetFunctionGraphMaximumSymbolWidth(self.handle) - - @max_symbol_width.setter - def max_symbol_width(self, value): - core.BNSetFunctionGraphMaximumSymbolWidth(self.handle, value) - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __repr__(self): - return "<graph of %s>" % repr(self.function) - - def _complete(self, ctxt): - try: - if self._on_complete is not None: - self._on_complete() - except: - log_error(traceback.format_exc()) - - def layout(self, graph_type = core.NormalFunctionGraph): - if isinstance(graph_type, str): - graph_type = core.BNFunctionGraphType_by_name[graph_type] - core.BNStartFunctionGraphLayout(self.handle, graph_type) - - def _wait_complete(self): - self._wait_cond.acquire() - self._wait_cond.notify() - self._wait_cond.release() - - def layout_and_wait(self, graph_type = core.NormalFunctionGraph): - self._wait_cond = threading.Condition() - self.on_complete(self._wait_complete) - self.layout(graph_type) - - self._wait_cond.acquire() - while not self.complete: - self._wait_cond.wait() - self._wait_cond.release() - - def on_complete(self, callback): - self._on_complete = callback - core.BNSetFunctionGraphCompleteCallback(self.handle, None, self._cb) - - def abort(self): - core.BNAbortFunctionGraph(self.handle) - - def get_blocks_in_region(self, left, top, right, bottom): - count = ctypes.c_ulonglong() - blocks = core.BNGetFunctionGraphBlocksInRegion(self.handle, left, top, right, bottom, count) - result = [] - for i in xrange(0, count.value): - result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]))) - core.BNFreeFunctionGraphBlockList(blocks, count.value) - return result - - def is_option_set(self, option): - if isinstance(option, str): - option = core.BNFunctionGraphOption_by_name(option) - return core.BNIsFunctionGraphOptionSet(self.handle, option) - - def set_option(self, option, state = True): - if isinstance(option, str): - option = core.BNFunctionGraphOption_by_name(option) - core.BNSetFunctionGraphOption(self.handle, option, state) - -class RegisterInfo: - def __init__(self, full_width_reg, size, offset = 0, extend = core.NoExtend, index = None): - self.full_width_reg = full_width_reg - self.offset = offset - self.size = size - self.extend = extend - self.index = index - - def __repr__(self): - if (self.extend == core.ZeroExtendToFullWidth) or (self.extend == "ZeroExtendToFullWidth"): - extend = ", zero extend" - elif (self.extend == core.SignExtendToFullWidth) or (self.extend == "SignExtendToFullWidth"): - extend = ", sign extend" - else: - extend = "" - return "<reg: size %d, offset %d in %s%s>" % (self.size, self.offset, self.full_width_reg, extend) - -class InstructionBranch: - def __init__(self, branch_type, target = 0, arch = None): - self.type = branch_type - self.target = target - self.arch = arch - - def __repr__(self): - branch_type = self.type - if not isinstance(branch_type, str): - branch_type = core.BNBranchType_names[branch_type] - if self.arch is not None: - return "<%s: %s@%#x>" % (branch_type, self.arch.name, self.target) - return "<%s: %#x>" % (branch_type, self.target) - -class InstructionInfo: - def __init__(self): - self.length = 0 - self.branch_delay = False - self.branches = [] - - def add_branch(self, branch_type, target = 0, arch = None): - self.branches.append(InstructionBranch(branch_type, target, arch)) - - def __repr__(self): - branch_delay = "" - if self.branch_delay: - branch_delay = ", delay slot" - return "<instr: %d bytes%s, %s>" % (self.length, branch_delay, repr(self.branches)) - -class InstructionTextToken: - def __init__(self, token_type, text, value = 0): - self.type = token_type - self.text = text - self.value = value - - def __str__(self): - return self.text - - def __repr__(self): - return repr(self.text) - -class _ArchitectureMetaClass(type): - @property - def list(self): - """Architecture list (read-only)""" - _init_plugins() - count = ctypes.c_ulonglong() - archs = core.BNGetArchitectureList(count) - result = [] - for i in xrange(0, count.value): - result.append(Architecture(archs[i])) - core.BNFreeArchitectureList(archs) - return result - - def __getitem__(cls, name): - _init_plugins() - arch = core.BNGetArchitectureByName(name) - if arch is None: - raise KeyError, "'%s' is not a valid architecture" % str(name) - return Architecture(arch) - - def register(cls): - _init_plugins() - if cls.name is None: - raise ValueError, "architecture 'name' is not defined" - arch = cls() - cls._registered_cb = arch._cb - arch.handle = core.BNRegisterArchitecture(cls.name, arch._cb) - - def __setattr__(self, name, value): - try: - type.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - -class Architecture(object): - name = None - endianness = core.LittleEndian - address_size = 8 - default_int_size = 4 - regs = {} - stack_pointer = None - link_reg = None - flags = [] - flag_write_types = [] - flag_roles = {} - flags_required_for_flag_condition = {} - flags_written_by_flag_write_type = {} - __metaclass__ = _ArchitectureMetaClass - - def __init__(self, handle = None): - if handle is not None: - self.handle = core.handle_of_type(handle, core.BNArchitecture) - self.__dict__["name"] = core.BNGetArchitectureName(self.handle) - self.__dict__["endianness"] = core.BNEndianness_names[core.BNGetArchitectureEndianness(self.handle)] - self.__dict__["address_size"] = core.BNGetArchitectureAddressSize(self.handle) - self.__dict__["default_int_size"] = core.BNGetArchitectureDefaultIntegerSize(self.handle) - self.__dict__["stack_pointer"] = core.BNGetArchitectureRegisterName(self.handle, - core.BNGetArchitectureStackPointerRegister(self.handle)) - self.__dict__["link_reg"] = core.BNGetArchitectureRegisterName(self.handle, - core.BNGetArchitectureLinkRegister(self.handle)) - - count = ctypes.c_ulonglong() - regs = core.BNGetAllArchitectureRegisters(self.handle, count) - self.__dict__["regs"] = {} - for i in xrange(0, count.value): - name = core.BNGetArchitectureRegisterName(self.handle, regs[i]) - info = core.BNGetArchitectureRegisterInfo(self.handle, regs[i]) - full_width_reg = core.BNGetArchitectureRegisterName(self.handle, info.fullWidthRegister) - self.regs[name] = RegisterInfo(full_width_reg, info.size, info.offset, - core.BNImplicitRegisterExtend_names[info.extend], regs[i]) - core.BNFreeRegisterList(regs) - - count = ctypes.c_ulonglong() - flags = core.BNGetAllArchitectureFlags(self.handle, count) - self._flags = {} - self._flags_by_index = {} - self.__dict__["flags"] = [] - for i in xrange(0, count.value): - name = core.BNGetArchitectureFlagName(self.handle, flags[i]) - self._flags[name] = flags[i] - self._flags_by_index[flags[i]] = name - self.flags.append(name) - core.BNFreeRegisterList(flags) - - count = ctypes.c_ulonglong() - types = core.BNGetAllArchitectureFlagWriteTypes(self.handle, count) - self._flag_write_types = {} - self._flag_write_types_by_index = {} - self.__dict__["flag_write_types"] = [] - for i in xrange(0, count.value): - name = core.BNGetArchitectureFlagWriteTypeName(self.handle, types[i]) - self._flag_write_types[name] = types[i] - self._flag_write_types_by_index[types[i]] = name - self.flag_write_types.append(name) - core.BNFreeRegisterList(types) - - self._flag_roles = {} - self.__dict__["flag_roles"] = {} - for flag in self.__dict__["flags"]: - role = core.BNGetArchitectureFlagRole(self.handle, self._flags[flag]) - self.__dict__["flag_roles"][flag] = role - self._flag_roles[self._flags[flag]] = role - - self._flags_required_for_flag_condition = {} - self.__dict__["flags_required_for_flag_condition"] = {} - for cond in core.BNLowLevelILFlagCondition_names.keys(): - count = ctypes.c_ulonglong() - flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, count) - flag_indexes = [] - flag_names = [] - for i in xrange(0, count.value): - flag_indexes.append(flags[i]) - flag_names.append(self._flags_by_index[flags[i]]) - core.BNFreeRegisterList(flags) - self._flags_required_for_flag_condition[cond] = flag_indexes - self.__dict__["flags_required_for_flag_condition"][cond] = flag_names - - self._flags_written_by_flag_write_type = {} - self.__dict__["flags_written_by_flag_write_type"] = {} - for write_type in self.flag_write_types: - count = ctypes.c_ulonglong() - flags = core.BNGetArchitectureFlagsWrittenByFlagWriteType(self.handle, - self._flag_write_types[write_type], count) - flag_indexes = [] - flag_names = [] - for i in xrange(0, count.value): - flag_indexes.append(flags[i]) - flag_names.append(self._flags_by_index[flags[i]]) - core.BNFreeRegisterList(flags) - self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flag_indexes - self.__dict__["flags_written_by_flag_write_type"][write_type] = flag_names - else: - _init_plugins() - self._cb = core.BNCustomArchitecture() - self._cb.context = 0 - self._cb.init = self._cb.init.__class__(self._init) - self._cb.getEndianness = self._cb.getEndianness.__class__(self._get_endianness) - self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size) - self._cb.getDefaultIntegerSize = self._cb.getDefaultIntegerSize.__class__(self._get_default_integer_size) - self._cb.getInstructionInfo = self._cb.getInstructionInfo.__class__(self._get_instruction_info) - self._cb.getInstructionText = self._cb.getInstructionText.__class__(self._get_instruction_text) - self._cb.freeInstructionText = self._cb.freeInstructionText.__class__(self._free_instruction_text) - self._cb.getInstructionLowLevelIL = self._cb.getInstructionLowLevelIL.__class__( - self._get_instruction_low_level_il) - self._cb.getRegisterName = self._cb.getRegisterName.__class__(self._get_register_name) - self._cb.getFlagName = self._cb.getFlagName.__class__(self._get_flag_name) - self._cb.getFlagWriteTypeName = self._cb.getFlagWriteTypeName.__class__(self._get_flag_write_type_name) - self._cb.getFullWidthRegisters = self._cb.getFullWidthRegisters.__class__(self._get_full_width_registers) - self._cb.getAllRegisters = self._cb.getAllRegisters.__class__(self._get_all_registers) - self._cb.getAllFlags = self._cb.getAllRegisters.__class__(self._get_all_flags) - self._cb.getAllFlagWriteTypes = self._cb.getAllRegisters.__class__(self._get_all_flag_write_types) - self._cb.getFlagRole = self._cb.getFlagRole.__class__(self._get_flag_role) - self._cb.getFlagsRequiredForFlagCondition = self._cb.getFlagsRequiredForFlagCondition.__class__( - self._get_flags_required_for_flag_condition) - self._cb.getFlagsWrittenByFlagWriteType = self._cb.getFlagsWrittenByFlagWriteType.__class__( - self._get_flags_written_by_flag_write_type) - self._cb.getFlagWriteLowLevelIL = self._cb.getFlagWriteLowLevelIL.__class__( - self._get_flag_write_low_level_il) - self._cb.getFlagConditionLowLevelIL = self._cb.getFlagConditionLowLevelIL.__class__( - self._get_flag_condition_low_level_il) - self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list) - self._cb.getRegisterInfo = self._cb.getRegisterInfo.__class__(self._get_register_info) - self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__( - self._get_stack_pointer_register) - self._cb.getLinkRegister = self._cb.getLinkRegister.__class__(self._get_link_register) - self._cb.assemble = self._cb.assemble.__class__(self._assemble) - self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__( - self._is_never_branch_patch_available) - self._cb.isAlwaysBranchPatchAvailable = self._cb.isAlwaysBranchPatchAvailable.__class__( - self._is_always_branch_patch_available) - self._cb.isInvertBranchPatchAvailable = self._cb.isInvertBranchPatchAvailable.__class__( - self._is_invert_branch_patch_available) - self._cb.isSkipAndReturnZeroPatchAvailable = self._cb.isSkipAndReturnZeroPatchAvailable.__class__( - self._is_skip_and_return_zero_patch_available) - self._cb.isSkipAndReturnValuePatchAvailable = self._cb.isSkipAndReturnValuePatchAvailable.__class__( - self._is_skip_and_return_value_patch_available) - self._cb.convertToNop = self._cb.convertToNop.__class__(self._convert_to_nop) - self._cb.alwaysBranch = self._cb.alwaysBranch.__class__(self._always_branch) - self._cb.invertBranch = self._cb.invertBranch.__class__(self._invert_branch) - self._cb.skipAndReturnValue = self._cb.skipAndReturnValue.__class__(self._skip_and_return_value) - - self._all_regs = {} - self._full_width_regs = {} - self._regs_by_index = {} - self.__dict__["regs"] = self.__class__.regs - reg_index = 0 - for reg in self.regs.keys(): - info = self.regs[reg] - if reg not in self._all_regs: - self._all_regs[reg] = reg_index - self._regs_by_index[reg_index] = reg - self.regs[reg].index = reg_index - reg_index += 1 - if info.full_width_reg not in self._all_regs: - self._all_regs[info.full_width_reg] = reg_index - self._regs_by_index[reg_index] = info.full_width_reg - self.regs[info.full_width_reg].index = reg_index - reg_index += 1 - if info.full_width_reg not in self._full_width_regs: - self._full_width_regs[info.full_width_reg] = self._all_regs[info.full_width_reg] - - self._flags = {} - self._flags_by_index = {} - self.__dict__["flags"] = self.__class__.flags - flag_index = 0 - for flag in self.__class__.flags: - if flag not in self._flags: - self._flags[flag] = flag_index - self._flags_by_index[flag_index] = flag - flag_index += 1 - - self._flag_write_types = {} - self._flag_write_types_by_index = {} - self.__dict__["flag_write_types"] = self.__class__.flag_write_types - write_type_index = 0 - for write_type in self.__class__.flag_write_types: - if write_type not in self._flag_write_types: - self._flag_write_types[write_type] = write_type_index - self._flag_write_types_by_index[write_type_index] = write_type - write_type_index += 1 - - self._flag_roles = {} - self.__dict__["flag_roles"] = self.__class__.flag_roles - for flag in self.__class__.flag_roles.keys(): - role = self.__class__.flag_roles[flag] - if isinstance(role, str): - role = core.BNFlagRole_by_name[role] - self._flag_roles[self._flags[flag]] = role - - self._flags_required_for_flag_condition = {} - self.__dict__["flags_required_for_flag_condition"] = self.__class__.flags_required_for_flag_condition - for cond in self.__class__.flags_required_for_flag_condition.keys(): - flags = [] - for flag in self.__class__.flags_required_for_flag_condition[cond]: - flags.append(self._flags[flag]) - self._flags_required_for_flag_condition[cond] = flags - - self._flags_written_by_flag_write_type = {} - self.__dict__["flags_written_by_flag_write_type"] = self.__class__.flags_written_by_flag_write_type - for write_type in self.__class__.flags_written_by_flag_write_type.keys(): - flags = [] - for flag in self.__class__.flags_written_by_flag_write_type[write_type]: - flags.append(self._flags[flag]) - self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flags - - self._pending_reg_lists = {} - self._pending_token_lists = {} - - @property - def full_width_regs(self): - """List of full width registers (read-only)""" - count = ctypes.c_ulonglong() - regs = core.BNGetFullWidthArchitectureRegisters(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) - core.BNFreeRegisterList(regs) - return result - - @property - def calling_conventions(self): - """Dict of calling conventions (read-only)""" - count = ctypes.c_ulonglong() - cc = core.BNGetArchitectureCallingConventions(self.handle, count) - result = {} - for i in xrange(0, count.value): - obj = CallingConvention(None, core.BNNewCallingConventionReference(cc[i])) - result[obj.name] = obj - core.BNFreeCallingConventionList(cc, count) - return result - - @property - def standalone_platform(self): - """Architecture standalone platform (read-only)""" - pl = core.BNGetArchitectureStandalonePlatform(self.handle) - return Platform(self, pl) - - def __setattr__(self, name, value): - if ((name == "name") or (name == "endianness") or (name == "address_size") or (name == "default_int_size") or - (name == "regs")): - raise AttributeError, "attribute '%s' is read only" % name - else: - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __repr__(self): - return "<arch: %s>" % self.name - - def _init(self, ctxt, handle): - self.handle = handle - - def _get_endianness(self, ctxt): - try: - return self.__class__.endianness - except: - log_error(traceback.format_exc()) - return core.LittleEndian - - def _get_address_size(self, ctxt): - try: - return self.__class__.address_size - except: - log_error(traceback.format_exc()) - return 8 - - def _get_default_integer_size(self, ctxt): - try: - return self.__class__.default_int_size - except: - log_error(traceback.format_exc()) - return 4 - - def _get_instruction_info(self, ctxt, data, addr, max_len, result): - try: - buf = ctypes.create_string_buffer(max_len) - ctypes.memmove(buf, data, max_len) - info = self.perform_get_instruction_info(buf.raw, addr) - if info is None: - return False - result[0].length = info.length - result[0].branchDelay = info.branch_delay - result[0].branchCount = len(info.branches) - for i in xrange(0, len(info.branches)): - if isinstance(info.branches[i].type, str): - result[0].branchType[i] = core.BNBranchType_by_name[info.branches[i].type] - else: - result[0].branchType[i] = info.branches[i].type - result[0].branchTarget[i] = info.branches[i].target - if info.branches[i].arch is None: - result[0].branchArch[i] = None - else: - result[0].branchArch[i] = info.branches[i].arch.handle - return True - except: - log_error(traceback.format_exc()) - return False - - def _get_instruction_text(self, ctxt, data, addr, length, result, count): - try: - buf = ctypes.create_string_buffer(length[0]) - ctypes.memmove(buf, data, length[0]) - info = self.perform_get_instruction_text(buf.raw, addr) - if info is None: - return False - tokens = info[0] - length[0] = info[1] - count[0] = len(tokens) - token_buf = (core.BNInstructionTextToken * len(tokens))() - for i in xrange(0, len(tokens)): - if isinstance(tokens[i].type, str): - token_buf[i].type = BNInstructionTextTokenType_by_name[tokens[i].type] - else: - token_buf[i].type = tokens[i].type - token_buf[i].text = tokens[i].text - token_buf[i].value = tokens[i].value - result[0] = token_buf - ptr = ctypes.cast(token_buf, ctypes.c_void_p) - self._pending_token_lists[ptr.value] = (ptr.value, token_buf) - return True - except: - log_error(traceback.format_exc()) - return False - - def _free_instruction_text(self, tokens, count): - try: - buf = ctypes.cast(tokens, ctypes.c_void_p) - if buf.value not in self._pending_token_lists: - raise ValueError, "freeing token list that wasn't allocated" - del self._pending_token_lists[buf.value] - except: - log_error(traceback.format_exc()) - - def _get_instruction_low_level_il(self, ctxt, data, addr, length, il): - try: - buf = ctypes.create_string_buffer(length[0]) - ctypes.memmove(buf, data, length[0]) - result = self.perform_get_instruction_low_level_il(buf.raw, addr, - LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))) - if result is None: - return False - length[0] = result - return True - except: - log_error(traceback.format_exc()) - return False - - def _get_register_name(self, ctxt, reg): - try: - if reg in self._regs_by_index: - return core.BNAllocString(self._regs_by_index[reg]) - return core.BNAllocString("") - except: - log_error(traceback.format_exc()) - return core.BNAllocString("") - - def _get_flag_name(self, ctxt, flag): - try: - if flag in self._flags_by_index: - return core.BNAllocString(self._flags_by_index[flag]) - return core.BNAllocString("") - except: - log_error(traceback.format_exc()) - return core.BNAllocString("") - - def _get_flag_write_type_name(self, ctxt, write_type): - try: - if write_type in self._flag_write_types_by_index: - return core.BNAllocString(self._flag_write_types_by_index[write_type]) - return core.BNAllocString("") - except: - log_error(traceback.format_exc()) - return core.BNAllocString("") - - def _get_full_width_registers(self, ctxt, count): - try: - regs = self._full_width_regs.values() - count[0] = len(regs) - reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): - reg_buf[i] = regs[i] - result = ctypes.cast(reg_buf, ctypes.c_void_p) - self._pending_reg_lists[result.value] = (result, reg_buf) - return result.value - except: - log_error(traceback.format_exc()) - count[0] = 0 - return None - - def _get_all_registers(self, ctxt, count): - try: - regs = self._regs_by_index.keys() - count[0] = len(regs) - reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): - reg_buf[i] = regs[i] - result = ctypes.cast(reg_buf, ctypes.c_void_p) - self._pending_reg_lists[result.value] = (result, reg_buf) - return result.value - except: - log_error(traceback.format_exc()) - count[0] = 0 - return None - - def _get_all_flags(self, ctxt, count): - try: - flags = self._flags_by_index.keys() - count[0] = len(flags) - flag_buf = (ctypes.c_uint * len(flags))() - for i in xrange(0, len(flags)): - flag_buf[i] = flags[i] - result = ctypes.cast(flag_buf, ctypes.c_void_p) - self._pending_reg_lists[result.value] = (result, flag_buf) - return result.value - except: - log_error(traceback.format_exc()) - count[0] = 0 - return None - - def _get_all_flag_write_types(self, ctxt, count): - try: - types = self._flag_write_types_by_index.keys() - count[0] = len(types) - type_buf = (ctypes.c_uint * len(types))() - for i in xrange(0, len(types)): - type_buf[i] = types[i] - result = ctypes.cast(type_buf, ctypes.c_void_p) - self._pending_reg_lists[result.value] = (result, type_buf) - return result.value - except: - log_error(traceback.format_exc()) - count[0] = 0 - return None - - def _get_flag_role(self, ctxt, flag): - try: - if flag in self._flag_roles: - return self._flag_roles[flag] - return core.SpecialFlagRole - except: - log_error(traceback.format_exc()) - return None - - def _get_flags_required_for_flag_condition(self, ctxt, cond, count): - try: - if cond in self._flags_required_for_flag_condition: - flags = self._flags_required_for_flag_condition[cond] - else: - flags = [] - count[0] = len(flags) - flag_buf = (ctypes.c_uint * len(flags))() - for i in xrange(0, len(flags)): - flag_buf[i] = flags[i] - result = ctypes.cast(flag_buf, ctypes.c_void_p) - self._pending_reg_lists[result.value] = (result, flag_buf) - return result.value - except: - log_error(traceback.format_exc()) - count[0] = 0 - return None - - def _get_flags_written_by_flag_write_type(self, ctxt, write_type, count): - try: - if write_type in self._flags_written_by_flag_write_type: - flags = self._flags_written_by_flag_write_type[write_type] - else: - flags = [] - count[0] = len(flags) - flag_buf = (ctypes.c_uint * len(flags))() - for i in xrange(0, len(flags)): - flag_buf[i] = flags[i] - result = ctypes.cast(flag_buf, ctypes.c_void_p) - self._pending_reg_lists[result.value] = (result, flag_buf) - return result.value - except: - log_error(traceback.format_exc()) - count[0] = 0 - return None - - def _get_flag_write_low_level_il(self, ctxt, op, size, write_type, flag, operands, operand_count, il): - try: - write_type_name = None - if write_type != 0: - write_type_name = self._flag_write_types_by_index[write_type] - flag_name = self._flags_by_index[flag] - operand_list = [] - for i in xrange(operand_count): - if operands[i].constant: - operand_list.append(("const", operands[i].value)) - elif LLIL_REG_IS_TEMP(operands[i].reg): - operand_list.append(("reg", operands[i].reg)) - else: - operand_list.append(("reg", self._regs_by_index[operands[i].reg])) - return self.perform_get_flag_write_low_level_il(op, size, write_type_name, flag_name, operand_list, - LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index - except: - log_error(traceback.format_exc()) - return False - - def _get_flag_condition_low_level_il(self, ctxt, cond, il): - try: - return self.perform_get_flag_condition_low_level_il(cond, - LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index - except: - log_error(traceback.format_exc()) - return 0 - - def _free_register_list(self, ctxt, regs): - try: - buf = ctypes.cast(regs, ctypes.c_void_p) - if buf.value not in self._pending_reg_lists: - raise ValueError, "freeing register list that wasn't allocated" - del self._pending_reg_lists[buf.value] - except: - log_error(traceback.format_exc()) - - def _get_register_info(self, ctxt, reg, result): - try: - if reg not in self._regs_by_index: - result[0].fullWidthRegister = 0 - result[0].offset = 0 - result[0].size = 0 - result[0].extend = core.NoExtend - return - info = self.__class__.regs[self._regs_by_index[reg]] - result[0].fullWidthRegister = self._all_regs[info.full_width_reg] - result[0].offset = info.offset - result[0].size = info.size - if isinstance(info.extend, str): - result[0].extend = core.BNImplicitRegisterExtend_by_name[info.extend] - else: - result[0].extend = info.extend - except: - log_error(traceback.format_exc()) - result[0].fullWidthRegister = 0 - result[0].offset = 0 - result[0].size = 0 - result[0].extend = core.NoExtend - - def _get_stack_pointer_register(self, ctxt): - try: - return self._all_regs[self.__class__.stack_pointer] - except: - log_error(traceback.format_exc()) - return 0 - - def _get_link_register(self, ctxt): - try: - if self.__class__.link_reg is None: - return 0xffffffff - return self._all_regs[self.__class__.link_reg] - except: - log_error(traceback.format_exc()) - return 0 - - def _assemble(self, ctxt, code, addr, result, errors): - try: - data, error_str = self.perform_assemble(code, addr) - errors[0] = core.BNAllocString(str(error_str)) - if data is None: - return False - data = str(data) - buf = ctypes.create_string_buffer(len(data)) - ctypes.memmove(buf, data, len(data)) - core.BNSetDataBufferContents(result, buf, len(data)) - return True - except: - log_error(traceback.format_exc()) - errors[0] = core.BNAllocString("Unhandled exception during assembly.\n") - return False - - def _is_never_branch_patch_available(self, ctxt, data, addr, length): - try: - buf = ctypes.create_string_buffer(length) - ctypes.memmove(buf, data, length) - return self.perform_is_never_branch_patch_available(buf.raw, addr) - except: - log_error(traceback.format_exc()) - return False - - def _is_always_branch_patch_available(self, ctxt, data, addr, length): - try: - buf = ctypes.create_string_buffer(length) - ctypes.memmove(buf, data, length) - return self.perform_is_always_branch_patch_available(buf.raw, addr) - except: - log_error(traceback.format_exc()) - return False - - def _is_invert_branch_patch_available(self, ctxt, data, addr, length): - try: - buf = ctypes.create_string_buffer(length) - ctypes.memmove(buf, data, length) - return self.perform_is_invert_branch_patch_available(buf.raw, addr) - except: - log_error(traceback.format_exc()) - return False - - def _is_skip_and_return_zero_patch_available(self, ctxt, data, addr, length): - try: - buf = ctypes.create_string_buffer(length) - ctypes.memmove(buf, data, length) - return self.perform_is_skip_and_return_zero_patch_available(buf.raw, addr) - except: - log_error(traceback.format_exc()) - return False - - def _is_skip_and_return_value_patch_available(self, ctxt, data, addr, length): - try: - buf = ctypes.create_string_buffer(length) - ctypes.memmove(buf, data, length) - return self.perform_is_skip_and_return_value_patch_available(buf.raw, addr) - except: - log_error(traceback.format_exc()) - return False - - def _convert_to_nop(self, ctxt, data, addr, length): - try: - buf = ctypes.create_string_buffer(length) - ctypes.memmove(buf, data, length) - result = self.perform_convert_to_nop(buf.raw, addr) - if result is None: - return False - result = str(result) - if len(result) > length: - result = result[0:length] - ctypes.memmove(data, result, len(result)) - return True - except: - log_error(traceback.format_exc()) - return False - - def _always_branch(self, ctxt, data, addr, length): - try: - buf = ctypes.create_string_buffer(length) - ctypes.memmove(buf, data, length) - result = self.perform_always_branch(buf.raw, addr) - if result is None: - return False - result = str(result) - if len(result) > length: - result = result[0:length] - ctypes.memmove(data, result, len(result)) - return True - except: - log_error(traceback.format_exc()) - return False - - def _invert_branch(self, ctxt, data, addr, length): - try: - buf = ctypes.create_string_buffer(length) - ctypes.memmove(buf, data, length) - result = self.perform_invert_branch(buf.raw, addr) - if result is None: - return False - result = str(result) - if len(result) > length: - result = result[0:length] - ctypes.memmove(data, result, len(result)) - return True - except: - log_error(traceback.format_exc()) - return False - - def _skip_and_return_value(self, ctxt, data, addr, length, value): - try: - buf = ctypes.create_string_buffer(length) - ctypes.memmove(buf, data, length) - result = self.perform_skip_and_return_value(buf.raw, addr, value) - if result is None: - return False - result = str(result) - if len(result) > length: - result = result[0:length] - ctypes.memmove(data, result, len(result)) - return True - except: - log_error(traceback.format_exc()) - return False - - def perform_get_instruction_low_level_il(self, data, addr, il): - return None - - def perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): - return il.unimplemented() - - def perform_get_flag_condition_low_level_il(self, cond, il): - return il.unimplemented() - - def perform_assemble(self, code, addr): - return None, "Architecture does not implement an assembler.\n" - - def perform_is_never_branch_patch_available(self, data, addr): - return False - - def perform_is_always_branch_patch_available(self, data, addr): - return False - - def perform_is_invert_branch_patch_available(self, data, addr): - return False - - def perform_is_skip_and_return_zero_patch_available(self, data, addr): - return False - - def perform_is_skip_and_return_value_patch_available(self, data, addr): - return False - - def perform_convert_to_nop(self, data, addr): - return None - - def perform_always_branch(self, data, addr): - return None - - def perform_invert_branch(self, data, addr): - return None - - def perform_skip_and_return_value(self, data, addr, value): - return None - - def get_instruction_info(self, data, addr): - info = core.BNInstructionInfo() - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - if not core.BNGetInstructionInfo(self.handle, buf, addr, len(data), info): - return None - result = InstructionInfo() - result.length = info.length - result.branch_delay = info.branchDelay - for i in xrange(0, info.branchCount): - branch_type = core.BNBranchType_names[info.branchType[i]] - target = info.branchTarget[i] - if info.branchArch[i]: - arch = Architecture(info.branchArch[i]) - else: - arch = None - result.add_branch(branch_type, target, arch) - return result - - def get_instruction_text(self, data, addr): - data = str(data) - count = ctypes.c_ulonglong() - length = ctypes.c_ulonglong() - length.value = len(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - tokens = ctypes.POINTER(core.BNInstructionTextToken)() - if not core.BNGetInstructionText(self.handle, buf, addr, length, tokens, count): - return None, 0 - result = [] - for i in xrange(0, count.value): - token_type = core.BNInstructionTextTokenType_names[tokens[i].type] - text = tokens[i].text - value = tokens[i].value - result.append(InstructionTextToken(token_type, text, value)) - core.BNFreeInstructionText(tokens, count.value) - return result, length.value - - def get_instruction_low_level_il(self, data, addr, il): - data = str(data) - length = ctypes.c_ulonglong() - length.value = len(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - core.BNGetInstructionLowLevelIL(self.handle, buf, addr, length, il.handle) - return length.value - - def get_reg_name(self, reg): - return core.BNGetArchitectureRegisterName(self.handle, reg) - - def get_flag_name(self, flag): - return core.BNGetArchitectureFlagName(self.handle, flag) - - def get_flag_write_type_name(self, write_type): - return core.BNGetArchitectureFlagWriteTypeName(self.handle, write_type) - - def get_flag_by_name(self, flag): - return self._flags[flag] - - def get_flag_write_type_by_name(self, write_type): - return self._flag_write_types[write_type] - - def get_flag_write_low_level_il(self, op, size, write_type, operands, il): - operand_list = (core.BNRegisterOrConstant * len(operands))() - for i in xrange(len(operands)): - if isinstance(operands[i], str): - operand_list[i].constant = False - operand_list[i].reg = self._flags[operands[i]] - else: - operand_list[i].constant = True - operand_list[i].value = operands[i] - return core.BNGetArchitectureFlagWriteLowLevelIL(self.handle, op, size, self._flag_write_types[write_type], - operand_list, len(operand_list), il.handle) - - def get_default_flag_write_low_level_il(self, op, size, write_type, operands, il): - operand_list = (core.BNRegisterOrConstant * len(operands))() - for i in xrange(len(operands)): - if isinstance(operands[i], str): - operand_list[i].constant = False - operand_list[i].reg = self._flags[operands[i]] - else: - operand_list[i].constant = True - operand_list[i].value = operands[i] - return core.BNGetDefaultArchitectureFlagWriteLowLevelIL(self.handle, op, size, self._flag_write_types[write_type], - operand_list, len(operand_list), il.handle) - - def get_flag_condition_low_level_il(self, cond, il): - return core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle) - - def get_modified_regs_on_write(self, reg): - reg = core.BNGetArchitectureRegisterByName(self.handle, str(reg)) - count = ctypes.c_ulonglong() - regs = core.BNGetModifiedArchitectureRegistersOnWrite(self.handle, reg, count) - result = [] - for i in xrange(0, count.value): - result.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) - core.BNFreeRegisterList(regs) - return result - - def assemble(self, code, addr = 0): - result = DataBuffer() - errors = ctypes.c_char_p() - if not core.BNAssemble(self.handle, code, addr, result.handle, errors): - return None, errors.value - return str(result), errors.value - - def is_never_branch_patch_available(self, data, addr): - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - return core.BNIsArchitectureNeverBranchPatchAvailable(self.handle, buf, addr, len(data)) - - def is_always_branch_patch_available(self, data, addr): - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - return core.BNIsArchitectureAlwaysBranchPatchAvailable(self.handle, buf, addr, len(data)) - - def is_invert_branch_patch_available(self, data, addr): - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - return core.BNIsArchitectureInvertBranchPatchAvailable(self.handle, buf, addr, len(data)) - - def is_skip_and_return_zero_patch_available(self, data, addr): - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - return core.BNIsArchitectureSkipAndReturnZeroPatchAvailable(self.handle, buf, addr, len(data)) - - def is_skip_and_return_value_patch_available(self, data, addr): - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - return core.BNIsArchitectureSkipAndReturnValuePatchAvailable(self.handle, buf, addr, len(data)) - - def convert_to_nop(self, data, addr): - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - if not core.BNArchitectureConvertToNop(self.handle, buf, addr, len(data)): - return None - result = ctypes.create_string_buffer(len(data)) - ctypes.memmove(result, buf, len(data)) - return result.raw - - def always_branch(self, data, addr): - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - if not core.BNArchitectureAlwaysBranch(self.handle, buf, addr, len(data)): - return None - result = ctypes.create_string_buffer(len(data)) - ctypes.memmove(result, buf, len(data)) - return result.raw - - def invert_branch(self, data, addr): - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - if not core.BNArchitectureInvertBranch(self.handle, buf, addr, len(data)): - return None - result = ctypes.create_string_buffer(len(data)) - ctypes.memmove(result, buf, len(data)) - return result.raw - - def skip_and_return_value(self, data, addr, value): - data = str(data) - buf = (ctypes.c_ubyte * len(data))() - ctypes.memmove(buf, data, len(data)) - if not core.BNArchitectureSkipAndReturnValue(self.handle, buf, addr, len(data), value): - return None - result = ctypes.create_string_buffer(len(data)) - ctypes.memmove(result, buf, len(data)) - return result.raw - - def is_view_type_constant_defined(self, type_name, const_name): - return core.BNIsBinaryViewTypeArchitectureConstantDefined(self.handle, type_name, const_name) - - def get_view_type_constant(self, type_name, const_name, default_value = 0): - return core.BNGetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, default_value) - - def set_view_type_constant(self, type_name, const_name, value): - core.BNSetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, value) - - def parse_types_from_source(self, source, filename = None, include_dirs = []): - if filename is None: - filename = "input" - dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) - parse = core.BNTypeParserResult() - errors = ctypes.c_char_p() - result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, len(include_dirs)) - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - if not result: - return (None, error_str) - types = {} - variables = {} - functions = {} - for i in xrange(0, parse.typeCount): - types[parse.types[i].name] = Type(core.BNNewTypeReference(parse.types[i].type)) - for i in xrange(0, parse.variableCount): - variables[parse.variables[i].name] = Type(core.BNNewTypeReference(parse.variables[i].type)) - for i in xrange(0, parse.functionCount): - functions[parse.functions[i].name] = Type(core.BNNewTypeReference(parse.functions[i].type)) - return (TypeParserResult(types, variables, functions), error_str) - - def parse_types_from_source_file(self, filename, include_dirs = []): - dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) - parse = core.BNTypeParserResult() - errors = ctypes.c_char_p() - result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, len(include_dirs)) - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - if not result: - return (None, error_str) - types = {} - variables = {} - functions = {} - for i in xrange(0, parse.typeCount): - types[parse.types[i].name] = Type(core.BNNewTypeReference(parse.types[i].type)) - for i in xrange(0, parse.variableCount): - variables[parse.variables[i].name] = Type(core.BNNewTypeReference(parse.variables[i].type)) - for i in xrange(0, parse.functionCount): - functions[parse.functions[i].name] = Type(core.BNNewTypeReference(parse.functions[i].type)) - return (TypeParserResult(types, variables, functions), error_str) - - def register_calling_convention(self, cc): - core.BNRegisterCallingConvention(self.handle, cc.handle) - -class ReferenceSource: - def __init__(self, func, arch, addr): - self.function = func - self.arch = arch - self.address = addr - - def __repr__(self): - if self.arch: - return "<ref: %s@%#x>" % (self.arch.name, self.address) - else: - return "<ref: %#x>" % self.address - -class LowLevelILLabel: - def __init__(self, handle = None): - if handle is None: - self.handle = (core.BNLowLevelILLabel * 1)() - core.BNLowLevelILInitLabel(self.handle) - else: - self.handle = handle - -class LowLevelILInstruction(object): - ILOperations = { - core.LLIL_NOP: [], - core.LLIL_SET_REG: [("dest", "reg"), ("src", "expr")], - core.LLIL_SET_REG_SPLIT: [("hi", "reg"), ("lo", "reg"), ("src", "expr")], - core.LLIL_SET_FLAG: [("dest", "flag"), ("src", "expr")], - core.LLIL_LOAD: [("src", "expr")], - core.LLIL_STORE: [("dest", "expr"), ("src", "expr")], - core.LLIL_PUSH: [("src", "expr")], - core.LLIL_POP: [], - core.LLIL_REG: [("src", "reg")], - core.LLIL_CONST: [("value", "int")], - core.LLIL_FLAG: [("src", "flag")], - core.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")], - core.LLIL_ADD: [("left", "expr"), ("right", "expr")], - core.LLIL_ADC: [("left", "expr"), ("right", "expr")], - core.LLIL_SUB: [("left", "expr"), ("right", "expr")], - core.LLIL_SBB: [("left", "expr"), ("right", "expr")], - core.LLIL_AND: [("left", "expr"), ("right", "expr")], - core.LLIL_OR: [("left", "expr"), ("right", "expr")], - core.LLIL_XOR: [("left", "expr"), ("right", "expr")], - core.LLIL_LSL: [("left", "expr"), ("right", "expr")], - core.LLIL_LSR: [("left", "expr"), ("right", "expr")], - core.LLIL_ASR: [("left", "expr"), ("right", "expr")], - core.LLIL_ROL: [("left", "expr"), ("right", "expr")], - core.LLIL_RLC: [("left", "expr"), ("right", "expr")], - core.LLIL_ROR: [("left", "expr"), ("right", "expr")], - core.LLIL_RRC: [("left", "expr"), ("right", "expr")], - core.LLIL_MUL: [("left", "expr"), ("right", "expr")], - core.LLIL_MULU_DP: [("left", "expr"), ("right", "expr")], - core.LLIL_MULS_DP: [("left", "expr"), ("right", "expr")], - core.LLIL_DIVU: [("left", "expr"), ("right", "expr")], - core.LLIL_DIVU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], - core.LLIL_DIVS: [("left", "expr"), ("right", "expr")], - core.LLIL_DIVS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], - core.LLIL_MODU: [("left", "expr"), ("right", "expr")], - core.LLIL_MODU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], - core.LLIL_MODS: [("left", "expr"), ("right", "expr")], - core.LLIL_MODS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], - core.LLIL_NEG: [("src", "expr")], - core.LLIL_NOT: [("src", "expr")], - core.LLIL_SX: [("src", "expr")], - core.LLIL_ZX: [("src", "expr")], - core.LLIL_JUMP: [("dest", "expr")], - core.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], - core.LLIL_CALL: [("dest", "expr")], - core.LLIL_RET: [("dest", "expr")], - core.LLIL_NORET: [], - core.LLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], - core.LLIL_GOTO: [("dest", "int")], - core.LLIL_FLAG_COND: [("condition", "cond")], - core.LLIL_CMP_E: [("left", "expr"), ("right", "expr")], - core.LLIL_CMP_NE: [("left", "expr"), ("right", "expr")], - core.LLIL_CMP_SLT: [("left", "expr"), ("right", "expr")], - core.LLIL_CMP_ULT: [("left", "expr"), ("right", "expr")], - core.LLIL_CMP_SLE: [("left", "expr"), ("right", "expr")], - core.LLIL_CMP_ULE: [("left", "expr"), ("right", "expr")], - core.LLIL_CMP_SGE: [("left", "expr"), ("right", "expr")], - core.LLIL_CMP_UGE: [("left", "expr"), ("right", "expr")], - core.LLIL_CMP_SGT: [("left", "expr"), ("right", "expr")], - core.LLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], - core.LLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], - core.LLIL_BOOL_TO_INT: [("src", "expr")], - core.LLIL_SYSCALL: [], - core.LLIL_BP: [], - core.LLIL_TRAP: [("value", "int")], - core.LLIL_UNDEF: [], - core.LLIL_UNIMPL: [], - core.LLIL_UNIMPL_MEM: [("src", "expr")] - } - - def __init__(self, func, expr_index, instr_index = None): - instr = core.BNGetLowLevelILByIndex(func.handle, expr_index) - self.function = func - self.expr_index = expr_index - self.instr_index = instr_index - self.operation = instr.operation - self.operation_name = core.BNLowLevelILOperation_names[instr.operation] - self.size = instr.size - self.address = instr.address - self.source_operand = instr.sourceOperand - if instr.flags == 0: - self.flags = None - else: - self.flags = func.arch.get_flag_write_type_name(instr.flags) - if self.source_operand == 0xffffffff: - self.source_operand = None - operands = LowLevelILInstruction.ILOperations[instr.operation] - self.operands = [] - for i in xrange(0, len(operands)): - name, operand_type = operands[i] - if operand_type == "int": - value = instr.operands[i] - elif operand_type == "expr": - value = LowLevelILInstruction(func, instr.operands[i]) - elif operand_type == "reg": - if (instr.operands[i] & 0x80000000) != 0: - value = instr.operands[i] - else: - value = func.arch.get_reg_name(instr.operands[i]) - elif operand_type == "flag": - value = func.arch.get_flag_name(instr.operands[i]) - elif operand_type == "cond": - value = core.BNLowLevelILFlagCondition_names[instr.operands[i]] - elif operand_type == "int_list": - count = ctypes.c_ulonglong() - operands = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) - value = [] - for i in xrange(count.value): - value.append(operands[i]) - core.BNLowLevelILFreeOperandList(operands) - self.operands.append(value) - self.__dict__[name] = value - - def __str__(self): - tokens = self.tokens - if tokens is None: - return "invalid" - result = "" - for token in tokens: - result += token.text - return result - - def __repr__(self): - return "<il: %s>" % str(self) - - @property - def tokens(self): - """LLIL tokens (read-only)""" - count = ctypes.c_ulonglong() - tokens = ctypes.POINTER(core.BNInstructionTextToken)() - if (self.instr_index is not None) and (self.function.source_function is not None): - if not core.BNGetLowLevelILInstructionText(self.function.handle, self.function.source_function.handle, - self.function.arch.handle, self.instr_index, tokens, count): - return None - else: - if not core.BNGetLowLevelILExprText(self.function.handle, self.function.arch.handle, - self.expr_index, tokens, count): - return None - result = [] - for i in xrange(0, count.value): - token_type = core.BNInstructionTextTokenType_names[tokens[i].type] - text = tokens[i].text - value = tokens[i].value - result.append(InstructionTextToken(token_type, text, value)) - core.BNFreeInstructionText(tokens, count.value) - return result - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - -class LowLevelILExpr: - def __init__(self, index): - self.index = index - -class LowLevelILFunction(object): - def __init__(self, arch, handle = None, source_func = None): - self.arch = arch - self.source_function = source_func - if handle is not None: - self.handle = core.handle_of_type(handle, core.BNLowLevelILFunction) - else: - self.handle = core.BNCreateLowLevelILFunction(arch.handle) - - def __del__(self): - core.BNFreeLowLevelILFunction(self.handle) - - @property - def current_address(self): - return core.BNLowLevelILGetCurrentAddress(self.handle) - - @current_address.setter - def current_address(self, value): - core.BNLowLevelILSetCurrentAddress(self.handle, value) - - @property - def temp_reg_count(self): - """Number of temporary registers (read-only)""" - return core.BNGetLowLevelILTemporaryRegisterCount(self.handle) - - @property - def temp_flag_count(self): - """Number of temporary flags (read-only)""" - return core.BNGetLowLevelILTemporaryFlagCount(self.handle) - - @property - def basic_blocks(self): - """Low level IL basic blocks (read-only)""" - count = ctypes.c_ulonglong() - blocks = core.BNGetLowLevelILBasicBlockList(self.handle, count) - result = [] - view = None - if self.source_function is not None: - view = self.source_function.view - for i in xrange(0, count.value): - result.append(LowLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)) - core.BNFreeBasicBlockList(blocks, count.value) - return result - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __len__(self): - return int(core.BNGetLowLevelILInstructionCount(self.handle)) - - def __getitem__(self, i): - if isinstance(i, slice) or isinstance(i, tuple): - raise IndexError, "expected integer instruction index" - if isinstance(i, LowLevelILExpr): - return LowLevelILInstruction(self, i.index) - if (i < 0) or (i >= len(self)): - raise IndexError, "index out of range" - return LowLevelILInstruction(self, core.BNGetLowLevelILIndexForInstruction(self.handle, i), i) - - def __setitem__(self, i): - raise IndexError, "instruction modification not implemented" - - def __iter__(self): - count = ctypes.c_ulonglong() - blocks = core.BNGetLowLevelILBasicBlockList(self.handle, count) - result = [] - view = None - if self.source_function is not None: - view = self.source_function.view - for i in xrange(0, count.value): - yield LowLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) - core.BNFreeBasicBlockList(blocks, count.value) - raise StopIteration - - def clear_indirect_branches(self): - core.BNLowLevelILClearIndirectBranches(self.handle) - - def set_indirect_branches(self, branches): - branch_list = (core.BNArchitectureAndAddress * len(branches))() - for i in xrange(len(branches)): - branch_list[i].arch = branches[i][0].handle - branch_list[i].address = branches[i][1] - core.BNLowLevelILSetIndirectBranches(self.handle, branch_list, len(branches)) - - def expr(self, operation, a = 0, b = 0, c = 0, d = 0, size = 0, flags = None): - if isinstance(operation, str): - operation = BNLowLevelILOperation_by_name[operation] - if isinstance(flags, str): - flags = self.arch.get_flag_write_type_by_name(flags) - elif flags is None: - flags = 0 - return LowLevelILExpr(core.BNLowLevelILAddExpr(self.handle, operation, size, flags, a, b, c, d)) - - def append(self, expr): - return core.BNLowLevelILAddInstruction(self.handle, expr.index) - - def nop(self): - return self.expr(core.LLIL_NOP) - - def set_reg(self, size, reg, value, flags = 0): - if isinstance(reg, str): - reg = self.arch.regs[reg].index - return self.expr(core.LLIL_SET_REG, reg, value.index, size = size, flags = flags) - - def set_reg_split(self, size, hi, lo, value, flags = 0): - if isinstance(hi, str): - hi = self.arch.regs[hi].index - if isinstance(lo, str): - lo = self.arch.regs[lo].index - return self.expr(core.LLIL_SET_REG_SPLIT, hi, lo, value.index, size = size, flags = flags) - - def set_flag(self, flag, value): - return self.expr(core.LLIL_SET_FLAG, self.arch.get_flag_by_name(flag), value.index) - - def load(self, size, addr): - return self.expr(core.LLIL_LOAD, addr.index, size = size) - - def store(self, size, addr, value): - return self.expr(core.LLIL_STORE, addr.index, value.index, size = size) - - def push(self, size, value): - return self.expr(core.LLIL_PUSH, value.index, size = size) - - def pop(self, size): - return self.expr(core.LLIL_POP, size = size) - - def reg(self, size, reg): - if isinstance(reg, str): - reg = self.arch.regs[reg].index - return self.expr(core.LLIL_REG, reg, size = size) - - def const(self, size, value): - return self.expr(core.LLIL_CONST, value, size = size) - - def flag(self, reg): - return self.expr(core.LLIL_FLAG, self.arch.get_flag_by_name(reg)) - - def flag_bit(self, size, reg, bit): - return self.expr(core.LLIL_FLAG_BIT, self.arch.get_flag_by_name(reg), bit, size = size) - - def add(self, size, a, b, flags = None): - return self.expr(core.LLIL_ADD, a.index, b.index, size = size, flags = flags) - - def add_carry(self, size, a, b, flags = None): - return self.expr(core.LLIL_ADC, a.index, b.index, size = size, flags = flags) - - def sub(self, size, a, b, flags = None): - return self.expr(core.LLIL_SUB, a.index, b.index, size = size, flags = flags) - - def sub_borrow(self, size, a, b, flags = None): - return self.expr(core.LLIL_SBB, a.index, b.index, size = size, flags = flags) - - def and_expr(self, size, a, b, flags = None): - return self.expr(core.LLIL_AND, a.index, b.index, size = size, flags = flags) - - def or_expr(self, size, a, b, flags = None): - return self.expr(core.LLIL_OR, a.index, b.index, size = size, flags = flags) - - def xor_expr(self, size, a, b, flags = None): - return self.expr(core.LLIL_XOR, a.index, b.index, size = size, flags = flags) - - def shift_left(self, size, a, b, flags = None): - return self.expr(core.LLIL_LSL, a.index, b.index, size = size, flags = flags) - - def logical_shift_right(self, size, a, b, flags = None): - return self.expr(core.LLIL_LSR, a.index, b.index, size = size, flags = flags) - - def arith_shift_right(self, size, a, b, flags = None): - return self.expr(core.LLIL_ASR, a.index, b.index, size = size, flags = flags) - - def rotate_left(self, size, a, b, flags = None): - return self.expr(core.LLIL_ROL, a.index, b.index, size = size, flags = flags) - - def rotate_left_carry(self, size, a, b, flags = None): - return self.expr(core.LLIL_RLC, a.index, b.index, size = size, flags = flags) - - def rotate_right(self, size, a, b, flags = None): - return self.expr(core.LLIL_ROR, a.index, b.index, size = size, flags = flags) - - def rotate_right_carry(self, size, a, b, flags = None): - return self.expr(core.LLIL_RRC, a.index, b.index, size = size, flags = flags) - - def mult(self, size, a, b, flags = None): - return self.expr(core.LLIL_MUL, a.index, b.index, size = size, flags = flags) - - def mult_double_prec_signed(self, size, a, b, flags = None): - return self.expr(core.LLIL_MULS_DP, a.index, b.index, size = size, flags = flags) - - def mult_double_prec_unsigned(self, size, a, b, flags = None): - return self.expr(core.LLIL_MULU_DP, a.index, b.index, size = size, flags = flags) - - def div_signed(self, size, a, b, flags = None): - return self.expr(core.LLIL_DIVS, a.index, b.index, size = size, flags = flags) - - def div_double_prec_signed(self, size, hi, lo, b, flags = None): - return self.expr(core.LLIL_DIVS_DP, hi.index, lo.index, b.index, size = size, flags = flags) - - def div_unsigned(self, size, a, b, flags = None): - return self.expr(core.LLIL_DIVS, a.index, b.index, size = size, flags = flags) - - def div_double_prec_unsigned(self, size, hi, lo, b, flags = None): - return self.expr(core.LLIL_DIVS_DP, hi.index, lo.index, b.index, size = size, flags = flags) - - def mod_signed(self, size, a, b, flags = None): - return self.expr(core.LLIL_MODS, a.index, b.index, size = size, flags = flags) - - def mod_double_prec_signed(self, size, hi, lo, b, flags = None): - return self.expr(core.LLIL_MODS_DP, hi.index, lo.index, b.index, size = size, flags = flags) - - def mod_unsigned(self, size, a, b, flags = None): - return self.expr(core.LLIL_MODS, a.index, b.index, size = size, flags = flags) - - def mod_double_prec_unsigned(self, size, hi, lo, b, flags = None): - return self.expr(core.LLIL_MODS_DP, hi.index, lo.index, b.index, size = size, flags = flags) - - def neg_expr(self, size, value, flags = None): - return self.expr(core.LLIL_NEG, value.index, size = size, flags = flags) - - def not_expr(self, size, value, flags = None): - return self.expr(core.LLIL_NOT, value.index, size = size, flags = flags) - - def sign_extend(self, size, value): - return self.expr(core.LLIL_SX, value.index, size = size) - - def zero_extend(self, size, value): - return self.expr(core.LLIL_ZX, value.index, size = size) - - def jump(self, dest): - return self.expr(core.LLIL_JUMP, dest.index) - - def call(self, dest): - return self.expr(core.LLIL_CALL, dest.index) - - def ret(self, dest): - return self.expr(core.LLIL_RET, dest.index) - - def no_ret(self, dest): - return self.expr(core.LLIL_NORET, dest.index) - - def flag_condition(self, cond): - if isinstance(cond, str): - cond = BNLowLevelILFlagCondition_by_name[cond] - return self.expr(core.LLIL_FLAG_COND, cond) - - def compare_equal(self, size, a, b): - return self.expr(core.LLIL_CMP_E, a.index, b.index, size = size) - - def compare_not_equal(self, size, a, b): - return self.expr(core.LLIL_CMP_NE, a.index, b.index, size = size) - - def compare_signed_less_than(self, size, a, b): - return self.expr(core.LLIL_CMP_SLT, a.index, b.index, size = size) - - def compare_unsigned_less_than(self, size, a, b): - return self.expr(core.LLIL_CMP_ULT, a.index, b.index, size = size) - - def compare_signed_less_equal(self, size, a, b): - return self.expr(core.LLIL_CMP_SLE, a.index, b.index, size = size) - - def compare_unsigned_less_equal(self, size, a, b): - return self.expr(core.LLIL_CMP_ULE, a.index, b.index, size = size) - - def compare_signed_greater_equal(self, size, a, b): - return self.expr(core.LLIL_CMP_SGE, a.index, b.index, size = size) - - def compare_unsigned_greater_equal(self, size, a, b): - return self.expr(core.LLIL_CMP_UGE, a.index, b.index, size = size) - - def compare_signed_greater_than(self, size, a, b): - return self.expr(core.LLIL_CMP_SGT, a.index, b.index, size = size) - - def compare_unsigned_greater_than(self, size, a, b): - return self.expr(core.LLIL_CMP_UGT, a.index, b.index, size = size) - - def test_bit(self, size, a, b): - return self.expr(core.LLIL_TEST_BIT, a.index, b.index, size = size) - - def system_call(self): - return self.expr(core.LLIL_SYSCALL) - - def breakpoint(self): - return self.expr(core.LLIL_BP) - - def trap(self, value): - return self.expr(core.LLIL_TRAP, value) - - def undefined(self): - return self.expr(core.LLIL_UNDEF) - - def unimplemented(self): - return self.expr(core.LLIL_UNIMPL) - - def unimplemented_memory_ref(self, size, addr): - return self.expr(core.LLIL_UNIMPL_MEM, addr.index, size = size) - - def goto(self, label): - return LowLevelILExpr(core.BNLowLevelILGoto(self.handle, label.handle)) - - def if_expr(self, operand, t, f): - return LowLevelILExpr(core.BNLowLevelILIf(self.handle, operand.index, t.handle, f.handle)) - - def mark_label(self, label): - core.BNLowLevelILMarkLabel(self.handle, label.handle) - - def add_label_list(self, labels): - label_list = (ctypes.POINTER(BNLowLevelILLabel) * len(labels))() - for i in xrange(len(labels)): - label_list[i] = labels[i].handle - return LowLevelILExpr(core.BNLowLevelILAddLabelList(self.handle, label_list, len(labels))) - - def add_operand_list(self, operands): - operand_list = (ctypes.c_ulonglong * len(operands))() - for i in xrange(len(operands)): - operand_list[i] = operands[i] - return LowLevelILExpr(core.BNLowLevelILAddOperandList(self.handle, operand_list, len(operands))) - - def operand(self, n, expr): - core.BNLowLevelILSetExprSourceOperand(self.handle, expr.index, n) - return expr - - def finalize(self, func = None): - if func is None: - core.BNFinalizeLowLevelILFunction(self.handle, None) - else: - core.BNFinalizeLowLevelILFunction(self.handle, func.handle) - - def add_label_for_address(self, arch, addr): - if arch is not None: - arch = arch.handle - core.BNAddLowLevelILLabelForAddress(self.handle, arch, addr) - - def get_label_for_address(self, arch, addr): - if arch is not None: - arch = arch.handle - label = core.BNGetLowLevelILLabelForAddress(self.handle, arch, addr) - if label is None: - return None - return LowLevelILLabel(label) - -class TypeParserResult: - def __init__(self, types, variables, functions): - self.types = types - self.variables = variables - self.functions = functions - - def __repr__(self): - return "{types: %s, variables: %s, functions: %s}" % (self.types, self.variables, self.functions) - -class _TransformMetaClass(type): - @property - def list(self): - _init_plugins() - count = ctypes.c_ulonglong() - xforms = core.BNGetTransformTypeList(count) - result = [] - for i in xrange(0, count.value): - result.append(Transform(xforms[i])) - core.BNFreeTransformTypeList(xforms) - return result - - def __setattr__(self, name, value): - try: - type.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __getitem__(cls, name): - _init_plugins() - xform = core.BNGetTransformByName(name) - if xform is None: - raise KeyError, "'%s' is not a valid transform" % str(name) - return Transform(xform) - - def register(cls): - _init_plugins() - if cls.name is None: - raise ValueError, "transform 'name' is not defined" - if cls.long_name is None: - cls.long_name = cls.name - if cls.transform_type is None: - raise ValueError, "transform 'transform_type' is not defined" - if cls.group is None: - cls.group = "" - xform = cls(None) - cls._registered_cb = xform._cb - xform.handle = core.BNRegisterTransformType(cls.transform_type, cls.name, cls.long_name, cls.group, xform._cb) - -class TransformParameter: - def __init__(self, name, long_name = None, fixed_length = 0): - self.name = name - if long_name is None: - self.long_name = name - else: - self.long_name = long_name - self.fixed_length = fixed_length - -class Transform: - transform_type = None - name = None - long_name = None - group = None - parameters = [] - _registered_cb = None - __metaclass__ = _TransformMetaClass - - def __init__(self, handle): - if handle is None: - self._cb = core.BNCustomTransform() - self._cb.context = 0 - self._cb.getParameters = self._cb.getParameters.__class__(self._get_parameters) - self._cb.freeParameters = self._cb.freeParameters.__class__(self._free_parameters) - self._cb.decode = self._cb.decode.__class__(self._decode) - self._cb.encode = self._cb.encode.__class__(self._encode) - self._pending_param_lists = {} - self.type = self.__class__.transform_type - if not isinstance(self.type, str): - self.type = core.BNTransformType_names[self.type] - self.name = self.__class__.name - self.long_name = self.__class__.long_name - self.group = self.__class__.group - self.parameters = self.__class__.parameters - else: - self.handle = handle - self.type = core.BNTransformType_names[core.BNGetTransformType(self.handle)] - self.name = core.BNGetTransformName(self.handle) - self.long_name = core.BNGetTransformLongName(self.handle) - self.group = core.BNGetTransformGroup(self.handle) - count = ctypes.c_ulonglong() - params = core.BNGetTransformParameterList(self.handle, count) - self.parameters = [] - for i in xrange(0, count.value): - self.parameters.append(TransformParameter(params[i].name, params[i].longName, params[i].fixedLength)) - core.BNFreeTransformParameterList(params, count.value) - - def __repr__(self): - return "<transform: %s>" % self.name - - def _get_parameters(self, ctxt, count): - try: - count[0] = len(self.parameters) - param_buf = (core.BNTransformParameterInfo * len(self.parameters))() - for i in xrange(0, len(self.parameters)): - param_buf[i].name = self.parameters[i].name - param_buf[i].longName = self.parameters[i].long_name - param_buf[i].fixedLength = self.parameters[i].fixed_length - result = ctypes.cast(param_buf, ctypes.c_void_p) - self._pending_param_lists[result.value] = (result, param_buf) - return result.value - except: - log_error(traceback.format_exc()) - count[0] = 0 - return None - - def _free_parameters(self, params, count): - try: - buf = ctypes.cast(params, ctypes.c_void_p) - if buf.value not in self._pending_param_lists: - raise ValueError, "freeing parameter list that wasn't allocated" - del self._pending_param_lists[buf.value] - except: - log_error(traceback.format_exc()) - - def _decode(self, ctxt, input_buf, output_buf, params, count): - try: - input_obj = DataBuffer(handle = core.BNDuplicateDataBuffer(input_buf)) - param_map = {} - for i in xrange(0, count): - data = DataBuffer(handle = core.BNDuplicateDataBuffer(params[i].value)) - param_map[params[i].name] = str(data) - result = self.perform_decode(str(input_obj), param_map) - if result is None: - return False - result = str(result) - core.BNSetDataBufferContents(output_buf, result, len(result)) - return True - except: - log_error(traceback.format_exc()) - return False - - def _encode(self, ctxt, input_buf, output_buf, params, count): - try: - input_obj = DataBuffer(handle = core.BNDuplicateDataBuffer(input_buf)) - param_map = {} - for i in xrange(0, count): - data = DataBuffer(handle = core.BNDuplicateDataBuffer(params[i].value)) - param_map[params[i].name] = str(data) - result = self.perform_encode(str(input_obj), param_map) - if result is None: - return False - result = str(result) - core.BNSetDataBufferContents(output_buf, result, len(result)) - return True - except: - log_error(traceback.format_exc()) - return False - - def perform_decode(self, data, params): - if self.type == "InvertingTransform": - return perform_encode(data, params) - return None - - def perform_encode(self, data, params): - return None - - def decode(self, input_buf, params = {}): - input_buf = DataBuffer(input_buf) - output_buf = DataBuffer() - keys = params.keys() - param_buf = (core.BNTransformParameter * len(keys))() - param_data = [] - for i in xrange(0, len(keys)): - data = DataBuffer(params[keys[i]]) - param_buf[i].name = keys[i] - param_buf[i].value = data.handle - if not core.BNDecode(self.handle, input_buf.handle, output_buf.handle, param_buf, len(keys)): - return None - return str(output_buf) - - def encode(self, input_buf, params = {}): - input_buf = DataBuffer(input_buf) - output_buf = DataBuffer() - keys = params.keys() - param_buf = (core.BNTransformParameter * len(keys))() - param_data = [] - for i in xrange(0, len(keys)): - data = DataBuffer(params[keys[i]]) - param_buf[i].name = keys[i] - param_buf[i].value = data.handle - if not core.BNEncode(self.handle, input_buf.handle, output_buf.handle, param_buf, len(keys)): - return None - return str(output_buf) - -class FunctionRecognizer: - _instance = None - - def __init__(self): - self._cb = core.BNFunctionRecognizer() - self._cb.context = 0 - self._cb.recognizeLowLevelIL = self._cb.recognizeLowLevelIL.__class__(self._recognize_low_level_il) - - @classmethod - def register_global(cls): - if cls._instance is None: - cls._instance = cls() - core.BNRegisterGlobalFunctionRecognizer(cls._instance._cb) - - @classmethod - def register_arch(cls, arch): - if cls._instance is None: - cls._instance = cls() - core.BNRegisterArchitectureFunctionRecognizer(arch.handle, cls._instance._cb) - - def _recognize_low_level_il(self, ctxt, data, func, il): - try: - file_metadata = FileMetadata(handle = core.BNGetFileForView(data)) - view = BinaryView(file_metadata, handle = core.BNNewViewReference(data)) - func = Function(view, handle = core.BNNewFunctionReference(func)) - il = LowLevelILFunction(func.arch, handle = core.BNNewLowLevelILFunctionReference(il)) - return self.recognize_low_level_il(view, func, il) - except: - log_error(traceback.format_exc()) - return False - - def recognize_low_level_il(self, data, func, il): - return False - -class _UpdateChannelMetaClass(type): - @property - def list(self): - _init_plugins() - count = ctypes.c_ulonglong() - errors = ctypes.c_char_p() - channels = core.BNGetUpdateChannels(count, errors) - if errors: - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - raise IOError, error_str - result = [] - for i in xrange(0, count.value): - result.append(UpdateChannel(channels[i].name, channels[i].description, channels[i].latestVersion)) - core.BNFreeUpdateChannelList(channels, count.value) - return result - - @property - def active(self): - return core.BNGetActiveUpdateChannel() - - @active.setter - def active(self, value): - return core.BNSetActiveUpdateChannel(value) - - def __setattr__(self, name, value): - try: - type.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __getitem__(cls, name): - _init_plugins() - count = ctypes.c_ulonglong() - errors = ctypes.c_char_p() - channels = core.BNGetUpdateChannels(count, errors) - if errors: - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - raise IOError, error_str - result = None - for i in xrange(0, count.value): - if channels[i].name == str(name): - result = UpdateChannel(channels[i].name, channels[i].description, channels[i].latestVersion) - break - core.BNFreeUpdateChannelList(channels, count.value) - if result is None: - raise KeyError, "'%s' is not a valid channel" % str(name) - return result - -class UpdateProgressCallback: - def __init__(self, func): - self.cb = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(self.callback) - self.func = func - - def callback(self, ctxt, progress, total): - try: - if self.func is not None: - return self.func(progress, total) - return True - except: - log_error(traceback.format_exc()) - -class UpdateChannel(object): - __metaclass__ = _UpdateChannelMetaClass - - def __init__(self, name, desc, ver): - self.name = name - self.description = desc - self.latest_version_num = ver - - @property - def versions(self): - """List of versions (read-only)""" - count = ctypes.c_ulonglong() - errors = ctypes.c_char_p() - versions = core.BNGetUpdateChannelVersions(self.name, count, errors) - if errors: - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - raise IOError, error_str - result = [] - for i in xrange(0, count.value): - result.append(UpdateVersion(self, versions[i].version, versions[i].notes, versions[i].time)) - core.BNFreeUpdateChannelVersionList(versions, count.value) - return result - - @property - def latest_version(self): - """Latest version (read-only)""" - count = ctypes.c_ulonglong() - errors = ctypes.c_char_p() - versions = core.BNGetUpdateChannelVersions(self.name, count, errors) - if errors: - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - raise IOError, error_str - result = None - for i in xrange(0, count.value): - if versions[i].version == self.latest_version_num: - result = UpdateVersion(self, versions[i].version, versions[i].notes, versions[i].time) - break - core.BNFreeUpdateChannelVersionList(versions, count.value) - return result - - @property - def updates_available(self): - """Whether updates are available (read-only)""" - errors = ctypes.c_char_p() - result = core.BNAreUpdatesAvailable(self.name, errors) - if errors: - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - raise IOError, error_str - return result - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __repr__(self): - return "<channel: %s>" % self.name - - def __str__(self): - return self.name - - def update_to_latest(self, progress = None): - cb = UpdateProgressCallback(progress) - errors = ctypes.c_char_p() - result = core.BNUpdateToLatestVersion(self.name, errors, cb.cb, None) - if errors: - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - raise IOError, error_str - return core.BNUpdateResult_names[result] - -class UpdateVersion: - def __init__(self, channel, ver, notes, t): - self.channel = channel - self.version = ver - self.notes = notes - self.time = t - - def __repr__(self): - return "<version: %s>" % self.version - - def __str__(self): - return self.version - - def update(self, progress = None): - cb = UpdateProgressCallback(progress) - errors = ctypes.c_char_p() - result = core.BNUpdateToVersion(self.channel.name, self.version, errors, cb.cb, None) - if errors: - error_str = errors.value - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - raise IOError, error_str - return core.BNUpdateResult_names[result] - -class PluginCommandContext: - def __init__(self, view): - self.view = view - self.address = 0 - self.length = 0 - self.function = None - -class _PluginCommandMetaClass(type): - @property - def list(self): - _init_plugins() - count = ctypes.c_ulonglong() - commands = core.BNGetAllPluginCommands(count) - result = [] - for i in xrange(0, count.value): - result.append(PluginCommand(commands[i])) - core.BNFreePluginCommandList(commands) - return result - - def __setattr__(self, name, value): - try: - type.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - -class PluginCommand: - _registered_commands = [] - __metaclass__ = _PluginCommandMetaClass - - def __init__(self, cmd): - self.command = core.BNPluginCommand() - ctypes.memmove(ctypes.byref(self.command), ctypes.byref(cmd), ctypes.sizeof(core.BNPluginCommand)) - self.name = str(cmd.name) - self.description = str(cmd.description) - self.type = core.BNPluginCommandType_names[cmd.type] - - @classmethod - def _default_action(cls, view, action): - try: - file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) - action(view_obj) - except: - log_error(traceback.format_exc()) - - @classmethod - def _address_action(cls, view, addr, action): - try: - file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) - action(view_obj, addr) - except: - log_error(traceback.format_exc()) - - @classmethod - def _range_action(cls, view, addr, length, action): - try: - file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) - action(view_obj, addr, length) - except: - log_error(traceback.format_exc()) - - @classmethod - def _function_action(cls, view, func, action): - try: - file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) - func_obj = Function(view_obj, core.BNNewFunctionReference(func)) - action(view_obj, func_obj) - except: - log_error(traceback.format_exc()) - - @classmethod - def _default_is_valid(cls, view, is_valid): - try: - if is_valid is None: - return True - file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) - return is_valid(view_obj) - except: - log_error(traceback.format_exc()) - return False - - @classmethod - def _address_is_valid(cls, view, addr, is_valid): - try: - if is_valid is None: - return True - file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) - return is_valid(view_obj, addr) - except: - log_error(traceback.format_exc()) - return False - - @classmethod - def _range_is_valid(cls, view, addr, length, is_valid): - try: - if is_valid is None: - return True - file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) - return is_valid(view_obj, addr, length) - except: - log_error(traceback.format_exc()) - return False - - @classmethod - def _function_is_valid(cls, view, func, is_valid): - try: - if is_valid is None: - return True - file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) - func_obj = Function(view_obj, core.BNNewFunctionReference(func)) - return is_valid(view_obj, func_obj) - except: - log_error(traceback.format_exc()) - return False - - @classmethod - def register(cls, name, description, action, is_valid = None): - _init_plugins() - action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView))(lambda ctxt, view: cls._default_action(view, action)) - is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView))(lambda ctxt, view: cls._default_is_valid(view, is_valid)) - cls._registered_commands.append((action_obj, is_valid_obj)) - core.BNRegisterPluginCommand(name, description, action_obj, is_valid_obj, None) - - @classmethod - def register_for_address(cls, name, description, action, is_valid = None): - _init_plugins() - action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.c_ulonglong)(lambda ctxt, view, addr: cls._address_action(view, addr, action)) - is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.c_ulonglong)(lambda ctxt, view, addr: cls._address_is_valid(view, addr, is_valid)) - cls._registered_commands.append((action_obj, is_valid_obj)) - core.BNRegisterPluginCommandForAddress(name, description, action_obj, is_valid_obj, None) - - @classmethod - def register_for_range(cls, name, description, action, is_valid = None): - _init_plugins() - action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.c_ulonglong, ctypes.c_ulonglong)(lambda ctxt, view, addr, length: cls._range_action(view, addr, length, action)) - is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.c_ulonglong, ctypes.c_ulonglong)(lambda ctxt, view, addr, length: cls._range_is_valid(view, addr, length, is_valid)) - cls._registered_commands.append((action_obj, is_valid_obj)) - core.BNRegisterPluginCommandForRange(name, description, action_obj, is_valid_obj, None) - - @classmethod - def register_for_function(cls, name, description, action, is_valid = None): - _init_plugins() - action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNFunction))(lambda ctxt, view, func: cls._function_action(view, func, action)) - is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNFunction))(lambda ctxt, view, func: cls._function_is_valid(view, func, is_valid)) - cls._registered_commands.append((action_obj, is_valid_obj)) - core.BNRegisterPluginCommandForFunction(name, description, action_obj, is_valid_obj, None) - - @classmethod - def get_valid_list(cls, context): - commands = cls.list - result = [] - for cmd in commands: - if cmd.is_valid(context): - result.append(cmd) - return result - - def is_valid(self, context): - if context.view is None: - return False - if self.command.type == core.DefaultPluginCommand: - if not self.command.defaultIsValid: - return True - return self.command.defaultIsValid(self.command.context, context.view.handle) - elif self.command.type == core.AddressPluginCommand: - if not self.command.addressIsValid: - return True - return self.command.addressIsValid(self.command.context, context.view.handle, context.address) - elif self.command.type == core.RangePluginCommand: - if context.length == 0: - return False - if not self.command.rangeIsValid: - return True - return self.command.rangeIsValid(self.command.context, context.view.handle, context.address, context.length) - elif self.command.type == core.FunctionPluginCommand: - if context.function is None: - return False - if not self.command.functionIsValid: - return True - return self.command.functionIsValid(self.command.context, context.view.handle, context.function.handle) - return False - - def execute(self, context): - if not self.is_valid(context): - return - if self.command.type == core.DefaultPluginCommand: - self.command.defaultCommand(self.command.context, context.view.handle) - elif self.command.type == core.AddressPluginCommand: - self.command.addressCommand(self.command.context, context.view.handle, context.address) - elif self.command.type == core.RangePluginCommand: - self.command.rangeCommand(self.command.context, context.view.handle, context.address, context.length) - elif self.command.type == core.FunctionPluginCommand: - self.command.functionCommand(self.command.context, context.view.handle, context.function.handle) - - def __repr__(self): - return "<PluginCommand: %s>" % self.name - -class CallingConvention: - name = None - caller_saved_regs = [] - int_arg_regs = [] - float_arg_regs = [] - arg_regs_share_index = False - stack_reserved_for_arg_regs = False - int_return_reg = None - high_int_return_reg = None - float_return_reg = None - - _registered_calling_conventions = [] - - def __init__(self, arch, handle = None): - if handle is None: - self.arch = arch - self._pending_reg_lists = {} - self._cb = core.BNCustomCallingConvention() - self._cb.context = 0 - self._cb.getCallerSavedRegisters = self._cb.getCallerSavedRegisters.__class__(self._get_caller_saved_regs) - self._cb.getIntegerArgumentRegisters = self._cb.getIntegerArgumentRegisters.__class__(self._get_int_arg_regs) - self._cb.getFloatArgumentRegisters = self._cb.getFloatArgumentRegisters.__class__(self._get_float_arg_regs) - self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list) - self._cb.areArgumentRegistersSharedIndex = self._cb.areArgumentRegistersSharedIndex.__class__(self._arg_regs_share_index) - self._cb.isStackReservedForArgumentRegisters = self._cb.isStackReservedForArgumentRegisters.__class__(self._stack_reserved_for_arg_regs) - self._cb.getIntegerReturnValueRegister = self._cb.getIntegerReturnValueRegister.__class__(self._get_int_return_reg) - self._cb.getHighIntegerReturnValueRegister = self._cb.getHighIntegerReturnValueRegister.__class__(self._get_high_int_return_reg) - self._cb.getFloatReturnValueRegister = self._cb.getFloatReturnValueRegister.__class__(self._get_float_return_reg) - self.handle = core.BNCreateCallingConvention(arch.handle, self.__class__.name, self._cb) - self.__class__._registered_calling_conventions.append(self) - else: - self.handle = handle - self.arch = Architecture(core.BNGetCallingConventionArchitecture(self.handle)) - self.__dict__["name"] = core.BNGetCallingConventionName(self.handle) - self.__dict__["arg_regs_share_index"] = core.BNAreArgumentRegistersSharedIndex(self.handle) - self.__dict__["stack_reserved_for_arg_regs"] = core.BNIsStackReservedForArgumentRegisters(self.handle) - - count = ctypes.c_ulonglong() - regs = core.BNGetCallerSavedRegisters(self.handle, count) - result = [] - arch = self.arch - for i in xrange(0, count.value): - result.append(arch.get_reg_name(regs[i])) - core.BNFreeRegisterList(regs, count.value) - self.__dict__["caller_saved_regs"] = result - - count = ctypes.c_ulonglong() - regs = core.BNGetIntegerArgumentRegisters(self.handle, count) - result = [] - arch = self.arch - for i in xrange(0, count.value): - result.append(arch.get_reg_name(regs[i])) - core.BNFreeRegisterList(regs, count.value) - self.__dict__["int_arg_regs"] = result - - count = ctypes.c_ulonglong() - regs = core.BNGetFloatArgumentRegisters(self.handle, count) - result = [] - arch = self.arch - for i in xrange(0, count.value): - result.append(arch.get_reg_name(regs[i])) - core.BNFreeRegisterList(regs, count.value) - self.__dict__["float_arg_regs"] = result - - reg = core.BNGetIntegerReturnValueRegister(self.handle) - if reg == 0xffffffff: - self.__dict__["int_return_reg"] = None - else: - self.__dict__["int_return_reg"] = self.arch.get_reg_name(reg) - - reg = core.BNGetHighIntegerReturnValueRegister(self.handle) - if reg == 0xffffffff: - self.__dict__["high_int_return_reg"] = None - else: - self.__dict__["high_int_return_reg"] = self.arch.get_reg_name(reg) - - reg = core.BNGetFloatReturnValueRegister(self.handle) - if reg == 0xffffffff: - self.__dict__["float_return_reg"] = None - else: - self.__dict__["float_return_reg"] = self.arch.get_reg_name(reg) - - def __del__(self): - core.BNFreeCallingConvention(self.handle) - - def _get_caller_saved_regs(self, ctxt, count): - try: - regs = self.__class__.caller_saved_regs - count[0] = len(regs) - reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): - reg_buf[i] = self.arch.regs[regs[i]].index - result = ctypes.cast(reg_buf, ctypes.c_void_p) - self._pending_reg_lists[result.value] = (result, reg_buf) - return result.value - except: - log_error(traceback.format_exc()) - count[0] = 0 - return None - - def _get_int_arg_regs(self, ctxt, count): - try: - regs = self.__class__.int_arg_regs - count[0] = len(regs) - reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): - reg_buf[i] = self.arch.regs[regs[i]].index - result = ctypes.cast(reg_buf, ctypes.c_void_p) - self._pending_reg_lists[result.value] = (result, reg_buf) - return result.value - except: - log_error(traceback.format_exc()) - count[0] = 0 - return None - - def _get_float_arg_regs(self, ctxt, count): - try: - regs = self.__class__.float_arg_regs - count[0] = len(regs) - reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): - reg_buf[i] = self.arch.regs[regs[i]].index - result = ctypes.cast(reg_buf, ctypes.c_void_p) - self._pending_reg_lists[result.value] = (result, reg_buf) - return result.value - except: - log_error(traceback.format_exc()) - count[0] = 0 - return None - - def _free_register_list(self, ctxt, regs): - try: - buf = ctypes.cast(regs, ctypes.c_void_p) - if buf.value not in self._pending_reg_lists: - raise ValueError, "freeing register list that wasn't allocated" - del self._pending_reg_lists[buf.value] - except: - log_error(traceback.format_exc()) - - def _arg_regs_share_index(self, ctxt): - try: - return self.__class__.arg_regs_share_index - except: - log_error(traceback.format_exc()) - return False - - def _stack_reserved_for_arg_regs(self, ctxt): - try: - return self.__class__.stack_reserved_for_arg_regs - except: - log_error(traceback.format_exc()) - return False - - def _get_int_return_reg(self, ctxt): - try: - return self.arch.regs[self.__class__.int_return_reg].index - except: - log_error(traceback.format_exc()) - return False - - def _get_high_int_return_reg(self, ctxt): - try: - if self.__class__.high_int_return_reg is None: - return 0xffffffff - return self.arch.regs[self.__class__.high_int_return_reg].index - except: - log_error(traceback.format_exc()) - return False - - def _get_float_return_reg(self, ctxt): - try: - if self.__class__.float_return_reg is None: - return 0xffffffff - return self.arch.regs[self.__class__.float_int_return_reg].index - except: - log_error(traceback.format_exc()) - return False - - def __repr__(self): - return "<calling convention: %s %s>" % (self.arch.name, self.name) - - def __str__(self): - return self.name - -class _PlatformMetaClass(type): - @property - def list(self): - _init_plugins() - count = ctypes.c_ulonglong() - platforms = core.BNGetPlatformList(count) - result = [] - for i in xrange(0, count.value): - result.append(Platform(None, core.BNNewPlatformReference(platforms[i]))) - core.BNFreePlatformList(platforms, count.value) - return result - - @property - def os_list(self): - _init_plugins() - count = ctypes.c_ulonglong() - platforms = core.BNGetPlatformOSList(count) - result = [] - for i in xrange(0, count.value): - result.append(str(platforms[i])) - core.BNFreePlatformOSList(platforms, count.value) - return result - - def __setattr__(self, name, value): - try: - type.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __getitem__(cls, value): - _init_plugins() - platform = core.BNGetPlatformByName(str(value)) - if platform is None: - raise KeyError, "'%s' is not a valid platform" % str(value) - return Platform(None, platform) - - def get_list(cls, os = None, arch = None): - _init_plugins() - count = ctypes.c_ulonglong() - if os is None: - platforms = core.BNGetPlatformList(count) - elif arch is None: - platforms = core.BNGetPlatformListByOS(os) - else: - platforms = core.BNGetPlatformListByArchitecture(os, arch.handle) - result = [] - for i in xrange(0, count.value): - result.append(Platform(None, core.BNNewPlatformReference(platforms[i]))) - core.BNFreePlatformList(platforms, count.value) - return result - -class Platform: - __metaclass__ = _PlatformMetaClass - name = None - - def __init__(self, arch, handle = None): - if handle is None: - self.arch = arch - self.handle = core.BNCreatePlatform(arch.handle, self.__class__.name) - else: - self.handle = handle - self.__dict__["name"] = core.BNGetPlatformName(self.handle) - self.arch = Architecture(core.BNGetPlatformArchitecture(self.handle)) - - def __del__(self): - core.BNFreePlatform(self.handle) - - @property - def default_calling_convention(self): - result = core.BNGetPlatformDefaultCallingConvention(self.handle) - if result is None: - return None - return CallingConvention(None, result) - - @default_calling_convention.setter - def default_calling_convention(self, value): - core.BNRegisterPlatformDefaultCallingConvention(self.handle, value.handle) - - @property - def cdecl_calling_convention(self): - result = core.BNGetPlatformCdeclCallingConvention(self.handle) - if result is None: - return None - return CallingConvention(None, result) - - @cdecl_calling_convention.setter - def cdecl_calling_convention(self, value): - core.BNRegisterPlatformCdeclCallingConvention(self.handle, value.handle) - - @property - def stdcall_calling_convention(self): - result = core.BNGetPlatformStdcallCallingConvention(self.handle) - if result is None: - return None - return CallingConvention(None, result) - - @stdcall_calling_convention.setter - def stdcall_calling_convention(self, value): - core.BNRegisterPlatformStdcallCallingConvention(self.handle, value.handle) - - @property - def fastcall_calling_convention(self): - result = core.BNGetPlatformFastcallCallingConvention(self.handle) - if result is None: - return None - return CallingConvention(None, result) - - @fastcall_calling_convention.setter - def fastcall_calling_convention(self, value): - core.BNRegisterPlatformFastcallCallingConvention(self.handle, value.handle) - - @property - def system_call_convention(self): - result = core.BNGetPlatformSystemCallConvention(self.handle) - if result is None: - return None - return CallingConvention(None, result) - - @system_call_convention.setter - def system_call_convention(self, value): - core.BNSetPlatformSystemCallConvention(self.handle, value.handle) - - @property - def calling_conventions(self): - """List of platform calling conventions (read-only)""" - count = ctypes.c_ulonglong() - cc = core.BNGetPlatformCallingConventions(self.handle, count) - result = [] - for i in xrange(0, count.value): - result.append(CallingConvention(None, core.BNNewCallingConventionReference(cc[i]))) - core.BNFreeCallingConventionList(cc, count.value) - return result - - def __setattr__(self, name, value): - try: - object.__setattr__(self,name,value) - except AttributeError: - raise AttributeError, "attribute '%s' is read only" % name - - def __repr__(self): - return "<platform: %s>" % self.name - - def __str__(self): - return self.name - - def register(self, os): - core.BNRegisterPlatform(os, self.handle) - - def register_calling_convention(self, cc): - core.BNRegisterPlatformCallingConvention(self.handle, cc.handle) - -def LLIL_TEMP(n): - return n | 0x80000000 - -def LLIL_REG_IS_TEMP(n): - return (n & 0x80000000) != 0 +# Binary Ninja components +import _binaryninjacore as core +from .enums import * +from .databuffer import * +from .filemetadata import * +from .fileaccessor import * +from .binaryview import * +from .transform import * +from .architecture import * +from .basicblock import * +from .function import * +from .log import * +from .lowlevelil import * +from .types import * +from .functionrecognizer import * +from .update import * +from .plugin import * +from .callingconvention import * +from .platform import * +from .demangle import * +from .mainthread import * +from .interaction import * +from .lineardisassembly import * +from .undoaction import * +from .highlight import * +from .scriptingprovider import * -def LLIL_GET_TEMP_REG_INDEX(n): - return n & 0x7fffffff def shutdown(): + """ + ``shutdown`` cleanly shuts down the core, stopping all workers and closing all log files. + """ core.BNShutdown() -def log(level, text): - core.BNLog(level, "%s", str(text)) - -def log_debug(text): - core.BNLogDebug("%s", str(text)) - -def log_info(text): - core.BNLogInfo("%s", str(text)) - -def log_warn(text): - core.BNLogWarn("%s", str(text)) - -def log_error(text): - core.BNLogError("%s", str(text)) -def log_alert(text): - core.BNLogAlert("%s", str(text)) +def get_unique_identifier(): + return core.BNGetUniqueIdentifierString() -def log_to_stdout(min_level): - core.BNLogToStdout(min_level) -def log_to_stderr(min_level): - core.BNLogToStderr(min_level) +def get_install_directory(): + """ + ``get_install_directory`` returns a string pointing to the installed binary currently running -def log_to_file(min_level, path, append = False): - core.BNLogToFile(min_level, str(path), append) + .warning:: ONLY for use within the Binary Ninja UI, behavior is undefined and unreliable if run headlessly + """ + return core.BNGetInstallDirectory() -def close_logs(): - core.BNCloseLogs() -def escape_string(text): - return DataBuffer(text).escape() - -def unescape_string(text): - return DataBuffer(text).unescape() +class _DestructionCallbackHandler(object): + def __init__(self): + self._cb = core.BNObjectDestructionCallbacks() + self._cb.context = 0 + self._cb.destructBinaryView = self._cb.destructBinaryView.__class__(self.destruct_binary_view) + self._cb.destructFileMetadata = self._cb.destructFileMetadata.__class__(self.destruct_file_metadata) + self._cb.destructFunction = self._cb.destructFunction.__class__(self.destruct_function) + core.BNRegisterObjectDestructionCallbacks(self._cb) -def preprocess_source(source, filename = None, include_dirs = []): - if filename is None: - filename = "input" - dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) - output = ctypes.c_char_p() - errors = ctypes.c_char_p() - result = core.BNPreprocessSource(source, filename, output, errors, dir_buf, len(include_dirs)) - output_str = output.value - error_str = errors.value - core.BNFreeString(ctypes.cast(output, ctypes.POINTER(ctypes.c_byte))) - core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) - if result: - return (output_str, error_str) - return (None, error_str) + def destruct_binary_view(self, ctxt, view): + BinaryView._unregister(view) -def are_auto_updates_enabled(): - return core.BNAreAutoUpdatesEnabled() + def destruct_file_metadata(self, ctxt, f): + FileMetadata._unregister(f) -def set_auto_updates_enabled(enabled): - core.BNSetAutoUpdatesEnabled(enabled) + def destruct_function(self, ctxt, func): + Function._unregister(func) -def get_time_since_last_update_check(): - return core.BNGetTimeSinceLastUpdateCheck() -def updates_checked(): - core.BNUpdatesChecked() +_destruct_callbacks = _DestructionCallbackHandler() bundled_plugin_path = core.BNGetBundledPluginDirectory() user_plugin_path = core.BNGetUserPluginDirectory() core_version = core.BNGetVersionString() +'''Core version''' + core_build_id = core.BNGetBuildId() +'''Build ID''' + +core_product = core.BNGetProduct() +'''Product string from the license file''' + +core_product_type = core.BNGetProductType() +'''Product type from the license file''' -# Ensure all enumeration constants from the core are exposed by this module -for name in core.all_enum_values: - globals()[name] = core.all_enum_values[name] +core_license_count = core.BNGetLicenseCount() +'''License count from the license file''' |
