Skip to content

Issues with _NT_TIB object in Volshell #1819

@the-rectifier

Description

@the-rectifier

While working at #1816, I encountered an issue in Volshell when parsing the _NT_TIB structures. I don't know if this is for this specific object combination, but as @eve-mem mentioned, this deserves its own issue.

Currently, if we dereference and cast _KTHREAD.Teb into _NT_TIB (first entry of _TEB is _NT_TIB), it results in a malformed object:

(layer_name_Process4988) >>> dt(nt_tib)
symbol_table_name1!_NT_TIB (56 bytes) @ 0x82bf405000:
   0x0 :   ExceptionList            *symbol_table_name1!_EXCEPTION_REGISTRATION_RECORD     N/A
   0x8 :   StackBase                *symbol_table_name1!void                               N/A
  0x10 :   StackLimit               *symbol_table_name1!void                               N/A
  0x18 :   SubSystemTib             *symbol_table_name1!void                               N/A
  0x20 :   FiberData                *symbol_table_name1!void                               N/A
  0x20 :   Version                  symbol_table_name1!unsigned long                       N/A
  0x28 :   ArbitraryUserPointer     *symbol_table_name1!void                               N/A
  0x30 :   Self                     *symbol_table_name1!_NT_TIB                            N/A
(layer_name_Process4988) >>>

To reproduce, try the following script (change the pid argument accordingly):

kernel = self.context.modules[self.config["kernel"]]
kernel_layer = self.context.layers[kernel.layer_name]
proc = gp(pid=4988)

proc_layer_name = proc.add_process_layer()
proc_layer = self.context.layers[proc_layer_name]

cl(proc_layer_name)

thread_list = list(
    proc.ThreadListHead.to_list(
        f"{kernel.symbol_table_name}!_ETHREAD", "ThreadListEntry"
    )
)

active_thread_list = [t for t in thread_list if t.ExitTime.QuadPart < 0]
main_thread = active_thread_list[0]
nt_tib = main_thread.Tcb.Teb.dereference().cast(f'{kernel.symbol_table_name}!_NT_TIB')

assert(main_thread.Tcb.Teb == nt_tib.vol.offset)

# this works
# StackBase is @ NtTib + 8
layer_read = proc_layer.read(nt_tib.vol.offset + 8, 8)
print(layer_read.hex())

# this fails
nt_tib.StackBase

As you will see, accessing the attribute .StackBase will cause a PagedInvalidAddressException while directly reading from the layer will be fine.

Full run:

Volshell (Volatility 3 Framework) 2.26.2
Readline imported successfully  PDB scanning finished
Running code from file:///home/canopus/dev/diss/volatility3/inter.py

000032bf82000000
Traceback (most recent call last):
  File "<input>", line 28, in <module>
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/objects/__init__.py", line 985, in __getattr__
    member = template(context=self._context, object_info=object_info)
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/objects/templates.py", line 96, in __call__
    return self.vol.object_class(
           ~~~~~~~~~~~~~~~~~~~~~^
        context=context, object_info=object_info, **arguments
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/objects/__init__.py", line 168, in __new__
    value = cls._unmarshall(context, data_format, object_info)
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/objects/__init__.py", line 407, in _unmarshall
    cls._get_raw_value(
    ~~~~~~~~~~~~~~~~~~^
        context, data_format, object_info.layer_name, object_info.offset
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/objects/__init__.py", line 425, in _get_raw_value
    data = context.layers.read(layer_name, offset, length)
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/interfaces/layers.py", line 635, in read
    return self[layer].read(offset, length, pad)
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/layers/linear.py", line 45, in read
    for offset, _, mapped_offset, mapped_length, layer in self.mapping(
                                                          ~~~~~~~~~~~~^
        offset, length, ignore_errors=pad
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ):
    ^
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/layers/intel.py", line 307, in mapping
    for offset, size, mapped_offset, mapped_size, map_layer in self._mapping(
                                                               ~~~~~~~~~~~~~^
        offset, length, ignore_errors
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ):
    ^
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/layers/intel.py", line 363, in _mapping
    chunk_offset, page_size, layer_name = self._translate(offset)
                                          ~~~~~~~~~~~~~~~^^^^^^^^
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/layers/intel.py", line 515, in _translate
    return self._translate_swap(self, offset, self._bits_per_register // 2)
           ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/layers/intel.py", line 462, in _translate_swap
    return super()._translate(offset)
           ~~~~~~~~~~~~~~~~~~^^^^^^^^
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/layers/intel.py", line 162, in _translate
    entry, position = self._translate_entry(offset & self.page_mask)
                      ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/canopus/dev/diss/volatility3/volatility3/framework/layers/intel.py", line 217, in _translate_entry
    raise exceptions.PagedInvalidAddressException(
    ...<5 lines>...
    )
volatility3.framework.exceptions.PagedInvalidAddressException: Page Fault at entry 0x0 in table page directory pointer

Code complete

Call help() to see available functions

Volshell mode        : Windows
Current Layer        : layer_name
Current Symbol Table : symbol_table_name1
Current Kernel Name  : kernel

(layer_name_Process4988) >>>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions