From a40f0e1e494af967a35ca4a8977596f4693b5c0e Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 29 Sep 2016 18:41:13 -0400 Subject: Adding APIs for segments and sections --- python/__init__.py | 313 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 241 insertions(+), 72 deletions(-) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 26c8fb5d..53d5653b 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -300,7 +300,7 @@ class FileMetadata(object): view = core.BNGetFileViewOfType(self.handle, "Raw") if view is None: return None - return BinaryView(self, handle = view) + return BinaryView(file_metadata = self, handle = view) @property def saved(self): @@ -455,7 +455,7 @@ class FileMetadata(object): lambda ctxt, cur, total: progress_func(cur, total))) if view is None: return None - return BinaryView(self, handle = view) + return BinaryView(file_metadata = self, handle = view) def save_auto_snapshot(self, progress_func = None): if progress_func is None: @@ -474,7 +474,7 @@ class FileMetadata(object): view = core.BNCreateBinaryViewOfType(view_type, self.raw.handle) if view is None: return None - return BinaryView(self, handle = view) + return BinaryView(file_metadata = self, handle = view) def __setattr__(self, name, value): try: @@ -812,7 +812,7 @@ class BinaryViewType(object): view = core.BNCreateBinaryViewOfType(self.handle, data.handle) if view is None: return None - return BinaryView(data.file, handle = view) + return BinaryView(file_metadata = data.file, handle = view) def open(self, src, file_metadata = None): data = BinaryView.open(src, file_metadata) @@ -924,6 +924,64 @@ class DataVariable(object): def __repr__(self): return "" % (self.address, str(self.type)) +class Segment(object): + def __init__(self, start, length, data_offset, data_length, flags): + self.start = start + self.length = length + self.data_offset = data_offset + self.data_length = data_length + self.flags = flags + + @property + def end(self): + return self.start + self.length + + def __len__(self): + return self.length + + def __repr__(self): + return "" % (self.start, self.end, + "r" if (self.flags & core.SegmentReadable) != 0 else "-", + "w" if (self.flags & core.SegmentWritable) != 0 else "-", + "x" if (self.flags & core.SegmentExecutable) != 0 else "-") + +class Section(object): + def __init__(self, name, section_type, start, length, linked_section, info_section, info_data, align, entry_size): + self.name = name + self.type = section_type + self.start = start + self.length = length + self.linked_section = linked_section + self.info_section = info_section + self.info_data = info_data + self.align = align + self.entry_size = entry_size + + @property + def end(self): + return self.start + self.length + + def __len__(self): + return self.length + + def __repr__(self): + return "
" % (self.name, self.start, self.end) + +class AddressRange(object): + def __init__(self, start, end): + self.start = start + self.end = end + + @property + def length(self): + return self.end - self.start + + def __len__(self): + return self.end - self.start + + def __repr__(self): + return "<%#x-%#x>" % (self.start, self.end) + class _BinaryViewAssociatedDataStore(_AssociatedDataStore): _defaults = {} @@ -982,7 +1040,7 @@ class BinaryView(object): next_address = 0 _associated_data = {} - def __init__(self, file_metadata = None, handle = None): + def __init__(self, parent_view = None, file_metadata = None, handle = None): if handle is not None: self.handle = core.handle_of_type(handle, core.BNBinaryView) if file_metadata is None: @@ -1020,7 +1078,9 @@ class BinaryView(object): 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) + if parent_view is not None: + parent_view = parent_view.handle + self.handle = core.BNCreateCustomBinaryView(self.__class__.name, file_metadata.handle, parent_view, self._cb) self.notifications = {} self.next_address = None # Do NOT try to access view before init() is called, use placeholder @@ -1042,7 +1102,7 @@ class BinaryView(object): def _create(cls, ctxt, data): try: file_metadata = FileMetadata(handle = core.BNGetFileForView(data)) - view = cls(BinaryView(file_metadata, handle = core.BNNewViewReference(data))) + view = cls(BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(data))) if view is None: return None return ctypes.cast(core.BNNewViewReference(view.handle), ctypes.c_void_p).value @@ -1053,7 +1113,7 @@ class BinaryView(object): @classmethod def _is_valid_for_data(cls, ctxt, data): try: - return cls.is_valid_for_data(BinaryView(None, handle = core.BNNewViewReference(data))) + return cls.is_valid_for_data(BinaryView(handle = core.BNNewViewReference(data))) except: log_error(traceback.format_exc()) return False @@ -1071,7 +1131,7 @@ class BinaryView(object): view = core.BNCreateBinaryDataViewFromFilename(file_metadata.handle, str(src)) if view is None: return None - result = BinaryView(file_metadata, handle = view) + result = BinaryView(file_metadata = file_metadata, handle = view) return result @classmethod @@ -1086,7 +1146,7 @@ class BinaryView(object): view = core.BNCreateBinaryDataViewFromBuffer(file_metadata.handle, buf.handle) if view is None: return None - result = BinaryView(file_metadata, handle = view) + result = BinaryView(file_metadata = file_metadata, handle = view) return result @classmethod @@ -1113,6 +1173,14 @@ class BinaryView(object): finally: core.BNFreeFunctionList(funcs, count.value) + @property + def parent_view(self): + """View that contains the raw data used by this view (read-only)""" + result = core.BNGetParentView(self.handle) + if result is None: + return None + return BinaryView(handle = result) + @property def modified(self): """boolean modification state of the BinaryView (read/write)""" @@ -1310,6 +1378,42 @@ class BinaryView(object): core.BNFreeTypeList(type_list, count.value) return result + @property + def segments(self): + """List of segments (read-only)""" + count = ctypes.c_ulonglong(0) + segment_list = core.BNGetSegments(self.handle, count) + result = [] + for i in xrange(0, count.value): + result.append(Segment(segment_list[i].start, segment_list[i].length, + segment_list[i].dataOffset, segment_list[i].dataLength, segment_list[i].flags)) + core.BNFreeSegmentList(segment_list) + return result + + @property + def sections(self): + """List of sections (read-only)""" + count = ctypes.c_ulonglong(0) + section_list = core.BNGetSections(self.handle, count) + result = {} + for i in xrange(0, count.value): + result[section_list[i].name] = Section(section_list[i].name, section_list[i].type, section_list[i].start, + section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection, + section_list[i].infoData, section_list[i].align, section_list[i].entrySize) + core.BNFreeSectionList(section_list, count.value) + return result + + @property + def allocated_ranges(self): + """List of valid address ranges for this view (read-only)""" + count = ctypes.c_ulonglong(0) + range_list = core.BNGetAllocatedRanges(self.handle, count) + result = [] + for i in xrange(0, count.value): + result.append(AddressRange(range_list[i].start, range_list[i].end)) + core.BNFreeAddressRanges(range_list) + return result + @property def data(self): """Dictionary object where plugins can store arbitrary data associated with the view""" @@ -1587,43 +1691,52 @@ class BinaryView(object): return None return ''.join(str(a) for a in txt).strip() - @abc.abstractmethod def perform_save(self, accessor): - raise NotImplementedError + if self.parent_view is not None: + return self.parent_view.save(accessor) + return False @abc.abstractmethod def perform_get_address_size(self): raise NotImplementedError - @abc.abstractmethod def perform_get_length(self): - raise NotImplementedError + """ + ``perform_get_length`` implements a query for the size of the virtual address range used by + the BinaryView. + + .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide + data without overriding this method. + .. warning:: This method **must not** be called directly. + + :return: returns the size of the virtual address range used by the BinaryView. + :rtype: int + """ + return 0 - @abc.abstractmethod def perform_read(self, addr, length): """ ``perform_read`` implements a mapping between a virtual address and an absolute file offset, reading ``length`` bytes from the rebased address ``addr``. - .. note:: This method must be overridden by custom BinaryViews if they have segments or the virtual address is\ - different from the physical address. + .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide + data without overriding this method. .. warning:: This method **must not** be called directly. :param int addr: a virtual address to attempt to read from :param int length: the number of bytes to be read :return: length bytes read from addr, should return empty string on error - :rtype: int + :rtype: str """ - raise NotImplementedError + return "" - @abc.abstractmethod def perform_write(self, addr, data): """ ``perform_write`` implements a mapping between a virtual address and an absolute file offset, writing the bytes ``data`` to rebased address ``addr``. - .. note:: This method must be overridden by custom BinaryViews if they have segments or the virtual address is \ - different from the physical address. + .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide + data without overriding this method. .. warning:: This method **must not** be called directly. :param int addr: a virtual address @@ -1631,16 +1744,14 @@ class BinaryView(object): :return: length of data written, should return 0 on error :rtype: int """ - raise NotImplementedError + return 0 - @abc.abstractmethod def perform_insert(self, addr, data): """ ``perform_insert`` implements a mapping between a virtual address and an absolute file offset, inserting the bytes ``data`` to rebased address ``addr``. - .. note:: This method must be overridden by custom BinaryViews if they have segments or the virtual address is \ - different from the physical address. + .. note:: This method **may** be overridden by custom BinaryViews. If not overridden, inserting is disallowed .. warning:: This method **must not** be called directly. :param int addr: a virtual address @@ -1648,16 +1759,14 @@ class BinaryView(object): :return: length of data inserted, should return 0 on error :rtype: int """ - raise NotImplementedError + return 0 - @abc.abstractmethod def perform_remove(self, addr, length): """ ``perform_remove`` implements a mapping between a virtual address and an absolute file offset, removing ``length`` bytes from the rebased address ``addr``. - .. note:: This method must be overridden by custom BinaryViews if they have segments or the virtual address is \ - different from the physical address. + .. note:: This method **may** be overridden by custom BinaryViews. If not overridden, removing data is disallowed .. warning:: This method **must not** be called directly. :param int addr: a virtual address @@ -1665,14 +1774,14 @@ class BinaryView(object): :return: length of data removed, should return 0 on error :rtype: int """ - raise NotImplementedError + return 0 - @abc.abstractmethod def perform_get_modification(self, addr): """ ``perform_get_modification`` implements query to the whether the virtual address ``addr`` is modified. - .. note:: This method **may** be overridden by custom BinaryViews. + .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide + data without overriding this method. .. warning:: This method **must not** be called directly. :param int addr: a virtual address to be checked @@ -1681,13 +1790,12 @@ class BinaryView(object): """ return core.Original - @abc.abstractmethod def perform_is_valid_offset(self, addr): """ ``perform_is_valid_offset`` implements a check if an virtual address ``addr`` is valid. - .. note:: This method **must** be implemented for custom BinaryViews whose virtual addresses differ from \ - physical file offsets. + .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide + data without overriding this method. .. warning:: This method **must not** be called directly. :param int addr: a virtual address to be checked @@ -1697,13 +1805,12 @@ class BinaryView(object): data = self.read(addr, 1) return (data is not None) and (len(data) == 1) - @abc.abstractmethod def perform_is_offset_readable(self, offset): """ ``perform_is_offset_readable`` implements a check if an virtual address is readable. - .. note:: This method **must** be implemented for custom BinaryViews whose virtual addresses differ from \ - physical file offsets, or if memory protections exist. + .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide + data without overriding this method. .. warning:: This method **must not** be called directly. :param int offset: a virtual address to be checked @@ -1712,13 +1819,12 @@ class BinaryView(object): """ return self.is_valid_offset(offset) - @abc.abstractmethod def perform_is_offset_writable(self, addr): """ ``perform_is_offset_writable`` implements a check if a virtual address ``addr`` is writable. - .. note:: This method **must** be implemented for custom BinaryViews whose virtual addresses differ from \ - physical file offsets, or if memory protections exist. + .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide + data without overriding this method. .. warning:: This method **must not** be called directly. :param int addr: a virtual address to be checked @@ -1727,13 +1833,12 @@ class BinaryView(object): """ return self.is_valid_offset(addr) - @abc.abstractmethod def perform_is_offset_executable(self, addr): """ ``perform_is_offset_writable`` implements a check if a virtual address ``addr`` is executable. - .. note:: This method **must** be implemented for custom BinaryViews whose virtual addresses differ from \ - physical file offsets, or if memory protections exist. + .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide + data without overriding this method. .. warning:: This method **must not** be called directly. :param int addr: a virtual address to be checked @@ -1742,13 +1847,13 @@ class BinaryView(object): """ return self.is_valid_offset(addr) - @abc.abstractmethod def perform_get_next_valid_offset(self, addr): """ ``perform_get_next_valid_offset`` implements a query for the next valid readable, writable, or executable virtual memory address. - .. note:: This method **may** be implemented by custom BinaryViews + .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide + data without overriding this method. .. warning:: This method **must not** be called directly. :param int addr: a virtual address to start checking from. @@ -1759,13 +1864,13 @@ class BinaryView(object): return self.perform_get_start() return addr - @abc.abstractmethod def perform_get_start(self): """ ``perform_get_start`` implements a query for the first readable, writable, or executable virtual address in the BinaryView. - .. note:: This method **may** be implemented by custom BinaryViews + .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide + data without overriding this method. .. warning:: This method **must not** be called directly. :return: returns the first virtual address in the BinaryView. @@ -1773,7 +1878,6 @@ class BinaryView(object): """ return 0 - @abc.abstractmethod def perform_get_entry_point(self): """ ``perform_get_entry_point`` implements a query for the initial entry point for code execution. @@ -1786,7 +1890,6 @@ class BinaryView(object): """ return 0 - @abc.abstractmethod def perform_is_executable(self): """ ``perform_is_executable`` implements a check which returns true if the BinaryView is executable. @@ -1797,9 +1900,8 @@ class BinaryView(object): :return: true if the current BinaryView is executable, false if it is not executable or on error :rtype: bool """ - raise NotImplementedError + return False - @abc.abstractmethod def perform_get_default_endianness(self): """ ``perform_get_default_endianness`` implements a check which returns true if the BinaryView is executable. @@ -2868,7 +2970,7 @@ class BinaryView(object): 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) + core.BNFreeStringReferenceList(strings) return result def add_analysis_completion_event(self, callback): @@ -3387,6 +3489,73 @@ class BinaryView(object): return None return value.value + def add_auto_segment(self, start, length, data_offset, data_length, flags): + core.BNAddAutoSegment(self.handle, start, length, data_offset, data_length, flags) + + def remove_auto_segment(self, start, length): + core.BNRemoveAutoSegment(self.handle, start, length) + + def add_user_segment(self, start, length, data_offset, data_length, flags): + core.BNAddUserSegment(self.handle, start, length, data_offset, data_length, flags) + + def remove_user_segment(self, start, length): + core.BNRemoveUserSegment(self.handle, start, length) + + def get_segment_at(self, addr): + segment = core.BNSegment() + if not core.BNGetSegmentAt(self.handle, addr, segment): + return None + result = Segment(segment.start, segment.length, segment.dataOffset, segment.dataLength, + segment.flags) + return result + + def add_auto_section(self, name, start, length, type = "", align = 1, entry_size = 1, linked_section = "", + info_section = "", info_data = 0): + core.BNAddAutoSection(self.handle, name, start, length, type, align, entry_size, linked_section, + info_section, info_data) + + def remove_auto_section(self, name): + core.BNRemoveAutoSection(self.handle, name) + + def add_user_section(self, name, start, length, type = "", align = 1, entry_size = 1, linked_section = "", + info_section = "", info_data = 0): + core.BNAddUserSection(self.handle, name, start, length, type, align, entry_size, linked_section, + info_section, info_data) + + def remove_user_section(self, name): + core.BNRemoveUserSection(self.handle, name) + + def get_sections_at(self, addr): + count = ctypes.c_ulonglong(0) + section_list = core.BNGetSectionsAt(self.handle, addr, count) + result = [] + for i in xrange(0, count.value): + result.append(Section(section_list[i].name, section_list[i].type, section_list[i].start, + section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection, + section_list[i].infoData, section_list[i].align, section_list[i].entrySize)) + core.BNFreeSectionList(section_list, count.value) + return result + + def get_section_by_name(self, name): + section = core.BNSection() + if not core.BNGetSectionByName(self.handle, name, section): + return None + result = Section(section.name, section.type, section.start, section.length, section.linkedSection, + section.infoSection, section.infoData, section.align, section.entrySize) + core.BNFreeSection(section) + return result + + def get_unique_section_names(self, name_list): + incoming_names = (ctypes.c_char_p * len(name_list))() + for i in xrange(0, len(name_list)): + incoming_names[i] = name_list[i] + outgoing_names = core.BNGetUniqueSectionNames(self.handle, incoming_names, len(name_list)) + result = [] + for i in xrange(0, len(name_list)): + result.append(str(outgoing_names[i])) + core.BNFreeStringList(outgoing_names, len(name_list)) + return result + def __setattr__(self, name, value): try: object.__setattr__(self,name,value) @@ -5266,7 +5435,7 @@ class FunctionGraphBlock(object): core.BNFreeBasicBlock(block) block = None else: - block = BasicBlock(BinaryView(None, handle = core.BNGetFunctionData(func)), block) + block = BasicBlock(BinaryView(handle = core.BNGetFunctionData(func)), block) core.BNFreeFunction(func) return block @@ -8719,7 +8888,7 @@ class FunctionRecognizer(object): 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)) + view = BinaryView(file_metadata = 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) @@ -8956,7 +9125,7 @@ class PluginCommand: def _default_action(cls, view, action): try: file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) + view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) action(view_obj) except: log_error(traceback.format_exc()) @@ -8965,7 +9134,7 @@ class PluginCommand: def _address_action(cls, view, addr, action): try: file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) + view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) action(view_obj, addr) except: log_error(traceback.format_exc()) @@ -8974,7 +9143,7 @@ class PluginCommand: 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)) + view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) action(view_obj, addr, length) except: log_error(traceback.format_exc()) @@ -8983,7 +9152,7 @@ class PluginCommand: def _function_action(cls, view, func, action): try: file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) + view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) func_obj = Function(view_obj, core.BNNewFunctionReference(func)) action(view_obj, func_obj) except: @@ -8995,7 +9164,7 @@ class PluginCommand: if is_valid is None: return True file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) + view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) return is_valid(view_obj) except: log_error(traceback.format_exc()) @@ -9007,7 +9176,7 @@ class PluginCommand: if is_valid is None: return True file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) + view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) return is_valid(view_obj, addr) except: log_error(traceback.format_exc()) @@ -9019,7 +9188,7 @@ class PluginCommand: if is_valid is None: return True file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) + view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) return is_valid(view_obj, addr, length) except: log_error(traceback.format_exc()) @@ -9031,7 +9200,7 @@ class PluginCommand: if is_valid is None: return True file_metadata = FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view)) + view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) func_obj = Function(view_obj, core.BNNewFunctionReference(func)) return is_valid(view_obj, func_obj) except: @@ -9595,7 +9764,7 @@ class ScriptingInstance(object): def _set_current_binary_view(self, ctxt, view): try: if view: - view = BinaryView(None, handle = core.BNNewViewReference(view)) + view = BinaryView(handle = core.BNNewViewReference(view)) else: view = None self.perform_set_current_binary_view(view) @@ -9605,7 +9774,7 @@ class ScriptingInstance(object): def _set_current_function(self, ctxt, func): try: if func: - func = Function(BinaryView(None, handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func)) + func = Function(BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func)) else: func = None self.perform_set_current_function(func) @@ -9619,7 +9788,7 @@ class ScriptingInstance(object): if func is None: block = None else: - block = BasicBlock(BinaryView(None, handle = core.BNGetFunctionData(func)), core.BNNewBasicBlockReference(block)) + block = BasicBlock(BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewBasicBlockReference(block)) core.BNFreeFunction(func) else: block = None @@ -10369,7 +10538,7 @@ class InteractionHandler(object): def _show_plain_text_report(self, ctxt, view, title, contents): try: if view: - view = BinaryView(None, handle = core.BNNewViewReference(view)) + view = BinaryView(handle = core.BNNewViewReference(view)) else: view = None self.show_plain_text_report(view, title, contents) @@ -10379,7 +10548,7 @@ class InteractionHandler(object): def _show_markdown_report(self, ctxt, view, title, contents, plaintext): try: if view: - view = BinaryView(None, handle = core.BNNewViewReference(view)) + view = BinaryView(handle = core.BNNewViewReference(view)) else: view = None self.show_markdown_report(view, title, contents, plaintext) @@ -10389,7 +10558,7 @@ class InteractionHandler(object): def _show_html_report(self, ctxt, view, title, contents, plaintext): try: if view: - view = BinaryView(None, handle = core.BNNewViewReference(view)) + view = BinaryView(handle = core.BNNewViewReference(view)) else: view = None self.show_html_report(view, title, contents, plaintext) @@ -10419,7 +10588,7 @@ class InteractionHandler(object): def _get_address_input(self, ctxt, result, prompt, title, view, current_address): try: if view: - view = BinaryView(None, handle = core.BNNewViewReference(view)) + view = BinaryView(handle = core.BNNewViewReference(view)) else: view = None value = self.get_address_input(prompt, title, view, current_address) @@ -10490,7 +10659,7 @@ class InteractionHandler(object): elif fields[i].type == core.AddressFormField: view = None if fields[i].view: - view = BinaryView(None, handle = core.BNNewViewReference(fields[i].view)) + view = BinaryView(handle = core.BNNewViewReference(fields[i].view)) field_objs.append(AddressField(fields[i].prompt, view, fields[i].currentAddress)) elif fields[i].type == core.ChoiceFormField: choices = [] -- cgit v1.3.1 From 1584c0f2ae591eafe6b69a9d663dbff4d32beaff Mon Sep 17 00:00:00 2001 From: plafosse Date: Thu, 25 Aug 2016 00:22:43 +0100 Subject: adding gnu3 demangler apis --- binaryninjaapi.h | 12 ++++++++++++ binaryninjacore.h | 23 +++++++++++++++++++++-- demangle.cpp | 20 ++++++++++++++++++++ python/__init__.py | 19 +++++++++++++++++++ type.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 2 deletions(-) (limited to 'python/__init__.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index b115263c..ed714be6 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1449,6 +1449,7 @@ namespace BinaryNinja }; class Structure; + class UnknownType; class Enumeration; struct NameAndType @@ -1476,6 +1477,8 @@ namespace BinaryNinja bool CanReturn() const; Ref GetStructure() const; Ref GetEnumeration() const; + Ref GetUnknownType() const; + uint64_t GetElementCount() const; void SetFunctionCanReturn(bool canReturn); @@ -1492,6 +1495,7 @@ namespace BinaryNinja static Ref IntegerType(size_t width, bool sign, const std::string& altName = ""); static Ref FloatType(size_t width, const std::string& typeName = ""); static Ref StructureType(Structure* strct); + static Ref UnknownNamedType(UnknownType* unknwn); static Ref EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); static Ref PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, BNReferenceType refType = PointerReferenceType); @@ -1502,6 +1506,14 @@ namespace BinaryNinja static std::string GetQualifiedName(const std::vector& names); }; + class UnknownType: public CoreRefCountObject + { + public: + UnknownType(BNUnknownType* s, std::vector name = {}); + std::vector GetName() const; + void SetName(const std::vector& name); + }; + struct StructureMember { Ref type; diff --git a/binaryninjacore.h b/binaryninjacore.h index b6d2f7ed..e841b2d7 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -94,6 +94,7 @@ extern "C" struct BNLowLevelILFunction; struct BNType; struct BNStructure; + struct BNUnknownType; struct BNEnumeration; struct BNCallingConvention; struct BNPlatform; @@ -355,7 +356,8 @@ extern "C" ArrayTypeClass = 7, FunctionTypeClass = 8, VarArgsTypeClass = 9, - ValueTypeClass = 10 + ValueTypeClass = 10, + UnknownTypeClass = 11 }; enum BNStructureType @@ -471,7 +473,11 @@ extern "C" RttiBaseClassDescriptor, RttiBaseClassArray, RttiClassHeirarchyDescriptor, - RttiCompleteObjectLocator + RttiCompleteObjectLocator, + OperatorUnaryMinusNameType, + OperatorUnaryPlusNameType, + OperatorUnaryBitAndNameType, + OperatorUnaryStarNameType }; enum BNCallingConventionName @@ -1878,6 +1884,13 @@ extern "C" BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type); BINARYNINJACOREAPI char* BNGetTypeStringAfterName(BNType* type); + BINARYNINJACOREAPI BNType* BNCreateUnknownNamedType(BNUnknownType* ut); + BINARYNINJACOREAPI BNUnknownType* BNCreateUnknownType(void); + BINARYNINJACOREAPI void BNSetUnknownTypeName(BNUnknownType* ut, const char** name, size_t size); + BINARYNINJACOREAPI char** BNGetUnknownTypeName(BNUnknownType* ut, size_t* size); + BINARYNINJACOREAPI void BNFreeUnknownType(BNUnknownType* ut); + BINARYNINJACOREAPI BNUnknownType* BNNewUnknownTypeReference(BNUnknownType* ut); + BINARYNINJACOREAPI BNStructure* BNCreateStructure(void); BINARYNINJACOREAPI BNStructure* BNNewStructureReference(BNStructure* s); BINARYNINJACOREAPI void BNFreeStructure(BNStructure* s); @@ -2143,6 +2156,12 @@ extern "C" BINARYNINJACOREAPI BNMessageBoxButtonResult BNShowMessageBox(const char* title, const char* text, BNMessageBoxButtonSet buttons, BNMessageBoxIcon icon); + BINARYNINJACOREAPI bool BNDemangleGNU3(BNArchitecture* arch, + const char* mangledName, + BNType** outType, + char*** outVarName, + size_t* outVarNameElements); + BINARYNINJACOREAPI void BNFreeDemangledName(char*** name, size_t nameElements); #ifdef __cplusplus } #endif diff --git a/demangle.cpp b/demangle.cpp index 1a998a87..a12303ca 100644 --- a/demangle.cpp +++ b/demangle.cpp @@ -21,3 +21,23 @@ bool DemangleMS(Architecture* arch, delete [] localVarName; return true; } + + +bool DemangleGNU3(Architecture* arch, + const std::string& mangledName, + Type** outType, + std::vector& outVarName) +{ + BNType* localType = (*outType)->GetObject(); + char** localVarName = nullptr; + size_t localSize = 0; + if (!BNDemangleGNU3(arch->GetObject(), mangledName.c_str(), &localType, &localVarName, &localSize)) + return false; + for (size_t i = 0; i < localSize; i++) + { + outVarName.push_back(localVarName[i]); + BNFreeString(localVarName[i]); + } + delete [] localVarName; + return true; +} diff --git a/python/__init__.py b/python/__init__.py index 26c8fb5d..f5a46798 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -4150,6 +4150,10 @@ class Type(object): def unknown_type(self, unknown_type): return Type(core.BNCreateUnknownType(unknown_type.handle)) + @classmethod + def unknown_type(self, s): + return Type(core.BNCreateUnknownType(s.handle)) + @classmethod def enumeration_type(self, arch, e, width = None): if width is None: @@ -10839,6 +10843,21 @@ def demangle_ms(arch, mangled_name): names.append(outName[i]) #core.BNFreeDemangledName(outName.value, outSize.value) return (Type(handle), names) + return (None, mangledName) + + +def demangle_gnu3(arch, mangledName): + handle = ctypes.POINTER(core.BNType)() + outName = ctypes.POINTER(ctypes.c_char_p)() + outSize = ctypes.c_ulonglong() + names = [] + if core.BNDemangleGNU3(arch.handle, mangledName, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize)): + for i in xrange(outSize.value): + names.append(outName[i]) + #core.BNFreeDemangledName(outName.value, outSize.value) + if not handle: + return (None, names) + return (Type(handle), names) return (None, mangled_name) diff --git a/type.cpp b/type.cpp index 34e142b6..e0235664 100644 --- a/type.cpp +++ b/type.cpp @@ -235,6 +235,12 @@ Ref Type::StructureType(Structure* strct) } +Ref Type::UnknownNamedType(UnknownType* unknwn) +{ + return new Type(BNCreateUnknownNamedType(unknwn->GetObject())); +} + + Ref Type::EnumerationType(Architecture* arch, Enumeration* enm, size_t width, bool isSigned) { return new Type(BNCreateEnumerationType(arch->GetObject(), enm->GetObject(), width, isSigned)); @@ -277,6 +283,46 @@ void Type::SetFunctionCanReturn(bool canReturn) } +UnknownType::UnknownType(BNUnknownType* ut, vector names) +{ + m_object = ut; + const char ** nameList = new const char*[names.size()]; + for (size_t i = 0; i < names.size(); i++) + { + nameList[i] = names[i].c_str(); + } + BNSetUnknownTypeName(ut, nameList, names.size()); + delete [] nameList; +} + + +void UnknownType::SetName(const vector& names) +{ + const char ** nameList = new const char*[names.size()]; + for (size_t i = 0; i < names.size(); i++) + { + nameList[i] = names[i].c_str(); + } + BNSetUnknownTypeName(m_object, nameList, names.size()); + delete [] nameList; +} + + +vector UnknownType::GetName() const +{ + size_t size; + char** name = BNGetUnknownTypeName(m_object, &size); + vector result; + for (size_t i = 0; i < size; i++) + { + result.push_back(name[i]); + BNFreeString(name[i]); + } + delete [] name; + return result; +} + + Structure::Structure(BNStructure* s) { m_object = s; -- cgit v1.3.1 From 38caf5265ce660a1d9b337d4183c2bb757d2ddd6 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Sun, 9 Oct 2016 16:32:44 -0400 Subject: Modify binary view init parameter order for compat --- python/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 53d5653b..af5e0b55 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -1040,7 +1040,7 @@ class BinaryView(object): next_address = 0 _associated_data = {} - def __init__(self, parent_view = None, file_metadata = None, handle = None): + def __init__(self, file_metadata = None, parent_view = None, handle = None): if handle is not None: self.handle = core.handle_of_type(handle, core.BNBinaryView) if file_metadata is None: -- cgit v1.3.1 From 70dd487931d7bcd75e10753a741fba3299488327 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 10 Oct 2016 16:46:21 -0400 Subject: Rename data to session_data, as this API is per-session and not stored in the db --- python/__init__.py | 12 ++++++------ python/examples/angr_plugin.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index f5a46798..bfd2358f 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -243,7 +243,7 @@ class FileMetadata(object): del cls._associated_data[handle.value] @classmethod - def set_default_data(cls, name, value): + def set_default_session_data(cls, name, value): _FileMetadataAssociatedDataStore.set_default(name, value) @property @@ -324,7 +324,7 @@ class FileMetadata(object): self.nav = value @property - def data(self): + def session_data(self): """Dictionary object where plugins can store arbitrary data associated with the file""" handle = ctypes.cast(self.handle, ctypes.c_void_p) if handle.value not in FileMetadata._associated_data: @@ -1096,7 +1096,7 @@ class BinaryView(object): del cls._associated_data[handle.value] @classmethod - def set_default_data(cls, name, value): + def set_default_session_data(cls, name, value): _BinaryViewAssociatedDataStore.set_default(name, value) def __del__(self): @@ -1311,7 +1311,7 @@ class BinaryView(object): return result @property - def data(self): + def session_data(self): """Dictionary object where plugins can store arbitrary data associated with the view""" handle = ctypes.cast(self.handle, ctypes.c_void_p) if handle.value not in BinaryView._associated_data: @@ -4589,7 +4589,7 @@ class Function(object): del cls._associated_data[handle.value] @classmethod - def set_default_data(cls, name, value): + def set_default_session_data(cls, name, value): _FunctionAssociatedDataStore.set_default(name, value) @property @@ -4717,7 +4717,7 @@ class Function(object): return result @property - def data(self): + def session_data(self): """Dictionary object where plugins can store arbitrary data associated with the function""" handle = ctypes.cast(self.handle, ctypes.c_void_p) if handle.value not in Function._associated_data: diff --git a/python/examples/angr_plugin.py b/python/examples/angr_plugin.py index 5d567511..c6e6f87d 100644 --- a/python/examples/angr_plugin.py +++ b/python/examples/angr_plugin.py @@ -21,8 +21,8 @@ import os logging.disable(logging.WARNING) # Create sets in the BinaryView's data field to store the desired path for each view -BinaryView.set_default_data("angr_find", set()) -BinaryView.set_default_data("angr_avoid", set()) +BinaryView.set_default_session_data("angr_find", set()) +BinaryView.set_default_session_data("angr_avoid", set()) def escaped_output(str): return '\n'.join([s.encode("string_escape") for s in str.split('\n')]) @@ -89,7 +89,7 @@ def find_instr(bv, addr): block.function.set_auto_instr_highlight(block.arch, addr, GreenHighlightColor) # Add the instruction to the list associated with the current view - bv.data.angr_find.add(addr) + bv.session_data.angr_find.add(addr) def avoid_instr(bv, addr): # Highlight the instruction in red @@ -99,17 +99,17 @@ def avoid_instr(bv, addr): block.function.set_auto_instr_highlight(block.arch, addr, RedHighlightColor) # Add the instruction to the list associated with the current view - bv.data.angr_avoid.add(addr) + bv.session_data.angr_avoid.add(addr) def solve(bv): - if len(bv.data.angr_find) == 0: + if len(bv.session_data.angr_find) == 0: show_message_box("Angr Solve", "You have not specified a goal instruction.\n\n" + "Please right click on the goal instruction and select \"Find Path to This Instruction\" to " + "continue.", OKButtonSet, ErrorIcon) return # Start a solver thread for the path associated with the view - s = Solver(bv.data.angr_find, bv.data.angr_avoid, bv) + s = Solver(bv.session_data.angr_find, bv.session_data.angr_avoid, bv) s.start() # Register commands for the user to interact with the plugin -- cgit v1.3.1 From 96b81a90b2a2f4663dbf0023dbe657a26935172f Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Wed, 12 Oct 2016 13:33:44 -0400 Subject: Added flags parameter to sign_extend --- python/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 70267678..37edb17a 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -8291,16 +8291,17 @@ class LowLevelILFunction(object): """ return self.expr(core.LLIL_NOT, value.index, size = size, flags = flags) - def sign_extend(self, size, value): + def sign_extend(self, size, value, flags = None): """ ``sign_extend`` two's complement sign-extends the expression in ``value`` to ``size`` bytes :param int size: the size of the result in bytes :param LowLevelILExpr value: the expression to sign extend + :param str flags: optional, flags to set :return: The expression ``sx.(value)`` :rtype: LowLevelILExpr """ - return self.expr(core.LLIL_SX, value.index, size = size) + return self.expr(core.LLIL_SX, value.index, size = size, flags = flags) def zero_extend(self, size, value): """ -- cgit v1.3.1 From 253fc58d774f74edd47724eaec0197fc41561112 Mon Sep 17 00:00:00 2001 From: plafosse Date: Sun, 16 Oct 2016 23:31:06 -0400 Subject: bug fix in gnu3_demangle python api --- python/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 70267678..0ba0f1a5 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -11015,12 +11015,12 @@ def demangle_ms(arch, mangled_name): return (None, mangledName) -def demangle_gnu3(arch, mangledName): +def demangle_gnu3(arch, mangled_name): handle = ctypes.POINTER(core.BNType)() outName = ctypes.POINTER(ctypes.c_char_p)() outSize = ctypes.c_ulonglong() names = [] - if core.BNDemangleGNU3(arch.handle, mangledName, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize)): + if core.BNDemangleGNU3(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize)): for i in xrange(outSize.value): names.append(outName[i]) #core.BNFreeDemangledName(outName.value, outSize.value) -- cgit v1.3.1 From 0ccbd5f5fe3e646ac18ea013bb443a2b5b29b609 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 20 Oct 2016 18:28:43 -0400 Subject: Add associated arch API to Python --- python/__init__.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 70267678..63916b1f 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -6011,6 +6011,8 @@ class Architecture(object): self._cb.getDefaultIntegerSize = self._cb.getDefaultIntegerSize.__class__(self._get_default_integer_size) self._cb.getMaxInstructionLength = self._cb.getMaxInstructionLength.__class__(self._get_max_instruction_length) self._cb.getOpcodeDisplayLength = self._cb.getOpcodeDisplayLength.__class__(self._get_opcode_display_length) + self._cb.getAssociatedArchitectureByAddress = self._cb.getAssociatedArchitectureByAddress.__class__( + self._get_associated_arch_by_address) 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) @@ -6200,6 +6202,15 @@ class Architecture(object): log_error(traceback.format_exc()) return 8 + def _get_associated_arch_by_address(self, ctxt, addr): + try: + result, new_addr = self.perform_get_associated_arch_by_address(addr[0]) + addr[0] = new_addr + return ctypes.cast(result.handle, ctypes.c_void_p).value + except: + log_error(traceback.format_exc()) + return ctypes.cast(self.handle, ctypes.c_void_p).value + def _get_instruction_info(self, ctxt, data, addr, max_len, result): try: buf = ctypes.create_string_buffer(max_len) @@ -6609,6 +6620,9 @@ class Architecture(object): log_error(traceback.format_exc()) return False + def perform_get_associated_arch_by_address(self, addr): + return self, addr + @abc.abstractmethod def perform_get_instruction_info(self, data, addr): """ @@ -6859,6 +6873,12 @@ class Architecture(object): """ return None + def get_associated_arch_by_address(self, addr): + new_addr = ctypes.c_ulonglong() + new_addr.value = addr + result = core.BNGetAssociatedArchitectureByAddress(self.handle, new_addr) + return Architecture(handle = result), new_addr.value + def get_instruction_info(self, data, addr): """ ``get_instruction_info`` returns an InstructionInfo object for the instruction at the given virtual address -- cgit v1.3.1 From 5cfb38e1c3178195935b969201dd7e42419ea671 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 24 Oct 2016 18:40:20 -0400 Subject: Add related platform API to Python --- python/__init__.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 63916b1f..6db17545 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -9713,6 +9713,15 @@ class Platform(object): """ core.BNRegisterPlatformCallingConvention(self.handle, cc.handle) + def get_related_platform(self, arch): + result = core.BNGetRelatedPlatform(self.handle, arch.handle) + if not result: + return None + return Platform(None, handle = result) + + def add_related_platform(self, arch, platform): + core.BNAddRelatedPlatform(self.handle, arch.handle, platform.handle) + class ScriptingOutputListener(object): def _register(self, handle): self._cb = core.BNScriptingOutputListener() -- cgit v1.3.1 From 6b307f7cad00e4d89e5ed66b9d67e374078f8b95 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 24 Oct 2016 19:00:23 -0400 Subject: Add platform property to function --- python/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 6db17545..8176b8e6 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -4788,6 +4788,14 @@ class Function(object): return None return Architecture(arch) + @property + def platform(self): + """Function platform (read-only)""" + platform = core.BNGetFunctionPlatform(self.handle) + if platform is None: + return None + return Platform(None, handle = platform) + @property def start(self): """Function start (read-only)""" -- cgit v1.3.1 From eef9d1eff05975c31862db4157ac2f1b2bb30502 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 31 Oct 2016 22:51:44 -0400 Subject: Added APIs for dealing with Thumb more easily --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 3 +++ binaryview.cpp | 7 +++++++ platform.cpp | 9 +++++++++ python/__init__.py | 21 +++++++++++++++++++++ 5 files changed, 42 insertions(+) (limited to 'python/__init__.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 6311271c..a918fc42 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -926,6 +926,7 @@ namespace BinaryNinja std::vector> GetSymbolsOfType(BNSymbolType type, uint64_t start, uint64_t len); void DefineAutoSymbol(Ref sym); + void DefineAutoSymbolAndVariableOrFunction(Ref platform, Ref sym, Ref type); void UndefineAutoSymbol(Ref sym); void DefineUserSymbol(Ref sym); @@ -2243,6 +2244,7 @@ namespace BinaryNinja Ref GetRelatedPlatform(Architecture* arch); void AddRelatedPlatform(Architecture* arch, Platform* platform); + Ref GetAssociatedPlatformByAddress(uint64_t& addr); }; class ScriptingOutputListener diff --git a/binaryninjacore.h b/binaryninjacore.h index ea81c388..b2ed7cd3 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1877,6 +1877,8 @@ extern "C" BINARYNINJACOREAPI void BNDefineUserSymbol(BNBinaryView* view, BNSymbol* sym); BINARYNINJACOREAPI void BNUndefineUserSymbol(BNBinaryView* view, BNSymbol* sym); BINARYNINJACOREAPI void BNDefineImportedFunction(BNBinaryView* view, BNSymbol* importAddressSym, BNFunction* func); + BINARYNINJACOREAPI void BNDefineAutoSymbolAndVariableOrFunction(BNBinaryView* view, BNPlatform* platform, + BNSymbol* sym, BNType* type); BINARYNINJACOREAPI BNSymbol* BNImportedFunctionFromImportAddressSymbol(BNSymbol* sym, uint64_t addr); @@ -2135,6 +2137,7 @@ extern "C" BINARYNINJACOREAPI BNPlatform* BNGetRelatedPlatform(BNPlatform* platform, BNArchitecture* arch); BINARYNINJACOREAPI void BNAddRelatedPlatform(BNPlatform* platform, BNArchitecture* arch, BNPlatform* related); + BINARYNINJACOREAPI BNPlatform* BNGetAssociatedPlatformByAddress(BNPlatform* platform, uint64_t* addr); //Demangler BINARYNINJACOREAPI bool BNDemangleMS(BNArchitecture* arch, diff --git a/binaryview.cpp b/binaryview.cpp index ff19de18..cc6667c5 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1156,6 +1156,13 @@ void BinaryView::DefineAutoSymbol(Ref sym) } +void BinaryView::DefineAutoSymbolAndVariableOrFunction(Ref platform, Ref sym, Ref type) +{ + BNDefineAutoSymbolAndVariableOrFunction(m_object, platform ? platform->GetObject() : nullptr, sym->GetObject(), + type ? type->GetObject() : nullptr); +} + + void BinaryView::UndefineAutoSymbol(Ref sym) { BNUndefineAutoSymbol(m_object, sym->GetObject()); diff --git a/platform.cpp b/platform.cpp index 9b4053db..7a6571cc 100644 --- a/platform.cpp +++ b/platform.cpp @@ -244,3 +244,12 @@ void Platform::AddRelatedPlatform(Architecture* arch, Platform* platform) { BNAddRelatedPlatform(m_object, arch->GetObject(), platform->GetObject()); } + + +Ref Platform::GetAssociatedPlatformByAddress(uint64_t& addr) +{ + BNPlatform* platform = BNGetAssociatedPlatformByAddress(m_object, &addr); + if (!platform) + return nullptr; + return new Platform(platform); +} diff --git a/python/__init__.py b/python/__init__.py index 6c7e298c..1751fefa 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -2630,6 +2630,21 @@ class BinaryView(object): """ core.BNDefineAutoSymbol(self.handle, sym.handle) + def define_auto_symbol_and_var_or_function(self, sym, sym_type, platform = None): + """ + ``define_auto_symbol`` adds a symbol to the internal list of automatically discovered Symbol objects. + + :param Symbol sym: the symbol to define + :rtype: None + """ + if platform is None: + platform = self.platform + if platform is not None: + platform = platform.handle + if sym_type is not None: + sym_type = sym_type.handle + core.BNDefineAutoSymbolAndVariableOrFunction(self.handle, platform, sym.handle, sym_type) + def undefine_auto_symbol(self, sym): """ ``undefine_auto_symbol`` removes a symbol from the internal list of automatically discovered Symbol objects. @@ -9730,6 +9745,12 @@ class Platform(object): def add_related_platform(self, arch, platform): core.BNAddRelatedPlatform(self.handle, arch.handle, platform.handle) + def get_associated_platform_by_address(self, addr): + new_addr = ctypes.c_ulonglong() + new_addr.value = addr + result = core.BNGetAssociatedPlatformByAddress(self.handle, new_addr) + return Platform(None, handle = result), new_addr.value + class ScriptingOutputListener(object): def _register(self, handle): self._cb = core.BNScriptingOutputListener() -- cgit v1.3.1 From fdad629b8e9d859607d70d2712eee1684fd31614 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Mon, 7 Nov 2016 19:59:38 -0500 Subject: updated documentation for get_code_refs --- python/__init__.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 1751fefa..a855d991 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -2490,6 +2490,19 @@ class BinaryView(object): return BasicBlock(self, block) def get_code_refs(self, addr, length = None): + """ + ``get_code_refs`` returns a list of ReferenceSource objects (xrefs or cross-references) that point to the provided virtual address. + + :param int addr: virtual address to query for references + :return: List of References for the given virtual address + :rtype: list(ReferenceSource) + :Example: + + >>> bv.get_code_refs(here) + [] + >>> + + """ count = ctypes.c_ulonglong(0) if length is None: refs = core.BNGetCodeReferences(self.handle, addr, count) -- cgit v1.3.1 From bd3117ef0e09276a77ada277413743776ffc9ce1 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Wed, 9 Nov 2016 01:17:02 -0500 Subject: missing function names --- python/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index a855d991..5e147ad5 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -3996,7 +3996,7 @@ class BinaryWriter(object): def write16(self, value): """ - ```` writes the lowest order two bytes from the integer ``value`` to the current offset, using internal endianness. + ``write16`` writes the lowest order two bytes from the integer ``value`` to the current offset, using internal endianness. :param int value: integer value to write. :return: boolean True on success, False on failure. @@ -4006,7 +4006,7 @@ class BinaryWriter(object): def write32(self, value): """ - ```` writes the lowest order four bytes from the integer ``value`` to the current offset, using internal endianness. + ``write32`` writes the lowest order four bytes from the integer ``value`` to the current offset, using internal endianness. :param int value: integer value to write. :return: boolean True on success, False on failure. @@ -4016,7 +4016,7 @@ class BinaryWriter(object): def write64(self, value): """ - ```` writes the lowest order eight bytes from the integer ``value`` to the current offset, using internal endianness. + ``write64`` writes the lowest order eight bytes from the integer ``value`` to the current offset, using internal endianness. :param int value: integer value to write. :return: boolean True on success, False on failure. -- cgit v1.3.1 From 62a052ba5872e208f49fcf9ed3521e7ba1d1b2f0 Mon Sep 17 00:00:00 2001 From: lucasduffey Date: Wed, 16 Nov 2016 18:05:49 -0800 Subject: usage for set_default_session_data --- python/__init__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 4c28e822..64763b71 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -1157,6 +1157,16 @@ class BinaryView(object): @classmethod def set_default_session_data(cls, name, value): + """ + ```set_default_session_data``` saves a variable to the BinaryView. + :param name: name of the variable to be saved + :param value: value of the variable to be saved + + :Example: + >>> BinaryView.set_default_session_data("variable_name", "value") + >>> bv.session_data.variable_name + 'value' + """ _BinaryViewAssociatedDataStore.set_default(name, value) def __del__(self): -- cgit v1.3.1 From 3b719e990e3e01242918bf66d5a1fb6032517641 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 29 Nov 2016 15:52:43 -0500 Subject: fix int Type --- python/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 64763b71..c5b7e5be 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -4342,8 +4342,9 @@ class Type(object): return Type(core.BNCreateBoolType()) @classmethod - def int(self, width, sign = True): - return Type(core.BNCreateIntegerType(width, sign)) + def int(self, width, sign = True, altname = ""): + return Type(core.BNCreateIntegerType(width, sign, + ctypes.create_string_buffer(altname))) @classmethod def float(self, width): -- cgit v1.3.1