def perform_custom_request(self, method, url, headers, data): try: proxy_setting = Settings().get_string('downloadClient.httpsProxy') if proxy_setting: proxies = {"https": proxy_setting} else: proxies = None r = requests.request(pyNativeStr(method), pyNativeStr(url), headers=headers, data=data, proxies=proxies) response = r.content if len(response) == 0: core.BNSetErrorForDownloadInstance(self.handle, "No data received from server!") return None raw_bytes = (ctypes.c_ubyte * len(response)).from_buffer_copy(response) bytes_wrote = core.BNWriteDataForDownloadInstance(self.handle, raw_bytes, len(raw_bytes)) if bytes_wrote != len(raw_bytes): core.BNSetErrorForDownloadInstance(self.handle, "Bytes written mismatch!") return None continue_download = core.BNNotifyProgressForDownloadInstance(self.handle, bytes_wrote, bytes_wrote) if continue_download is False: core.BNSetErrorForDownloadInstance(self.handle, "Download aborted!") return None return DownloadInstance.Response(r.status_code, r.headers, None) except requests.RequestException as e: core.BNSetErrorForDownloadInstance(self.handle, e.__class__.__name__) return None except: core.BNSetErrorForDownloadInstance(self.handle, "Unknown Exception!") log.log_error(traceback.format_exc()) return None
def _perform_custom_request(self, ctxt, method, url, header_count, header_keys, header_values, response): # Cast response to an array of length 1 so ctypes can write to the pointer # out_response = ((BNDownloadInstanceResponse*)[1])response out_response = (ctypes.POINTER(core.BNDownloadInstanceResponse) * 1).from_address(ctypes.addressof(response.contents)) try: # Extract headers keys_ptr = ctypes.cast(header_keys, ctypes.POINTER(ctypes.c_char_p)) values_ptr = ctypes.cast(header_values, ctypes.POINTER(ctypes.c_char_p)) header_key_array = (ctypes.c_char_p * header_count).from_address( ctypes.addressof(keys_ptr.contents)) header_value_array = (ctypes.c_char_p * header_count).from_address( ctypes.addressof(values_ptr.contents)) headers = {} for i in range(header_count): headers[header_key_array[i]] = header_value_array[i] # Read all data data = b'' while True: read_buffer = ctypes.create_string_buffer(0x1000) read_len = core.BNReadDataForDownloadInstance( self.handle, ctypes.cast(read_buffer, ctypes.POINTER(ctypes.c_uint8)), 0x1000) if read_len == 0: break data += read_buffer[:read_len] py_response = self.perform_custom_request(method, url, headers, data) if py_response is not None: # Assign to an instance variable so the memory stays live until the request is done self.bn_response = core.BNDownloadInstanceResponse() self.bn_response.statusCode = py_response.status_code self.bn_response.headerCount = len(py_response.headers) self.bn_response.headerKeys = (ctypes.c_char_p * len(py_response.headers))() self.bn_response.headerValues = (ctypes.c_char_p * len(py_response.headers))() for i, (key, value) in enumerate(py_response.headers.items()): self.bn_response.headerKeys[i] = core.BNAllocString( pyNativeStr(key)) self.bn_response.headerValues[i] = core.BNAllocString( pyNativeStr(value)) out_response[0] = ctypes.pointer(self.bn_response) else: out_response[0] = None return 0 if py_response is not None else -1 except: out_response[0] = None log.log_error(traceback.format_exc()) return -1
def demangle_ms(arch, mangled_name): """ ``demangle_ms`` demangles a mangled Microsoft Visual Studio C++ name to a Type object. :param Architecture arch: Architecture for the symbol. Required for pointer and integer sizes. :param str mangled_name: a mangled Microsoft Visual Studio C++ name :return: returns tuple of (Type, demangled_name) or (None, mangled_name) on error :rtype: Tuple :Example: >>> demangle_ms(Architecture["x86_64"], "?testf@Foobar@@SA?AW4foo@1@W421@@Z") (<type: public: static enum Foobar::foo __cdecl (enum Foobar::foo)>, ['Foobar', 'testf']) >>> """ handle = ctypes.POINTER(core.BNType)() outName = ctypes.POINTER(ctypes.c_char_p)() outSize = ctypes.c_ulonglong() names = [] if core.BNDemangleMS(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize)): for i in range(outSize.value): names.append(pyNativeStr(outName[i])) core.BNFreeDemangledName(ctypes.byref(outName), outSize.value) return (types.Type(handle), names) return (None, mangled_name)
def demangle_ms(arch, mangled_name, options=False): """ ``demangle_ms`` demangles a mangled Microsoft Visual Studio C++ name to a Type object. :param Architecture arch: Architecture for the symbol. Required for pointer and integer sizes. :param str mangled_name: a mangled Microsoft Visual Studio C++ name :param options: (optional) Whether to simplify demangled names : None falls back to user settings, a BinaryView uses that BinaryView's settings, or a boolean to set it directally :type options: Tuple[bool, BinaryView, None] :return: returns tuple of (Type, demangled_name) or (None, mangled_name) on error :rtype: Tuple :Example: >>> demangle_ms(Architecture["x86_64"], "?testf@Foobar@@SA?AW4foo@1@W421@@Z") (<type: public: static enum Foobar::foo __cdecl (enum Foobar::foo)>, ['Foobar', 'testf']) >>> """ handle = ctypes.POINTER(core.BNType)() outName = ctypes.POINTER(ctypes.c_char_p)() outSize = ctypes.c_ulonglong() names = [] if (isinstance(options, BinaryView) and core.BNDemangleMSWithOptions(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize), options)) or \ (isinstance(options, bool) and core.BNDemangleMS(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize), options)) or \ (options is None and core.BNDemangleMSWithOptions(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize), None)): for i in range(outSize.value): names.append(pyNativeStr(outName[i])) core.BNFreeDemangledName(ctypes.byref(outName), outSize.value) return (types.Type(handle), names) return (None, mangled_name)
def demangle_gnu3(arch, mangled_name, options=None): """ ``demangle_gnu3`` demangles a mangled name to a Type object. :param Architecture arch: Architecture for the symbol. Required for pointer and integer sizes. :param str mangled_name: a mangled GNU3 name :param options: (optional) Whether to simplify demangled names : None falls back to user settings, a BinaryView uses that BinaryView's settings, or a boolean to set it directally :type options: Tuple[bool, BinaryView, None] :return: returns tuple of (Type, demangled_name) or (None, mangled_name) on error :rtype: Tuple """ handle = ctypes.POINTER(core.BNType)() outName = ctypes.POINTER(ctypes.c_char_p)() outSize = ctypes.c_ulonglong() names = [] if (isinstance(options, BinaryView) and core.BNDemangleGNU3WithOptions(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize), options)) or \ (isinstance(options, bool) and core.BNDemangleGNU3(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize), options)) or \ (options is None and core.BNDemangleGNU3WithOptions(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize), None)): for i in range(outSize.value): names.append(pyNativeStr(outName[i])) core.BNFreeDemangledName(ctypes.byref(outName), outSize.value) if not handle: return (None, names) return (types.Type(handle), names) return (None, mangled_name)
def perform_request(self, url): try: proxy_setting = Settings().get_string('downloadClient.httpsProxy') if proxy_setting: proxies = {"https": proxy_setting} else: proxies = None r = requests.get(pyNativeStr(url), proxies=proxies) if not r.ok: core.BNSetErrorForDownloadInstance(self.handle, "Received error from server") return -1 data = r.content if len(data) == 0: core.BNSetErrorForDownloadInstance(self.handle, "No data received from server!") return -1 raw_bytes = (ctypes.c_ubyte * len(data)).from_buffer_copy(data) bytes_wrote = core.BNWriteDataForDownloadInstance(self.handle, raw_bytes, len(raw_bytes)) if bytes_wrote != len(raw_bytes): core.BNSetErrorForDownloadInstance(self.handle, "Bytes written mismatch!") return -1 continue_download = core.BNNotifyProgressForDownloadInstance(self.handle, bytes_wrote, bytes_wrote) if continue_download is False: core.BNSetErrorForDownloadInstance(self.handle, "Download aborted!") return -1 except requests.RequestException as e: core.BNSetErrorForDownloadInstance(self.handle, e.__class__.__name__) return -1 except: core.BNSetErrorForDownloadInstance(self.handle, "Unknown Exception!") log.log_error(traceback.format_exc()) return -1 return 0
def keys(self): length = ctypes.c_ulonglong() result = core.BNSettingsKeysList(self.handle, ctypes.byref(length)) out_list = [] for i in range(length.value): out_list.append(pyNativeStr(result[i])) core.BNFreeStringList(result, length) return out_list
def query_property_string_list(self, key, property_name): length = ctypes.c_ulonglong() result = core.BNSettingsQueryPropertyStringList(self.handle, key, property_name, ctypes.byref(length)) out_list = [] for i in range(length.value): out_list.append(pyNativeStr(result[i])) core.BNFreeStringList(result, length) return out_list
def existing_views(self): length = ctypes.c_ulonglong() result = core.BNGetExistingViews(self.handle, ctypes.byref(length)) views = [] for i in range(length.value): views.append(pyNativeStr(result[i])) core.BNFreeStringList(result, length) return views
def __init__(self, name=[]): if isinstance(name, str): self.name = [name] self.byte_name = [name.encode('charmap')] elif isinstance(name, QualifiedName): self.name = name.name self.byte_name = [n.encode('charmap') for n in name.name] else: self.name = [pyNativeStr(i) for i in name] self.byte_name = name
def __init__(self, name = []): if isinstance(name, str): self.name = [name] self.byte_name = [name.encode('charmap')] elif isinstance(name, QualifiedName): self.name = name.name self.byte_name = [n.encode('charmap') for n in name.name] else: self.name = [pyNativeStr(i) for i in name] self.byte_name = name
def get_string_list(self, key, view = None): if view is not None: view = view.handle length = ctypes.c_ulonglong() result = core.BNSettingsGetStringList(self.handle, key, view, None, ctypes.byref(length)) out_list = [] for i in range(length.value): out_list.append(pyNativeStr(result[i])) core.BNFreeStringList(result, length) return out_list
def get_string_list(self, id, view = None): if view is not None: view = view.handle length = ctypes.c_ulonglong() result = core.BNSettingsGetStringList(self.registry_id, id, view, None, ctypes.byref(length)) out_list = [] for i in range(length.value): out_list.append(pyNativeStr(result[i])) core.BNFreeStringList(result, length) return out_list
def get_string_list_with_scope(self, key, view = None, scope = SettingsScope.SettingsAutoScope): if view is not None: view = view.handle c_scope = core.SettingsScopeEnum(scope) length = ctypes.c_ulonglong() result = core.BNSettingsGetStringList(self.handle, key, view, ctypes.byref(c_scope), ctypes.byref(length)) out_list = [] for i in range(length.value): out_list.append(pyNativeStr(result[i])) core.BNFreeStringList(result, length) return (out_list, SettingsScope(c_scope.value))
def get_string_list_with_scope(self, id, view = None, scope = SettingsScope.SettingsAutoScope): if view is not None: view = view.handle c_scope = core.SettingsScopeEnum(scope) length = ctypes.c_ulonglong() result = core.BNSettingsGetStringList(self.registry_id, id, view, ctypes.byref(c_scope), ctypes.byref(length)) out_list = [] for i in range(length.value): out_list.append(pyNativeStr(result[i])) core.BNFreeStringList(result, length) return (out_list, SettingsScope(c_scope.value))
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, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize)): for i in range(outSize.value): names.append(pyNativeStr(outName[i])) core.BNFreeDemangledName(ctypes.byref(outName), outSize.value) if not handle: return (None, names) return (types.Type(handle), names) return (None, mangled_name)
def get_string_list(self, name, default_value=[]): length = ctypes.c_ulonglong() length.value = len(default_value) default_list = (ctypes.c_char_p * len(default_value))() for i in range(len(default_value)): default_list[i] = default_value[i].encode('charmap') result = core.BNSettingGetStringList(self.plugin_name, name, default_list, ctypes.byref(length)) out_list = [] for i in range(length.value): out_list.append(pyNativeStr(result[i])) core.BNFreeStringList(result, length) return out_list
def keys(self): """ ``keys`` retrieve the list of setting identifiers in the active settings schema :return: list of setting identifiers :rtype: list(str) """ length = ctypes.c_ulonglong() result = core.BNSettingsKeysList(self.handle, ctypes.byref(length)) out_list = [] for i in range(length.value): out_list.append(pyNativeStr(result[i])) core.BNFreeStringList(result, length) return out_list
def perform_request(self, url): try: proxy_setting = Settings().get_string( 'downloadClient.httpsProxy') if proxy_setting: opener = build_opener( ProxyHandler({'https': proxy_setting})) install_opener(opener) r = urlopen(pyNativeStr(url)) total_size = int(r.headers.get('content-length', 0)) bytes_sent = 0 while True: data = r.read(4096) if not data: break raw_bytes = (ctypes.c_ubyte * len(data)).from_buffer_copy(data) bytes_wrote = core.BNWriteDataForDownloadInstance( self.handle, raw_bytes, len(raw_bytes)) if bytes_wrote != len(raw_bytes): core.BNSetErrorForDownloadInstance( self.handle, "Bytes written mismatch!") return -1 bytes_sent = bytes_sent + bytes_wrote continue_download = core.BNNotifyProgressForDownloadInstance( self.handle, bytes_sent, total_size) if continue_download is False: core.BNSetErrorForDownloadInstance( self.handle, "Download aborted!") return -1 if not bytes_sent: core.BNSetErrorForDownloadInstance(self.handle, "Received no data!") return -1 except URLError as e: core.BNSetErrorForDownloadInstance(self.handle, e.__class__.__name__) log.log_error(str(e)) return -1 except: core.BNSetErrorForDownloadInstance(self.handle, "Unknown Exception!") log.log_error(traceback.format_exc()) return -1 return 0
def __iter__(self): if self.is_array: for i in range(core.BNMetadataSize(self.handle)): yield Metadata(handle=core.BNMetadataGetForIndex(self.handle, i)).value elif self.is_dict: result = core.BNMetadataGetValueStore(self.handle) try: for i in range(result.contents.size): if isinstance(result.contents.keys[i], bytes): yield str(pyNativeStr(result.contents.keys[i])) else: yield result.contents.keys[i] finally: core.BNFreeMetadataValueStore(result) else: raise Exception("Metadata object doesn't support iteration")
def __iter__(self): if self.is_array: for i in range(core.BNMetadataSize(self.handle)): yield Metadata( handle=core.BNMetadataGetForIndex(self.handle, i)).value elif self.is_dict: result = core.BNMetadataGetValueStore(self.handle) try: for i in range(result.contents.size): if isinstance(result.contents.keys[i], bytes): yield str(pyNativeStr(result.contents.keys[i])) else: yield result.contents.keys[i] finally: core.BNFreeMetadataValueStore(result) else: raise Exception("Metadata object doesn't support iteration")
def perform_custom_request(self, method, url, headers, data): result = None try: proxy_setting = Settings().get_string('downloadClient.httpsProxy') if proxy_setting: opener = build_opener(ProxyHandler({'https': proxy_setting})) install_opener(opener) if b"Content-Length" in headers: del headers[b"Content-Length"] req = PythonDownloadInstance.CustomRequest(pyNativeStr(url), data=data, headers=headers, method=pyNativeStr(method)) result = urlopen(req) except HTTPError as he: result = he except URLError as e: core.BNSetErrorForDownloadInstance(self.handle, e.__class__.__name__) log.log_error(str(e)) return None except: core.BNSetErrorForDownloadInstance(self.handle, "Unknown Exception!") log.log_error(traceback.format_exc()) return None total_size = int(result.headers.get('content-length', 0)) bytes_sent = 0 while True: data = result.read(4096) if not data: break raw_bytes = (ctypes.c_ubyte * len(data)).from_buffer_copy(data) bytes_wrote = core.BNWriteDataForDownloadInstance(self.handle, raw_bytes, len(raw_bytes)) if bytes_wrote != len(raw_bytes): core.BNSetErrorForDownloadInstance(self.handle, "Bytes written mismatch!") return None bytes_sent = bytes_sent + bytes_wrote continue_download = core.BNNotifyProgressForDownloadInstance(self.handle, bytes_sent, total_size) if continue_download is False: core.BNSetErrorForDownloadInstance(self.handle, "Download aborted!") return None if not bytes_sent: core.BNSetErrorForDownloadInstance(self.handle, "Received no data!") return None return DownloadInstance.Response(result.getcode(), result.headers, None)
def perform_request(self, url): try: proxy_setting = Settings().get_string('downloadClient.httpsProxy') if proxy_setting: opener = build_opener(ProxyHandler({'https': proxy_setting})) install_opener(opener) r = urlopen(pyNativeStr(url)) total_size = int(r.headers.get('content-length', 0)) bytes_sent = 0 while True: data = r.read(4096) if not data: break raw_bytes = (ctypes.c_ubyte * len(data)).from_buffer_copy(data) bytes_wrote = core.BNWriteDataForDownloadInstance(self.handle, raw_bytes, len(raw_bytes)) if bytes_wrote != len(raw_bytes): core.BNSetErrorForDownloadInstance(self.handle, "Bytes written mismatch!") return -1 bytes_sent = bytes_sent + bytes_wrote continue_download = core.BNNotifyProgressForDownloadInstance(self.handle, bytes_sent, total_size) if continue_download is False: core.BNSetErrorForDownloadInstance(self.handle, "Download aborted!") return -1 if not bytes_sent: core.BNSetErrorForDownloadInstance(self.handle, "Received no data!") return -1 except URLError as e: core.BNSetErrorForDownloadInstance(self.handle, e.__class__.__name__) return -1 except: core.BNSetErrorForDownloadInstance(self.handle, "Unknown Exception!") log.log_error(traceback.format_exc()) return -1 return 0
def __str__(self): buf = ctypes.create_string_buffer(len(self)) ctypes.memmove(buf, core.BNGetDataBufferContents(self.handle), len(self)) return pyNativeStr(buf.raw)