Windows: Handle missing _MM_SESSION_SPACE

As of Windows 11 24H2, the `_MM_SESSION_SPACE` type no longer appears in
the kernel PDB. Instead, the `_EPROCESS.Session` member refers to a new
type, `_PSP_SESSION_SPACE`, which does not have a type definition.
However, experimentation has shown that this new structure is
functionally identical to the old structure - the `ProcessList`
and `SessionId` members still appear to be at their old offsets.
In order to account for this when analyzing these newer Windows
versions, this catches the `SymbolError` and instantiates an `unsigned
long` at the offset (8) where the `SessionId` member would normally be
defined within an `_MM_SESSION_SPACE` structure.
This commit is contained in:
David McDonald
2024-12-12 23:24:40 -06:00
parent b6717d80d9
commit 04517ca797
2 changed files with 51 additions and 18 deletions
@@ -165,13 +165,33 @@ class Modules(interfaces.plugins.PluginInterface):
# create the session space object in the process' own layer.
# not all processes have a valid session pointer.
session_space = context.object(
symbol_table + constants.BANG + "_MM_SESSION_SPACE",
layer_name=layer_name,
offset=proc.Session,
)
try:
session_space = context.object(
symbol_table + constants.BANG + "_MM_SESSION_SPACE",
layer_name=layer_name,
offset=proc.Session,
)
session_id = session_space.SessionId
if session_space.SessionId in seen_ids:
except exceptions.SymbolError:
# In Windows 11 24H2, the _MM_SESSION_SPACE type was
# replaced with _PSP_SESSION_SPACE, and the kernel PDB
# doesn't contain information about its members (otherwise,
# we would just fall back to the new type). However, it
# appears to be, for our purposes, functionally identical
# to the _MM_SESSION_SPACE. Because _MM_SESSION_SPACE
# stores its session ID at offset 8 as an unsigned long, we
# create an unsigned long at that offset and use that
# instead.
session_id = int(
context.object(
layer_name=layer_name,
object_type=symbol_table + constants.BANG + "unsigned long",
offset=proc.Session + 8,
)
)
if session_id in seen_ids:
continue
except exceptions.InvalidAddressException:
@@ -184,7 +204,7 @@ class Modules(interfaces.plugins.PluginInterface):
continue
# save the layer if we haven't seen the session yet
seen_ids.append(session_space.SessionId)
seen_ids.append(session_id)
yield proc_layer_name
@classmethod
@@ -813,23 +813,36 @@ class EPROCESS(generic.GenericIntelProcess, pool.ExecutiveObject):
offset=kvo,
native_layer_name=self.vol.native_layer_name,
)
session = ntkrnlmp.object(
object_type="_MM_SESSION_SPACE", offset=self.Session, absolute=True
)
if session.has_member("SessionId"):
return session.SessionId
try:
session = ntkrnlmp.object(
object_type="_MM_SESSION_SPACE",
offset=self.Session,
absolute=True,
)
if session.has_member("SessionId"):
return session.SessionId
except exceptions.SymbolError:
# In Windows 11 24H2, the _MM_SESSION_SPACE type was
# replaced with _PSP_SESSION_SPACE, and the kernel PDB
# doesn't contain information about its members (otherwise,
# we would just fall back to the new type). However, it
# appears to be, for our purposes, functionally identical
# to the _MM_SESSION_SPACE. Because _MM_SESSION_SPACE
# stores its session ID at offset 8 as an unsigned long, we
# create an unsigned long at that offset and use that
# instead.
session_id = ntkrnlmp.object(
object_type="unsigned long",
offset=self.Session + 8,
absolute=True,
)
return int(session_id)
except exceptions.InvalidAddressException:
vollog.log(
constants.LOGLEVEL_VVV,
f"Cannot access _EPROCESS.Session.SessionId at {self.vol.offset:#x}",
)
except exceptions.SymbolError:
vollog.log(
constants.LOGLEVEL_VVV,
"Could not lookup _MM_SESSION_SPACE in symbol table",
)
return renderers.UnreadableValue()