|
3 | 3 | # |
4 | 4 |
|
5 | 5 | import re |
6 | | - |
7 | | -from typing import List, Optional, Union |
| 6 | +import logging |
| 7 | +from typing import Optional, Union |
8 | 8 |
|
9 | 9 | from volatility3.framework import interfaces, objects, constants, exceptions |
10 | 10 |
|
| 11 | +vollog = logging.getLogger(__name__) |
| 12 | + |
11 | 13 |
|
12 | 14 | def rol(value: int, count: int, max_bits: int = 64) -> int: |
13 | 15 | """A rotate-left instruction in Python""" |
@@ -254,51 +256,46 @@ def array_of_pointers( |
254 | 256 |
|
255 | 257 | def dynamically_sized_array_of_pointers( |
256 | 258 | context: interfaces.context.ContextInterface, |
257 | | - layer_name: str, |
258 | | - symbol_table_name: str, |
259 | | - array_offset: int, |
| 259 | + array: interfaces.objects.ObjectInterface, |
| 260 | + iterator_guard_value: int, |
| 261 | + subtype: Union[str, interfaces.objects.Template], |
260 | 262 | stop_value: int = 0, |
261 | | - iterator_guard_value: int = None, |
262 | 263 | stop_on_invalid_pointers: bool = True, |
263 | | -) -> List[interfaces.objects.ObjectInterface]: |
| 264 | +) -> interfaces.objects.ObjectInterface: |
264 | 265 | """Iterates over a dynamically sized array of pointers (e.g. NULL-terminated). |
| 266 | + Array iteration should always be performed with an arbitrary guard value as maximum size, |
| 267 | + to prevent running forever in case something unexpected happens. |
265 | 268 |
|
266 | 269 | Args: |
267 | 270 | context: The context on which to operate. |
268 | | - layer_name: The layer on which the array should be constructed. |
269 | | - symbol_table_name: The symbol table to use to construct object types. |
270 | | - array_offset: The array offset within the layer, from which to start iterating. |
271 | | - stop_value: Stop value used to determine when to terminate iteration once it is encountered. Defaults to 0 (NULL-terminated arrays). |
| 271 | + array: The object to cast to an array. |
272 | 272 | iterator_guard_value: Stop iterating when the iterator index is greater than this value. This is an extra-safety against smearing. |
| 273 | + subtype: The subtype of the array's pointers. |
| 274 | + stop_value: Stop value used to determine when to terminate iteration once it is encountered. Defaults to 0 (NULL-terminated arrays). |
273 | 275 | stop_on_invalid_pointers: Determines whether to stop iterating or not when an invalid pointer is encountered. This can be useful for arrays |
274 | 276 | that are known to have smeared entries before the end. |
275 | 277 |
|
276 | 278 | Returns: |
277 | 279 | An array of pointer objects |
278 | 280 | """ |
279 | | - pointer_type = context.symbol_space.get_type( |
280 | | - symbol_table_name + constants.BANG + "pointer" |
281 | | - ) |
282 | | - entry = context.object( |
283 | | - pointer_type, |
284 | | - layer_name=layer_name, |
285 | | - offset=array_offset, |
286 | | - ) |
287 | | - i = 0 |
288 | | - array = [] |
289 | | - # entry and entry.vol.offset aren't the same thing, as |
290 | | - # - entry is naturally represented by the address that the pointer refers to; |
291 | | - # - entry.vol.offset is the offset at which the pointer lives. |
292 | | - while entry != stop_value: |
293 | | - if (not entry.is_readable() and stop_on_invalid_pointers) or ( |
294 | | - iterator_guard_value is not None and i >= iterator_guard_value |
| 281 | + new_count = 0 |
| 282 | + for entry in array_of_pointers( |
| 283 | + array=array, count=iterator_guard_value, subtype=subtype, context=context |
| 284 | + ): |
| 285 | + # "entry" is naturally represented by the address that the pointer refers to |
| 286 | + if (entry == stop_value) or ( |
| 287 | + not entry.is_readable() and stop_on_invalid_pointers |
295 | 288 | ): |
296 | 289 | break |
297 | | - array.append(entry) |
298 | | - entry = context.object( |
299 | | - pointer_type, |
300 | | - layer_name=layer_name, |
301 | | - offset=entry.vol.offset + pointer_type.size, |
| 290 | + new_count += 1 |
| 291 | + else: |
| 292 | + vollog.log( |
| 293 | + constants.LOGLEVEL_V, |
| 294 | + f"""Iterator guard value {iterator_guard_value} reached while iterating over array at offset {array.vol.offset:#x}.\ |
| 295 | + This means that there is a bug (e.g. smearing) with this array, or that it may contain valid entries past the iterator guard value.""", |
302 | 296 | ) |
303 | | - i += 1 |
304 | | - return array |
| 297 | + |
| 298 | + # Leverage the "Array" object instead of returning a Python list |
| 299 | + return array_of_pointers( |
| 300 | + array=array, count=new_count, subtype=subtype, context=context |
| 301 | + ) |
0 commit comments