Esempio n. 1
0
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)
Esempio n. 2
0
 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"])
Esempio n. 3
0
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
Esempio n. 4
0
    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
Esempio n. 5
0
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))
Esempio n. 6
0
 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()
Esempio n. 7
0
 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)
Esempio n. 8
0
    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
Esempio n. 9
0
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
Esempio n. 10
0
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)
Esempio n. 11
0
    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
Esempio n. 12
0
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}
Esempio n. 13
0
 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)
Esempio n. 14
0
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='')
Esempio n. 16
0
	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')
Esempio n. 17
0
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
Esempio n. 18
0
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
Esempio n. 19
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)
Esempio n. 20
0
    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
Esempio n. 21
0
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
Esempio n. 22
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())
Esempio n. 23
0
    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
Esempio n. 24
0
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
Esempio n. 25
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
Esempio n. 26
0
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
Esempio n. 27
0
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
Esempio n. 28
0
    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
Esempio n. 29
0
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
Esempio n. 30
0
    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