def preprocess_source(source, filename=None, include_dirs=[]): """ ``preprocess_source`` run the C preprocessor on the given source or source filename. :param str source: source to pre-process :param str filename: optional filename to pre-process :param list(str) include_dirs: list of string directories to use as include directories. :return: returns a tuple of (preprocessed_source, error_string) :rtype: tuple(str,str) :Example: >>> source = "#define TEN 10\\nint x[TEN];\\n" >>> preprocess_source(source) ('#line 1 "input"\\n\\n#line 2 "input"\\n int x [ 10 ] ;\\n', '') >>> """ if filename is None: filename = "input" dir_buf = (ctypes.c_char_p * len(include_dirs))() for i in range(0, len(include_dirs)): dir_buf[i] = include_dirs[i].encode('charmap') 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 get_open_filename_input(prompt, ext=""): """ ``get_open_filename_input`` prompts the user for a file name to open Note: This API function differently on the command-line vs the UI. In the UI a pop-up is used. On the command-line a simple text prompt is used. The UI uses the native window pop-up for file selection. Multiple file selection groups can be included if separated by two semicolons. Multiple file wildcards may be specified by using a space within the parenthesis. Also, a simple selector of "*.extension" by itself may also be used instead of specifying the description. :param str prompt: Prompt to display. :param str ext: Optional, file extension :Example: >>> get_open_filename_input("filename:", "Executables (*.exe *.com);;Python Files (*.py);;All Files (*)") b'foo.exe' >>> get_open_filename_input("filename:", "*.py") b'test.py' """ value = ctypes.c_char_p() if not core.BNGetOpenFileNameInput(value, prompt, ext): return None result = value.value core.BNFreeString(ctypes.cast(value, ctypes.POINTER(ctypes.c_byte))) return result
def parse_types_from_source(self, source, filename=None, include_dirs=[], auto_type_source=None): """ ``parse_types_from_source`` parses the source string and any needed headers searching for them in the optional list of directories provided in ``include_dirs``. :param str source: source string to be parsed :param str filename: optional source filename :param list(str) include_dirs: optional list of string filename include directories :param str auto_type_source: optional source of types if used for automatically generated types :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) :rtype: TypeParserResult :Example: >>> platform.parse_types_from_source('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n') ({types: {'bas': <type: struct bas>}, variables: {'foo': <type: int32_t>}, functions:{'bar': <type: int32_t(int32_t x)>}}, '') >>> """ if filename is None: filename = "input" dir_buf = (ctypes.c_char_p * len(include_dirs))() for i in range(0, len(include_dirs)): dir_buf[i] = include_dirs[i].encode('charmap') parse = core.BNTypeParserResult() errors = ctypes.c_char_p() result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, len(include_dirs), auto_type_source) error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: raise SyntaxError(error_str) type_dict = {} variables = {} functions = {} for i in range(0, parse.typeCount): name = types.QualifiedName._from_core_struct(parse.types[i].name) type_dict[name] = types.Type(core.BNNewTypeReference( parse.types[i].type), platform=self) for i in range(0, parse.variableCount): name = types.QualifiedName._from_core_struct( parse.variables[i].name) variables[name] = types.Type(core.BNNewTypeReference( parse.variables[i].type), platform=self) for i in range(0, parse.functionCount): name = types.QualifiedName._from_core_struct( parse.functions[i].name) functions[name] = types.Type(core.BNNewTypeReference( parse.functions[i].type), platform=self) core.BNFreeTypeParserResult(parse) return types.TypeParserResult(type_dict, variables, functions)
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 UpdateResult(result)
def updates_available(self): """Whether updates are available (read-only)""" errors = ctypes.c_char_p() result = core.BNAreUpdatesAvailable(self.name, None, None, errors) if errors: error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise IOError(error_str) return result
def install_pending_update(): """ ``install_pending_update`` installs any pending updates :rtype: None """ errors = ctypes.c_char_p() core.BNInstallPendingUpdate(errors) if errors: error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise IOError(error_str)
def __iter__(self): binaryninja._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) try: for i in range(0, count.value): yield UpdateChannel(channels[i].name, channels[i].description, channels[i].latestVersion) finally: core.BNFreeUpdateChannelList(channels, count.value)
def list(self): binaryninja._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 range(0, count.value): result.append(UpdateChannel(channels[i].name, channels[i].description, channels[i].latestVersion)) core.BNFreeUpdateChannelList(channels, count.value) return result
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 range(0, count.value): result.append(UpdateVersion(self, versions[i].version, versions[i].notes, versions[i].time)) core.BNFreeUpdateChannelVersionList(versions, count.value) return result
def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): """ ``parse_types_from_source_file`` parses the source file ``filename`` and any needed headers searching for them in the optional list of directories provided in ``include_dirs``. :param str filename: filename of file to be parsed :param include_dirs: optional list of string filename include directories :type include_dirs: list(str) :param str auto_type_source: optional source of types if used for automatically generated types :return: :py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) :rtype: TypeParserResult :Example: >>> file = "/Users/binja/tmp.c" >>> open(file).read() 'int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n' >>> platform.parse_types_from_source_file(file) ({types: {'bas': <type: struct bas>}, variables: {'foo': <type: int32_t>}, functions: {'bar': <type: int32_t(int32_t x)>}}, '') >>> """ if not (isinstance(filename, str) and os.path.isfile(filename) and os.access(filename, os.R_OK)): raise AttributeError("File {} doesn't exist or isn't readable".format(filename)) dir_buf = (ctypes.c_char_p * len(include_dirs))() for i in range(0, len(include_dirs)): dir_buf[i] = include_dirs[i].encode('charmap') parse = core.BNTypeParserResult() errors = ctypes.c_char_p() result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, len(include_dirs), auto_type_source) error_str = errors.value.decode("utf-8") core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: raise SyntaxError(error_str) type_dict = {} variables = {} functions = {} for i in range(0, parse.typeCount): name = types.QualifiedName._from_core_struct(parse.types[i].name) type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) for i in range(0, parse.variableCount): name = types.QualifiedName._from_core_struct(parse.variables[i].name) variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) for i in range(0, parse.functionCount): name = types.QualifiedName._from_core_struct(parse.functions[i].name) functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) core.BNFreeTypeParserResult(parse) return types.TypeParserResult(type_dict, variables, functions)
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 range(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
def __getitem__(cls, name): binaryninja._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 range(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
def get_directory_name_input(prompt, default_name=""): """ ``get_directory_name_input`` prompts the user for a directory name to save as, optionally providing a default_name Note: This API function differently on the command-line vs the UI. In the UI a pop-up is used. On the command-line a simple text prompt is used. The UI uses the native window pop-up for file selection. :param str prompt: Prompt to display. :param str default_name: Optional, default directory name. :rtype: str :Example: >>> get_directory_name_input("prompt") prompt dirname 'dirname' """ value = ctypes.c_char_p() if not core.BNGetDirectoryNameInput(value, prompt, default_name): return None result = value.value core.BNFreeString(ctypes.cast(value, ctypes.POINTER(ctypes.c_byte))) return result
def get_open_filename_input(prompt, ext=""): """ ``get_open_filename_input`` prompts the user for a file name to open Note: This API function differently on the command-line vs the UI. In the UI a pop-up is used. On the command-line a simple text prompt is used. The UI uses the native window pop-up for file selection. :param str prompt: Prompt to display. :param str ext: Optional, file extension :Example: >>> get_open_filename_input("filename:", "exe") filename: foo.exe 'foo.exe' """ value = ctypes.c_char_p() if not core.BNGetOpenFileNameInput(value, prompt, ext): return None result = value.value core.BNFreeString(ctypes.cast(value, ctypes.POINTER(ctypes.c_byte))) return result
def get_text_line_input(prompt, title): """ ``get_text_line_input`` prompts the user to input a string with the given prompt and title Note: This API function differently on the command-line vs the UI. In the UI a pop-up is used. On the command-line a simple text prompt is used. :param str prompt: String to prompt with. :param str title: Title of the window when executed in the UI. :rtype: str containing the input without trailing newline character. :Example: >>> get_text_line_input("PROMPT>", "getinfo") PROMPT> Input! 'Input!' """ value = ctypes.c_char_p() if not core.BNGetTextLineInput(value, prompt, title): return None result = value.value core.BNFreeString(ctypes.cast(value, ctypes.POINTER(ctypes.c_byte))) return result
def get_save_filename_input(prompt, ext="", default_name=""): """ ``get_save_filename_input`` prompts the user for a file name to save as, optionally providing a file extension and default_name. Note: This API function differently on the command line vs. the UI. In the UI a popup is used. On the commandline a simple text prompt is used. The ui uses the native window popup for file selection. :param str prompt: Prompt to display. :param str ext: Optional, file extension :param str default_name: Optional, default file name. :Example: >>> get_save_filename_input("filename:", "exe", "foo.exe") filename: foo.exe 'foo.exe' """ value = ctypes.c_char_p() if not core.BNGetSaveFileNameInput(value, prompt, ext, default_name): return None result = value.value core.BNFreeString(ctypes.cast(value, ctypes.POINTER(ctypes.c_byte))) return result