Commit e2684a6251ddd450d6cf9085579ede963456a85c

Authored by Christian Herdtweck
1 parent ddeeb743

tests: Create test for new excel encrypted files

Showing 1 changed file with 81 additions and 0 deletions
tests/olevba/test_crypto.py 0 → 100644
  1 +"""Check decryption of files from olevba works."""
  2 +
  3 +import sys
  4 +import unittest
  5 +import os
  6 +from os.path import join as pjoin
  7 +from subprocess import check_output, CalledProcessError
  8 +import json
  9 +from collections import OrderedDict
  10 +
  11 +from tests.test_utils import DATA_BASE_DIR, SOURCE_BASE_DIR
  12 +
  13 +from oletools import crypto
  14 +
  15 +
  16 +@unittest.skipIf(not crypto.check_msoffcrypto(),
  17 + 'Module msoffcrypto not installed for python{}.{}'
  18 + .format(sys.version_info.major, sys.version_info.minor))
  19 +class OlevbaCryptoWriteProtectTest(unittest.TestCase):
  20 + """
  21 + Test documents that are 'write-protected' through encryption.
  22 +
  23 + Excel has a way to 'write-protect' documents by encrypting them with a
  24 + hard-coded standard password. When looking at the file-structure you see
  25 + an OLE-file with streams `EncryptedPackage`, `StrongEncryptionSpace`, and
  26 + `EncryptionInfo`. Contained in the first is the actual file. When opening
  27 + such a file in excel, it is decrypted without the user noticing.
  28 +
  29 + Olevba should detect such encryption, try to decrypt with the standard
  30 + password and look for VBA code in the decrypted file.
  31 +
  32 + All these tests are skipped if the module `msoffcrypto-tools` is not
  33 + installed.
  34 + """
  35 + def test_autostart(self):
  36 + """Check that autostart macro is found in xls[mb] sample file."""
  37 + # create a PYTHONPATH environment var to prefer our olevba
  38 + env = os.environ
  39 + try:
  40 + env['PYTHONPATH'] = SOURCE_BASE_DIR + os.pathsep + \
  41 + os.environ['PYTHONPATH']
  42 + except KeyError:
  43 + env['PYTHONPATH'] = SOURCE_BASE_DIR
  44 +
  45 + for suffix in 'xlsm', 'xlsb':
  46 + example_file = pjoin(
  47 + DATA_BASE_DIR, 'encrypted',
  48 + 'autostart-encrypt-standardpassword.' + suffix)
  49 + try:
  50 + output = check_output([sys.executable, '-m', 'olevba', '-j',
  51 + example_file],
  52 + universal_newlines=True, env=env)
  53 + except CalledProcessError as err:
  54 + print(err.output)
  55 + raise
  56 + data = json.loads(output, object_pairs_hook=OrderedDict)
  57 + # debug: json.dump(data, sys.stdout, indent=4)
  58 + self.assertEqual(len(data), 4)
  59 + self.assertIn('script_name', data[0])
  60 + self.assertIn('version', data[0])
  61 + self.assertEqual(data[0]['type'], 'MetaInformation')
  62 + self.assertIn('return_code', data[-1])
  63 + self.assertEqual(data[-1]['type'], 'MetaInformation')
  64 + self.assertEqual(data[1]['container'], None)
  65 + self.assertEqual(data[1]['file'], example_file)
  66 + self.assertEqual(data[1]['analysis'], None)
  67 + self.assertEqual(data[1]['macros'], [])
  68 + self.assertEqual(data[1]['type'], 'OLE')
  69 + self.assertEqual(data[2]['container'], example_file)
  70 + self.assertNotEqual(data[2]['file'], example_file)
  71 + self.assertEqual(data[2]['type'], "OpenXML")
  72 + analysis = data[2]['analysis']
  73 + self.assertEqual(analysis[0]['type'], 'AutoExec')
  74 + self.assertEqual(analysis[0]['keyword'], 'Auto_Open')
  75 + macros = data[2]['macros']
  76 + self.assertEqual(macros[0]['vba_filename'], 'Modul1.bas')
  77 + self.assertIn('Sub Auto_Open()', macros[0]['code'])
  78 +
  79 +
  80 +if __name__ == '__main__':
  81 + unittest.main()
... ...