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 | 63 | |
| 64 | 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 | 80 | # Helpers |
| ... | ... | @@ -112,6 +124,12 @@ class OleRecordFile(olefile.OleFileIO): |
| 112 | 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 | 133 | @classmethod |
| 116 | 134 | def stream_class_for_name(cls, stream_name): |
| 117 | 135 | """ helper for iter_streams, must be overwritten in subclasses |
| ... | ... | @@ -143,7 +161,8 @@ class OleRecordFile(olefile.OleFileIO): |
| 143 | 161 | stream = clz(self._open(direntry.isectStart, direntry.size), |
| 144 | 162 | direntry.size, |
| 145 | 163 | None if is_orphan else direntry.name, |
| 146 | - direntry.entry_type) | |
| 164 | + direntry.entry_type, | |
| 165 | + self.is_encrypted) | |
| 147 | 166 | yield stream |
| 148 | 167 | stream.close() |
| 149 | 168 | |
| ... | ... | @@ -156,13 +175,14 @@ class OleRecordStream(object): |
| 156 | 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 | 179 | self.stream = stream |
| 161 | 180 | self.size = size |
| 162 | 181 | self.name = name |
| 163 | 182 | if stream_type not in ENTRY_TYPE2STR: |
| 164 | 183 | raise ValueError('Unknown stream type: {0}'.format(stream_type)) |
| 165 | 184 | self.stream_type = stream_type |
| 185 | + self.is_encrypted = is_encrypted | |
| 166 | 186 | |
| 167 | 187 | def read_record_head(self): |
| 168 | 188 | """ read first few bytes of record to determine size and type |
| ... | ... | @@ -191,6 +211,9 @@ class OleRecordStream(object): |
| 191 | 211 | |
| 192 | 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 | 217 | while True: |
| 195 | 218 | # unpacking as in olevba._extract_vba |
| 196 | 219 | pos = self.stream.tell() | ... | ... |