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
Example #2
0
    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
Example #3
0
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
Example #4
0
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
Example #5
0
    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
Example #6
0
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)
Example #7
0
    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
Example #8
0
    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
Example #9
0
    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
Example #10
0
    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.')
Example #12
0
    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