Commit dd498c52938d18bde9d068ec56fbd5a617e30ecf

Authored by Christian Herdtweck
1 parent 002fca03

record_base: throw encryption error when iterating encrypted files

Sofar, most tools (like msodde) do not complain if file is encrypted, but
cannot inspect it either. That gives the user a false sense of security
which is dangerous. Raise error to make the situation clear. But only
raise when iterating records (stream names are still reliable and useful.
Showing 1 changed file with 25 additions and 2 deletions
oletools/record_base.py
@@ -63,6 +63,18 @@ import logging @@ -63,6 +63,18 @@ import logging
63 63
64 import olefile 64 import olefile
65 65
  66 +try:
  67 + from oletools.common.errors import FileIsEncryptedError
  68 +except ImportError:
  69 + # little hack to allow absolute imports even if oletools is not installed.
  70 + PARENT_DIR = os.path.normpath(os.path.dirname(os.path.dirname(
  71 + os.path.abspath(__file__))))
  72 + if PARENT_DIR not in sys.path:
  73 + sys.path.insert(0, PARENT_DIR)
  74 + del PARENT_DIR
  75 + from oletools.common.errors import FileIsEncryptedError
  76 +from oletools import oleid
  77 +
66 78
67 ############################################################################### 79 ###############################################################################
68 # Helpers 80 # Helpers
@@ -112,6 +124,12 @@ class OleRecordFile(olefile.OleFileIO): @@ -112,6 +124,12 @@ class OleRecordFile(olefile.OleFileIO):
112 Subclass of OleFileIO! 124 Subclass of OleFileIO!
113 """ 125 """
114 126
  127 + def open(self, filename, *args, **kwargs):
  128 + """Call OleFileIO.open, raise error if is encrypted."""
  129 + #super(OleRecordFile, self).open(filename, *args, **kwargs)
  130 + OleFileIO.open(self, filename, *args, **kwargs)
  131 + self.is_encrypted = oleid.OleID(self).check_encrypted().value
  132 +
115 @classmethod 133 @classmethod
116 def stream_class_for_name(cls, stream_name): 134 def stream_class_for_name(cls, stream_name):
117 """ helper for iter_streams, must be overwritten in subclasses 135 """ helper for iter_streams, must be overwritten in subclasses
@@ -143,7 +161,8 @@ class OleRecordFile(olefile.OleFileIO): @@ -143,7 +161,8 @@ class OleRecordFile(olefile.OleFileIO):
143 stream = clz(self._open(direntry.isectStart, direntry.size), 161 stream = clz(self._open(direntry.isectStart, direntry.size),
144 direntry.size, 162 direntry.size,
145 None if is_orphan else direntry.name, 163 None if is_orphan else direntry.name,
146 - direntry.entry_type) 164 + direntry.entry_type,
  165 + self.is_encrypted)
147 yield stream 166 yield stream
148 stream.close() 167 stream.close()
149 168
@@ -156,13 +175,14 @@ class OleRecordStream(object): @@ -156,13 +175,14 @@ class OleRecordStream(object):
156 abstract base class 175 abstract base class
157 """ 176 """
158 177
159 - def __init__(self, stream, size, name, stream_type): 178 + def __init__(self, stream, size, name, stream_type, is_encrypted=False):
160 self.stream = stream 179 self.stream = stream
161 self.size = size 180 self.size = size
162 self.name = name 181 self.name = name
163 if stream_type not in ENTRY_TYPE2STR: 182 if stream_type not in ENTRY_TYPE2STR:
164 raise ValueError('Unknown stream type: {0}'.format(stream_type)) 183 raise ValueError('Unknown stream type: {0}'.format(stream_type))
165 self.stream_type = stream_type 184 self.stream_type = stream_type
  185 + self.is_encrypted = is_encrypted
166 186
167 def read_record_head(self): 187 def read_record_head(self):
168 """ read first few bytes of record to determine size and type 188 """ read first few bytes of record to determine size and type
@@ -191,6 +211,9 @@ class OleRecordStream(object): @@ -191,6 +211,9 @@ class OleRecordStream(object):
191 211
192 Stream must be positioned at start of records (e.g. start of stream). 212 Stream must be positioned at start of records (e.g. start of stream).
193 """ 213 """
  214 + if self.is_encrypted:
  215 + raise FileIsEncryptedError()
  216 +
194 while True: 217 while True:
195 # unpacking as in olevba._extract_vba 218 # unpacking as in olevba._extract_vba
196 pos = self.stream.tell() 219 pos = self.stream.tell()