def getPE(file): if (PE(file) == True): PEFileInstance = PE(file, data='module.dll') yeet = PEFileInstance.dump_info().strip().split('\n') pedata = [] keys = [ 'SizeOfOptionalHeader', 'Characteristics', 'MajorLinkerVersion', 'MinorLinkerVersion', 'SizeOfCode', 'SizeOfInitializedData', 'SizeOfUninitializedData', 'AddressOfEntryPoint', 'BaseOfCode', 'BaseOfData', 'ImageBase', 'SectionAlignment', 'FileAlignment', 'MajorOperatingSystemVersion', 'MinorOperatingSystemVersion', 'MajorImageVersion', 'MinorImageVersion', 'MajorSubsystemVersion', 'MinorSubsystemVersion', 'SizeOfImage', 'SizeOfHeaders', 'CheckSum', 'Subsystem', 'DllCharacteristics', 'SizeOfStackReserve', 'SizeOfStackCommit', 'SizeOfHeapReserve', 'SizeOfHeapCommit', 'LoaderFlags', 'NumberOfRvaAndSizes', 'SectionsMeanVirtualsize', 'SectionsMinVirtualsize', 'SectionMaxVirtualsize' ] for key in keys: for x in range(len(yeet)): if (yeet[x].find(key) != -1): pedata.append(int(str(yeet[x][48:].strip()), 16)) break print(pedata)
def analyze(self,data): ''' start analyzing exe logic, add descriptions and get words and wordsstripped from the file ''' data["PE"] = deepcopy(self.datastruct) data["ICONS"] = {"ICONS":[]} pe = PE(data["Location"]["File"]) ep = pe.OPTIONAL_HEADER.AddressOfEntryPoint section = self.find_entry_point_function(pe,ep) sig = section.get_data(ep, 12) singinhex = "".join("{:02x}".format(x) for x in sig) data["PE"]["General"] = { "PE Type" : self.what_type(pe), "Entrypoint": pe.OPTIONAL_HEADER.AddressOfEntryPoint, "Entrypoint Section":section.Name.decode("utf-8",errors="ignore").strip("\00"), "Header checksum": hex(pe.OPTIONAL_HEADER.CheckSum), "Verify checksum": hex(pe.generate_checksum()), "Match checksum":pe.verify_checksum(), "Sig":singinhex, "imphash":pe.get_imphash(), "warning":pe.get_warnings() if len(pe.get_warnings())> 0 else "None", "Timestamp":datetime.fromtimestamp(pe.FILE_HEADER.TimeDateStamp).strftime('%Y-%m-%d %H:%M:%S')} data["PE"]["Characteristics"] = self.get_characteristics(pe) data["PE"]["Singed"],data["PE"]["SignatureExtracted"] = self.check_if_singed(pe) data["PE"]["Stringfileinfo"] = self.get_string_file_info(pe) data["PE"]["Sections"] = self.get_sections(pe) data["PE"]["Dlls"] = self.get_dlls(pe) data["PE"]["Resources"],data["PE"]["Manifest"],data["ICONS"]["ICONS"] = self.get_recourse(pe) data["PE"]["Imported functions"] = self.get_imported_functions(pe) data["PE"]["Exported functions"] = self.get_exported_functions(pe) add_description("WinApis",data["PE"]["Imported functions"],"Function") add_description("ManHelp",data["PE"]["Imported functions"],"Function") add_description("WinDlls",data["PE"]["Dlls"],"Dll") add_description("WinSections",data["PE"]["Sections"],"Section") add_description("WinResources",data["PE"]["Resources"],"Resource") get_words(data,data["Location"]["File"])
def fileversion(pename): pe = PE(pename) verinfo = pe.VS_FIXEDFILEINFO[0] filever = (verinfo.FileVersionMS >> 16, verinfo.FileVersionMS & 0xFFFF, verinfo.FileVersionLS >> 16, verinfo.FileVersionLS & 0xFFFF) pe.close() return "%d.%d.%d.%d" % filever
def read(self): try: pe = PE(self.name, fast_load=True) except: print('File %s invalid' % self.name) return False if not pe.is_exe(): print('This file is not exe') pe.close() return False section = None for s in pe.sections: if s.Name == '.enigma1': section = s break if section is None: print('This file is not Enigma Virtual Box container') pe.close() return False self.data = pe.get_data(section.VirtualAddress, section.SizeOfRawData) pe.close() return True
def get_pe_info(target): row = [0] * (len(DLL_API_FEATURES) + len(SECTION_NAMES)) try: pe = PE(target) except PEFormatError: # log.exception("%s, not valid PE File" % target) return None if hasattr(pe, "DIRECTORY_ENTRY_IMPORT"): for entry in pe.DIRECTORY_ENTRY_IMPORT: dll = norm_str(entry.dll) if dll in DLL_API_FEATURES: index = DLL_API_FEATURES.index(dll) row[index] = 1 for imp in entry.imports: api = norm_str(imp.name) if api in DLL_API_FEATURES: index = DLL_API_FEATURES.index(api) row[index] = 1 else: return None for section in pe.sections: se = norm_str(section.Name) if se in SECTION_NAMES: index = SECTION_NAMES.index(se) row[index + len(DLL_API_FEATURES)] = 1 else: row[-1] += 1 # change list to string return ",".join(map(str, row))
def __init__(self, path): self.path = path self.type = 'PE' self.parser = PE(path, fast_load=True) self.parser.parse_data_directories() self.imageBase = self.parser.OPTIONAL_HEADER.ImageBase self.entryPoint = self.parser.OPTIONAL_HEADER.AddressOfEntryPoint self.sections = [] self.stringAddrs = [] self.strings = self.strings() for section in self.parser.sections: s = Section(section.Name.decode().replace('\x00', ''), section.VirtualAddress + self.imageBase, section.Misc_VirtualSize) self.sections.append(s) self.imports = [] for entry in self.parser.DIRECTORY_ENTRY_IMPORT: for imp in entry.imports: importFunc = ImportFunction(imp.name.decode(), imp.address, entry.dll.decode()) self.imports.append(importFunc) self.exports = [] if hasattr(self.parser, "DIRECTORY_ENTRY_EXPORT"): for exp in self.parser.DIRECTORY_ENTRY_EXPORT.symbols: exportFunc = ExportFunction(self.imageBase + exp.address, exp.name.decode()) self.exports.append(exportFunc) self.findStrings()
def _algorithm(self, data): pe = PE(data=data, fast_load=True) pe.parse_data_directories(directories=[IMAGE_DIRECTORY_ENTRY_IMPORT]) th = pe.get_imphash() if not th: raise ValueError('no import directory.') return bytes.fromhex(th)
def get_pe(self, force=False): """ Returns the pefile.PE object if the file is actually a PE Args: force: Disable extension detection for PE files (default False) Returns: pefile.PE None """ if not PEFILE_SUPPORT: return None if force or self.__attrs['path'].suffix in ['.dll', '.exe', '.sys']: try: data = self.get_data() self.pe_data = PE(name=str(self.__attrs['path']), data=data, fast_load=True) return self.pe_data except PEFormatError: return None except Exception: return None return None
def hash_module(imm, module_name): """Calculate an MD5 hash of each section in a given module. The results are displayed in the log window. Args: imm: Immunity debugger object module_name: Name of the module to hash Returns: String describing the success/failure of the operation """ if module_name.split('.')[-1] not in ('exe', 'sys', 'dll'): module_name = '%s.dll' % module_name module = imm.getModule(module_name) if not module: return '%s is not a loaded module' % module_name pe = PE(name=module.getPath()) for section in pe.sections: section_name = section.Name.split('\x00')[0] start = module.getBaseAddress() + section.VirtualAddress virtual_size = section.Misc_VirtualSize alignment = pe.OPTIONAL_HEADER.SectionAlignment size = virtual_size + (alignment - virtual_size % alignment) data = imm.readMemory(start, size) md5sum = md5(data).hexdigest() imm.log('%s %s MD5: %s' % (module.name, section_name, md5sum)) return 'Calculated hash for %s' % module.name
def get_pe_size(pe: Union[PE, ByteString], overlay=True, sections=True, directories=True, cert=True) -> int: """ This fuction determines the size of a PE file, optionally taking into account the pefile module overlay computation, section information, data directory information, and certificate entries. """ if not isinstance(pe, PE): pe = PE(data=pe, fast_load=True) overlay_value = overlay and pe.get_overlay_data_start_offset() or 0 sections_value = sections and max(s.PointerToRawData + s.SizeOfRawData for s in pe.sections) or 0 directories_value = directories and max( pe.get_offset_from_rva(d.VirtualAddress) + d.Size for d in pe.OPTIONAL_HEADER.DATA_DIRECTORY) or 0 if cert: # The certificate overlay is given as a file offset # rather than a virtual address. cert_entry = pe.OPTIONAL_HEADER.DATA_DIRECTORY[ IMAGE_DIRECTORY_ENTRY_SECURITY] cert_value = cert_entry.VirtualAddress + cert_entry.Size else: cert_value = 0 return max(overlay_value, sections_value, directories_value, cert_value)
def initialize(self): self.file_handle = open(self.wow_binary, 'rb') self.handle = mmap.mmap(self.file_handle.fileno(), 0, access=mmap.ACCESS_READ) self.pe = PE(data=self.handle, fast_load=True) logging.info('{} ImageBase={:#016x}'.format( self.wow_binary, self.pe.OPTIONAL_HEADER.ImageBase)) self.image_base = self.pe.OPTIONAL_HEADER.ImageBase for section in self.pe.sections: if b'.rdata' in section.Name: self.rdata_start = section.PointerToRawData self.rdata_end = self.rdata_start + section.SizeOfRawData self.rdata_voffset = section.VirtualAddress logging.info( ('{} .rdata found at PhysicalAddress={:#08x} ' 'VirtualAddress={:#08x}').format(self.wow_binary, self.rdata_start, self.rdata_voffset)) return True
def pdb_guid(file): pe = PE(file, fast_load=True) pe.parse_data_directories() try: codeview = next( filter( lambda x: x.struct.Type == DEBUG_TYPE[ "IMAGE_DEBUG_TYPE_CODEVIEW"], pe.DIRECTORY_ENTRY_DEBUG, )) except StopIteration: print("Failed to find CodeView in pdb") raise RuntimeError("Failed to find GUID age") offset = codeview.struct.PointerToRawData size = codeview.struct.SizeOfData tmp = CV_RSDS_HEADER.parse(pe.__data__[offset:offset + size]) guidstr = "%08x%04x%04x%s%x" % ( tmp.GUID.Data1, tmp.GUID.Data2, tmp.GUID.Data3, hexlify(tmp.GUID.Data4).decode("ascii"), tmp.Age, ) return {"filename": tmp.Filename, "GUID": guidstr}
def process(self, data): pe = PE(data=data, fast_load=True) pe.parse_data_directories(directories=[IMAGE_DIRECTORY_ENTRY_IMPORT]) th = pe.get_imphash() if not th: raise ValueError('no import directory.') return th.encode(self.codec) if self.args.text else bytes.fromhex(th)
def get_version(data): pe = PE(data=data) info = pe.VS_FIXEDFILEINFO[0] return '.'.join( map(str, [ info.FileVersionMS >> 16, info.FileVersionMS & 0xFFFF, info.FileVersionLS >> 16, info.FileVersionLS & 0xFFFF ]))
def main(): argp = ArgumentParser() argp.add_argument('file', type=str) args = argp.parse_args() build_time = datetime.utcfromtimestamp( PE(args.file).FILE_HEADER.TimeDateStamp) print(str(build_time), end='')
def patch_origin_client(self): origin = Client('Origin', 'Origin.exe', 'libeay32.dll', 'EVP_DigestVerifyFinal') eadesktop = Client('EA Desktop', 'EADesktop.exe', 'libcrypto-1_1-x64.dll', 'EVP_DigestVerifyFinal') client = origin try: client_process = Pymem(client.PROCESS_NAME) except ProcessNotFound: client = eadesktop try: client_process = Pymem(client.PROCESS_NAME) except ProcessNotFound: log.warning('Origin/EA Desktop process not found. Patching aborted') return if client_process.process_id == self.last_client_pid: log.debug(f'{client.NAME} client is already patched') return log.info(f'Patching {client.NAME} client') try: dll_module = next(m for m in client_process.list_modules() if m.name.lower() == client.DLL_NAME) except StopIteration: log.error(f'{client.DLL_NAME} is not loaded. Patching aborted') return # The rest should complete without issues in most cases. # Get the Export Address Table symbols # noinspection PyUnresolvedReferences dll_symbols = PE(dll_module.filename).DIRECTORY_ENTRY_EXPORT.symbols # Get the symbol of the EVP_DigestVerifyFinal function verify_func_symbol = next(s for s in dll_symbols if s.name.decode('ascii') == client.FUNCTION_NAME) # Calculate the final address in memory verify_func_addr = dll_module.lpBaseOfDll + verify_func_symbol.address # Instructions to patch. We return 1 to force successful response validation. patch_instructions = bytes([ 0x66, 0xB8, 0x01, 0, # mov ax, 0x1 0xC3 # ret ]) client_process.write_bytes(verify_func_addr, patch_instructions, len(patch_instructions)) # Validate the written memory read_instructions = client_process.read_bytes(verify_func_addr, len(patch_instructions)) if read_instructions != patch_instructions: log.error('Failed to patch the instruction memory') return # At this point we know that patching was successful self.last_client_pid = client_process.process_id log.info(f'Patching {client.NAME} was successful')
def scan_file_data(file_content, module_filter, only_detect): """ @param file_content: @param module_filter: @param only_detect: @return: """ # todo php deobfuscation preprocessor is_pe = False try: PE(data=file_content) is_pe = True except KeyboardInterrupt: raise except: is_pe = False preprocessor_data = {} for preprocessor in BAMF_Detect.preprocessors.common.Preprocessors.list: data_to_add, file_data = preprocessor.do_processing(file_content) file_content = file_data for key in data_to_add.keys(): preprocessor_data[key] = data_to_add[key] for m in modules.common.Modules.list: if not is_pe and m.get_datatype() == "PE": continue if module_filter is not None and m.get_module_name( ) not in module_filter: continue if m.is_bot(file_content): results = {} if not only_detect: try: results["information"] = m.get_bot_information( file_content) except KeyboardInterrupt: raise except Exception as e: results["information"] = {} results["exception_details"] = {"message": e.message} results["type"] = m.get_bot_name() results["module"] = m.get_module_name() results["description"] = m.get_metadata().description results["preprocessor"] = preprocessor_data postprocessor_data = {} for postprocessor in BAMF_Detect.postprocessors.common.Postprocessors.list: data_to_add, file_data = postprocessor.do_processing( file_content, results) file_content = file_data for key in data_to_add.keys(): postprocessor_data[key] = data_to_add[key] results["postprocessor"] = postprocessor_data return results return None
def get_exports_of_vad(vad): try: pe = PE(data=vad.read()) if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'): return 1 else: return 0 except Exception as e: return 0
def _validate_image(self, efi_path, profile="DEFAULT"): pe = PE(efi_path) target_config = self.config_data[MACHINE_TYPE[ pe.FILE_HEADER.Machine]].get(profile) if target_config == {}: # The target_config is present, but empty, therefore, override to default profile = "DEFAULT" return self.test_manager.run_tests(pe, profile)
def configExtract(rawData): pe = PE(data=rawData) try: rt_string_idx = [ entry.id for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries ].index(RESOURCE_TYPE['RT_RCDATA']) except ValueError, e: return None
def check_type(vad): try: p = PE(data=vad.read()) if p.FILE_HEADER.IMAGE_FILE_DLL: return 2 else: return 1 except Exception as e: return 0
def _add_pe_info(self): parsed_pe = PE(data=self._content) self._add_vs_info(parsed_pe) self._add_file_property('pe', 'imphash', parsed_pe.get_imphash()) self._add_file_property( 'pe', 'compilation', datetime.utcfromtimestamp( parsed_pe.FILE_HEADER.TimeDateStamp).isoformat())
def checkIfUpdateIsNeed(self,currentVersion): self.exepath = os.path.join(self.path, self.conf["process"]["image_name"]) if currentVersion=="" and not self.conf["version"]["use_exe_version"]: self.install=True elif self.conf["version"]["use_exe_version"] and not os.path.exists(self.exepath): self.install=True else: self.install=False #self.install=currentVersion=="" and not self.conf["version"]["use_exe_version"] and not os.path.exists(self.exepath) if self.simple: self.getDlUrl() self.version = self.api.getVersion(self.conf["version"]["regex"],self.conf["version"]["from_page"],self.conf["version"]["index"]) elif self.conf["basic"]["api_type"]=="sourceforge": self.getDlUrl() self.version = self.api.getVersion() else: self.version = self.api.getVersion(self.conf["build"]["no_pull"]) self.conf.var_replace("%VER",self.version) if self.install: return True elif self.conf["version"]["use_exe_version"]: version = re.sub('[^0-9\.\-]', '', self.version) version = version.replace(r"-", r".") version = version.split(r".") self.versiontuple = [] for num in version: try: self.versiontuple.append(int(num)) except ValueError: self.versiontuple.append(0) pe = PE(self.exepath) if not 'VS_FIXEDFILEINFO' in pe.__dict__: #raise NameError("ERROR: Oops, %s has no version info. Can't continue."%self.exepath) self.addversioninfo = True pe.close() return True if not pe.VS_FIXEDFILEINFO: #raise NameError("ERROR: VS_FIXEDFILEINFO field not set for %s. Can't continue."%self.exepath) pe.close() return True verinfo = pe.VS_FIXEDFILEINFO[0] filever = (verinfo.FileVersionMS >> 16, verinfo.FileVersionMS & 0xFFFF, verinfo.FileVersionLS >> 16, verinfo.FileVersionLS & 0xFFFF) prodver = (verinfo.ProductVersionMS >> 16, verinfo.ProductVersionMS & 0xFFFF, verinfo.ProductVersionLS >> 16, verinfo.ProductVersionLS & 0xFFFF) pe.close() return not (self.version_compare(self.versiontuple,filever) or self.version_compare(self.versiontuple,prodver)) elif self.conf["version"]["use_cmd_version"]: try: pass except IndexError: pass else: return not self.version == currentVersion
def get_imports_of_vad(data): try: pe = PE(data=data) if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'): res = 1 else: res = 0 return res except Exception as e: return 0
def unpack(self, data): cursor = 0 mv = memoryview(data) while True: offset = data.find(B'MZ', cursor) if offset < cursor: break cursor = offset + 2 ntoffset = mv[offset + 0x3C:offset + 0x3E] if len(ntoffset) < 2: return ntoffset, = unpack('H', ntoffset) if mv[offset + ntoffset:offset + ntoffset + 2] != B'PE': self.log_debug( F'invalid NT header signature for candidate at 0x{offset:08X}' ) continue try: pe = PE(data=data[offset:], fast_load=True) except PEFormatError as err: self.log_debug( F'parsing of PE header at 0x{offset:08X} failed:', err) continue pesize = get_pe_size(pe, memdump=self.args.memdump) pedata = mv[offset:offset + pesize] info = {} if self.args.fileinfo: try: info = pemeta().parse_version(pe) or {} except Exception as error: self.log_warn( F'Unable to obtain file information: {error!s}') try: path = info['OriginalFilename'] except KeyError: extension = 'exe' if pe.is_exe() else 'dll' if pe.is_dll( ) else 'sys' path = F'carve-0x{offset:08X}.{extension}' if offset > 0 or self.args.keep_root: yield UnpackResult(path, pedata, offset=offset) self.log_info( F'extracted PE file of size 0x{pesize:08X} from 0x{offset:08X}' ) else: self.log_info( F'ignored root file of size 0x{pesize:08X} from 0x{offset:08X}' ) continue if not offset or self.args.recursive: cursor += pe.OPTIONAL_HEADER.SizeOfHeaders else: cursor += pesize
def get_pe_debug_data(filename): pe = PE(filename, fast_load = True) # we prefer CodeView data to misc type = u'IMAGE_DEBUG_TYPE_CODEVIEW' dbgdata = get_debug_data(pe, DEBUG_TYPE[type]) if dbgdata is None: type = u'IMAGE_DEBUG_TYPE_MISC' dbgdata = get_debug_data(pe, DEBUG_TYPE[type]) if dbgdata is None: type = None return dbgdata, type
def get_external_codeview(filename): pe = PE(filename, fast_load=True) dbgdata = get_debug_data(pe, DEBUG_TYPE[u'IMAGE_DEBUG_TYPE_CODEVIEW']) if dbgdata[:4] == u'RSDS': (guid, filename) = get_rsds(dbgdata) elif dbgdata[:4] == u'NB10': (guid, filename) = get_nb10(dbgdata) else: raise TypeError(u'Invalid CodeView signature: [%s]' % dbgdata[:4]) guid = guid.upper() return guid, filename
def map_and_load(self, path, execute_now=False): ql = self.ql pe = PE(path, fast_load=True) # Make sure no module will occupy the NULL page if self.next_image_base > pe.OPTIONAL_HEADER.ImageBase: IMAGE_BASE = self.next_image_base pe.relocate_image(IMAGE_BASE) else: IMAGE_BASE = pe.OPTIONAL_HEADER.ImageBase IMAGE_SIZE = ql.mem.align(pe.OPTIONAL_HEADER.SizeOfImage, 0x1000) while IMAGE_BASE + IMAGE_SIZE < self.heap_base_address: if not ql.mem.is_mapped(IMAGE_BASE, 1): self.next_image_base = IMAGE_BASE + 0x10000 ql.mem.map(IMAGE_BASE, IMAGE_SIZE) pe.parse_data_directories() data = bytearray(pe.get_memory_mapped_image()) ql.mem.write(IMAGE_BASE, bytes(data)) logging.info("[+] Loading %s to 0x%x" % (path, IMAGE_BASE)) entry_point = IMAGE_BASE + pe.OPTIONAL_HEADER.AddressOfEntryPoint if self.entry_point == 0: # Setting entry point to the first loaded module entry point, so the debugger can break. self.entry_point = entry_point logging.info("[+] PE entry point at 0x%x" % entry_point) self.install_loaded_image_protocol(IMAGE_BASE, IMAGE_SIZE) self.images.append( self.coverage_image( IMAGE_BASE, IMAGE_BASE + pe.NT_HEADERS.OPTIONAL_HEADER.SizeOfImage, path)) if execute_now: logging.info( f'[+] Running from 0x{entry_point:x} of {path}') assembler = self.ql.create_assembler() code = f""" mov rcx, {IMAGE_BASE} mov rdx, {self.gST} mov rax, {entry_point} call rax """ runcode, _ = assembler.asm(code) ptr = ql.os.heap.alloc(len(runcode)) ql.mem.write(ptr, bytes(runcode)) ql.os.exec_arbitrary(ptr, ptr + len(runcode)) else: self.modules.append((path, IMAGE_BASE, entry_point, pe)) return True else: IMAGE_BASE += 0x10000 pe.relocate_image(IMAGE_BASE) return False
def parse_pe_fetch_pdb(symbol_server, file_path): ''' Attempt to fetch a symbol that relates to a PE file. The file must have a valid IMAGE_DEBUG_DIRECTORY and as well as a IMAGE_DEBUG_TYPE_CODEVIEW directroy entry. ''' try: guid = None pdb_filename = None pe = PE(file_path, fast_load=True) pe.parse_data_directories(directories=[DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_DEBUG']]) code_view_entry = None for debug_entry in pe.DIRECTORY_ENTRY_DEBUG: if DEBUG_TYPE[debug_entry.struct.Type] == "IMAGE_DEBUG_TYPE_CODEVIEW": code_view_entry = debug_entry break if code_view_entry == None: logger.warn("%s doesn't have symbol information", basename(file_path)) return None, None symbol_type_offset = code_view_entry.struct.PointerToRawData symbol_type_size = code_view_entry.struct.SizeOfData symbol_type_data = pe.__data__[symbol_type_offset:symbol_type_offset+symbol_type_size] if symbol_type_data[:4] == "RSDS": rsds = CV_RSDS_HEADER.parse(symbol_type_data) guid = "%08x%04x%04x%s%x" % (rsds.GUID.Data1, rsds.GUID.Data2, rsds.GUID.Data3, rsds.GUID.Data4.encode('hex'), rsds.Age) pdb_filename = ntbasename(rsds.Filename) elif symbol_type_data[:4] == "NB10": nb10 = CV_NB10_HEADER.parse(symbol_type_data) guid = "%x%x" % (nb10.Timestamp, nb10.Age) pdb_filename = ntbasename(nb10.Filename) else: logger.error("%s unsupported symbol type", symbol_type_data[:4]) return None, None assert guid assert pdb_filename symbol = __fetch__(symbol_server, guid, file_path, pdb_filename) if symbol[:4] == 'MSCF': # TODO, unpack cabinet else: logger.error("Excpected symbol server to return a cabinet file") return None, None return symbol, basename(pdb_filename) except Exception: logger.error(format_exc()) return None, None
def get_bot_information(self, file_data): results = {} encrypted_section = file_data.rfind("\x44\x6d\x47\x00") if encrypted_section == -1: pe = PE(data=file_data) for x in xrange(len(pe.sections)): for s in data_strings(pe.get_data( pe.sections[x].VirtualAddress), 8, charset=ascii_uppercase + ascii_lowercase + digits + punctuation): if s.startswith("http://") and s != "http://": if "c2s" not in results: results["c2s"] = [] results["c2s"].append({"c2_uri": s}) else: encrypted_section += 4 encryption_key = None pe = PE(data=file_data) for s in data_strings(pe.get_data(pe.sections[3].VirtualAddress), 7): # the last string encryption_key = s if encryption_key is not None: rc4 = RC4(encryption_key) decrypted = "".join([ chr(rc4.next() ^ ord(c)) for c in file_data[encrypted_section:] ]) for s in data_strings(decrypted, 8, charset=ascii_uppercase + ascii_lowercase + digits + punctuation): if s.startswith("http://") and s != "http://": if "c2s" not in results: results["c2s"] = [] results["c2s"].append({"c2_uri": s}) return results