def analyze_file(self, path): # Run the analyze functions self.encrypted = {'encrypted': is_encrypted(path)} if is_encrypted(path): import io, hashlib with io.open(path, 'rb') as fh: buf = fh.read() md5 = hashlib.md5() md5.update(buf) sha1 = hashlib.sha1() sha1.update(buf) sha256 = hashlib.sha256() sha256.update(buf) self.encrypted = { 'encrypted': is_encrypted(path), 'sha256': sha256.hexdigest(), 'sha1': sha1.hexdigest(), 'md5': md5.hexdigest() } self.analyze_vba(path) self.analyze_dde(path) return self.results
def analyze_file(self, path): # Run the analyze functions self.encrypted = {"encrypted": is_encrypted(path)} if is_encrypted(path): import io, hashlib with io.open(path, "rb") as fh: buf = fh.read() md5 = hashlib.md5() md5.update(buf) sha1 = hashlib.sha1() sha1.update(buf) sha256 = hashlib.sha256() sha256.update(buf) self.encrypted = { "encrypted": is_encrypted(path), "sha256": sha256.hexdigest(), "sha1": sha1.hexdigest(), "md5": md5.hexdigest(), } self.analyze_vba(path) self.analyze_dde(path) return self.results, None
def process_maybe_encrypted(filepath, passwords=None, crypto_nesting=0, **kwargs): """ Process a file that might be encrypted. Calls :py:func:`process_file` and if that fails tries to decrypt and process the result. Based on recommendation in module doc string of :py:mod:`oletools.crypto`. :param str filepath: path to file on disc. :param passwords: list of passwords (str) to try for decryption or None :param int crypto_nesting: How many decryption layers were already used to get the given file. :param kwargs: same as :py:func:`process_file` :returns: same as :py:func:`process_file` """ # TODO: here filepath may also be a file in memory, it's not necessarily on disk result = u'' try: result = process_file(filepath, **kwargs) if not crypto.is_encrypted(filepath): return result except Exception: logger.debug('Ignoring exception:', exc_info=True) if not crypto.is_encrypted(filepath): raise # we reach this point only if file is encrypted # check if this is an encrypted file in an encrypted file in an ... if crypto_nesting >= crypto.MAX_NESTING_DEPTH: raise crypto.MaxCryptoNestingReached(crypto_nesting, filepath) decrypted_file = None if passwords is None: passwords = crypto.DEFAULT_PASSWORDS else: passwords = list(passwords) + crypto.DEFAULT_PASSWORDS try: logger.debug('Trying to decrypt file') decrypted_file = crypto.decrypt(filepath, passwords) if not decrypted_file: logger.error( 'Decrypt failed, run with debug output to get details') raise crypto.WrongEncryptionPassword(filepath) logger.info('Analyze decrypted file') result = process_maybe_encrypted(decrypted_file, passwords, crypto_nesting + 1, **kwargs) finally: # clean up try: # (maybe file was not yet created) os.unlink(decrypted_file) except Exception: logger.debug('Ignoring exception closing decrypted file:', exc_info=True) return result
def process_maybe_encrypted(filepath, passwords=None, crypto_nesting=0, **kwargs): """ Process a file that might be encrypted. Calls :py:func:`process_file` and if that fails tries to decrypt and process the result. Based on recommendation in module doc string of :py:mod:`oletools.crypto`. :param str filepath: path to file on disc. :param passwords: list of passwords (str) to try for decryption or None :param int crypto_nesting: How many decryption layers were already used to get the given file. :param kwargs: same as :py:func:`process_file` :returns: same as :py:func:`process_file` """ result = u'' try: result = process_file(filepath, **kwargs) if not crypto.is_encrypted(filepath): return result except Exception: if not crypto.is_encrypted(filepath): raise # we reach this point only if file is encrypted # check if this is an encrypted file in an encrypted file in an ... if crypto_nesting >= crypto.MAX_NESTING_DEPTH: raise crypto.MaxCryptoNestingReached(crypto_nesting, filepath) decrypted_file = None if passwords is None: passwords = [ crypto.WRITE_PROTECT_ENCRYPTION_PASSWORD, ] else: passwords = list(passwords) + \ [crypto.WRITE_PROTECT_ENCRYPTION_PASSWORD, ] try: logger.debug('Trying to decrypt file') decrypted_file = crypto.decrypt(filepath, passwords) logger.info('Analyze decrypted file') result = process_maybe_encrypted(decrypted_file, passwords, crypto_nesting + 1, **kwargs) finally: # clean up try: # (maybe file was not yet created) os.unlink(decrypted_file) except Exception: pass return result
def check_encrypted(self): """ Check whether this file is encrypted. :returns: :py:class:`Indicator` for encryption or None if file was not opened """ # we keep the pointer to the indicator, can be modified by other checks: encrypted = Indicator('encrypted', False, name='Encrypted', risk=RISK.NONE, description='The file is not encrypted', hide_if_false=False) self.indicators.append(encrypted) # Only OLE files can be encrypted (OpenXML files are encrypted in an OLE container): if not self.ole: return None try: if crypto.is_encrypted(self.ole): encrypted.value = True encrypted.risk = RISK.LOW encrypted.description = 'The file is encrypted. It may be decrypted with msoffcrypto-tool' except Exception as exception: # msoffcrypto-tool can trigger exceptions, such as "Unknown file format" for Excel 5.0/95 encrypted.value = 'Error' encrypted.risk = RISK.ERROR encrypted.description = 'msoffcrypto-tool raised an error when checking if the file is encrypted: {}'.format( exception) return encrypted
def BasicInfoGa(targetFile): # Check for ole structures if isOleFile(targetFile) == True: print(f"{infoS} Ole File: {green}True{white}") else: print(f"{infoS} Ole File: {red}False{white}") # Check for encryption if is_encrypted(targetFile) == True: print(f"{infoS} Encrypted: {green}True{white}") else: print(f"{infoS} Encrypted: {red}False{white}") # VBA_MACRO scanner vbascan = OleID(targetFile) vbascan.check() # Sanitizing the array vba_params = [] for vb in vbascan.indicators: vba_params.append(vb.id) if "vba_macros" in vba_params: for vb in vbascan.indicators: if vb.id == "vba_macros": if vb.value == True: print(f"{infoS} VBA Macros: {green}Found{white}") MacroHunter(targetFile) else: print(f"{infoS} VBA Macros: {red}Not Found{white}") else: MacroHunter(targetFile)
def check_file(self, **kwargs): """Oletools accepts MS office documents.""" try: if kwargs.get("filetype") in [ "DOC", "DOCM", "DOCX", "XLS", "XLSM", "XLSX", "PPT", "PPTM", "PPTX", ] or (kwargs.get("mimetype").startswith( "application/vnd.openxmlformats-officedocument") or kwargs.get("mimetype").startswith("application/encrypted") or kwargs.get("mimetype").startswith("application/vnd.ms-") or kwargs.get("mimetype").startswith("application/msword") or kwargs.get("mimetype").startswith( "Composite Document File V2 Document")): if kwargs.get("mimetype").startswith( "application/encrypted") and not is_encrypted( kwargs.get("file")): return False return True except KeyError: return False return False
def check_encrypted(self): """ Check whether this file is encrypted. Might call check_properties. :returns: :py:class:`Indicator` for encryption or None if file was not opened """ # we keep the pointer to the indicator, can be modified by other checks: encrypted = Indicator('encrypted', False, name='Encrypted') self.indicators.append(encrypted) if not self.ole: return None encrypted.value = crypto.is_encrypted(self.ole) return encrypted
def check_encrypted(self): """ Check whether this file is encrypted. Might call check_properties. :returns: :py:class:`Indicator` for encryption or None if file was not opened """ # we keep the pointer to the indicator, can be modified by other checks: encrypted = Indicator('encrypted', False, name='Encrypted') self.indicators.append(encrypted) if not self.ole: return None encrypted.value = crypto.is_encrypted(self.ole) return encrypted
def check_file(self, **kwargs): """Oletools accepts MS office documents.""" try: if kwargs.get('filetype') in [ 'DOC', 'DOCM', 'DOCX', 'XLS', 'XLSM', 'XLSX', 'PPT', 'PPTM', 'PPTX' ] or (kwargs.get('mimetype').startswith( "application/vnd.openxmlformats-officedocument") or kwargs.get('mimetype').startswith("application/encrypted") or kwargs.get('mimetype').startswith("application/vnd.ms-")): if kwargs.get('mimetype').startswith( "application/encrypted") and not is_encrypted( kwargs.get('file')): return False return True except KeyError: return False return False
def analyze_vba(self, path): """Analyze a given sample for malicious vba.""" try: if is_encrypted(path): path = decrypt(path) vba_parser = VBA_Parser_CLI(path, relaxed=True) vbaparser_result = vba_parser.process_file_json( show_decoded_strings=True, display_code=True, hide_attributes=False, vba_code_only=False, show_deobfuscated_code=True, deobfuscate=True) self.add_result_subsection('Olevba', vbaparser_result) except TypeError: self.add_result_subsection( 'Oletools VBA Analysis failed', 'Analysis failed due to an filetype error.' 'The file does not seem to be a valid MS-Office ' 'file.')
def check_encrypted(self): """ Check whether this file is encrypted. :returns: :py:class:`Indicator` for encryption or None if file was not opened """ # we keep the pointer to the indicator, can be modified by other checks: encrypted = Indicator('encrypted', False, name='Encrypted', risk=RISK.NONE, description='The file is not encrypted', hide_if_false=False) self.indicators.append(encrypted) if not self.ole: return None if crypto.is_encrypted(self.ole): encrypted.value = True encrypted.risk = RISK.LOW encrypted.description = 'The file is encrypted. It may be decrypted with msoffcrypto-tool' return encrypted