Commit dd498c52938d18bde9d068ec56fbd5a617e30ecf
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() |