Improve object manager doc + add samples

This commit is contained in:
hakril
2018-07-13 14:24:55 +02:00
parent eb3b13016f
commit c19241098a
7 changed files with 224 additions and 13 deletions
+10 -2
View File
@@ -6,7 +6,15 @@ Object Manager -- Kernel objects
The :class:`ObjectManager` instance is accessible via :py:attr:`windows.system.object_manager
<windows.winobject.system.System.object_manager>`
TODO: doc + sample
.. note::
See sample at :ref:`sample_object_manager`
.. warning::
This API have not been tested on real case yet and may be subject to changes.
ObjectManager
"""""""""""""
@@ -24,4 +32,4 @@ KernelObject
.. autoclass:: KernelObject
:members:
:undoc-members:
:special-members: __getitem__
:special-members: __getitem__, __iter__
@@ -0,0 +1,23 @@
(cmd) python object_manager\findobj.py
Looking for object name containing <ls>
* <KernelObject "\KnownDlls32" (type="Directory")>
* <KernelObject "\Win32kCrossSessionGlobals" (type="Section")>
* <KernelObject "\KnownDlls" (type="Directory")>
<\DriverStores\SYSTEM> -> STATUS_ACCESS_DENIED
* <KernelObject "\Device\MailslotRedirector" (type="SymbolicLink")> -> <\Device\Mup\;MailslotRedirector>
* <KernelObject "\Device\Mailslot" (type="Device")>
<\Device\00000020> -> STATUS_ACCESS_DENIED
<\Device\00000020> -> STATUS_ACCESS_DENIED
<\Device\00000020> -> STATUS_ACCESS_DENIED
<\Device\00000020> -> STATUS_ACCESS_DENIED
<\Device\00000020> -> STATUS_ACCESS_DENIED
<\KernelObjects\PrefetchTracesReady> -> STATUS_ACCESS_DENIED
<\KnownDlls\powrprof.dll> -> STATUS_ACCESS_DENIED
* <KernelObject "\RPC Control\lsapolicylookup" (type="ALPC Port")>
* <KernelObject "\RPC Control\lsacap" (type="ALPC Port")>
* <KernelObject "\RPC Control\lsasspirpc" (type="ALPC Port")>
<\Windows\SbApiPort> -> STATUS_ACCESS_DENIED
<\Windows\SbApiPort> -> STATUS_ACCESS_DENIED
<\Sessions\BNOLINKS\1> -> STATUS_ACCESS_DENIED
<\Sessions\BNOLINKS\1> -> STATUS_ACCESS_DENIED
<\Sessions\BNOLINKS\1> -> STATUS_ACCESS_DENIED
@@ -0,0 +1,22 @@
(cmd) python object_manager\object_manager.py
Object manager is <windows.winobject.object_manager.ObjectManager object at 0x0370ED10>
Root object is <KernelObject "\" (type="Directory")>
Listing some of root-subobject:
* PendingRenameMutex: <KernelObject "\PendingRenameMutex" (type="Mutant")>
* ObjectTypes: <KernelObject "\ObjectTypes" (type="Directory")>
* storqosfltport: <KernelObject "\storqosfltport" (type="FilterConnectionPort")>
* MicrosoftMalwareProtectionRemoteIoPortWD: <KernelObject "\MicrosoftMalwareProtectionRemoteIoPortWD" (type="FilterConnectionPort")>
Retrieving <\Rpc Control\lsasspirpc>:
Object is: <KernelObject "\Rpc Control\lsasspirpc" (type="ALPC Port")>
* name: <lsasspirpc>
* path: <\Rpc Control>
* fullname: <\Rpc Control\lsasspirpc>
* type: <ALPC Port>
* target: <None>
Looking for a SymbolicLink in <ArcName>
Object is: <KernelObject "\ArcName\multi(0)disk(0)rdisk(0)" (type="SymbolicLink")>
* name: <multi(0)disk(0)rdisk(0)>
* target: <\Device\Harddisk0\Partition0>
+35
View File
@@ -0,0 +1,35 @@
import argparse
import windows
import windows.generated_def as gdef
def obj_with_link(obj):
target = obj.target
if target is None:
return str(obj)
return "{0} -> <{1}>".format(obj, target)
def find_name(root, findname):
TODO = [root]
while TODO:
try:
for name, obj in TODO.pop().items():
if findname in name:
print("* {0}".format(obj_with_link(obj)))
if obj.type == "Directory":
TODO.append(obj)
except gdef.NtStatusException as e:
print("<{0}> -> {1}".format(obj.fullname, e.name))
parser = argparse.ArgumentParser(prog=__file__)
parser.add_argument('name', nargs='?', default="ls", help='The name of the object to find')
res = parser.parse_args()
objmanag = windows.system.object_manager
print("Looking for object name containing <{0}>".format(res.name))
find_name(objmanag.root, res.name)
+44
View File
@@ -0,0 +1,44 @@
import sys
import os.path
sys.path.append(os.path.abspath(__file__ + "\..\.."))
import windows
import windows.generated_def as gdef
object_manager = windows.system.object_manager
print("Object manager is {0}".format(object_manager))
root = object_manager.root
print("Root object is {0}".format(root))
print("")
print("Listing some of root-subobject:")
# Kernel object of type 'Directory' are iterable
for i, (name, obj) in enumerate(root.items()):
print(" * {0}: {1}".format(name, obj))
if i == 3:
break
print("")
print(r"Retrieving <\Rpc Control\lsasspirpc>:")
# You can retrieve this value in one request
x1 = root[r"\Rpc Control\lsasspirpc"]
# Sub-directory also allow __getitem__
x2 = root["Rpc Control"]["lsasspirpc"]
# You can directly request the object manager that will request `root`
x3 = object_manager[r"\Rpc Control\lsasspirpc"]
assert x1.fullname == x2.fullname == x3.fullname
lsasspirpc = x1
print("Object is: {0}".format(lsasspirpc))
print(" * name: <{0}>".format(lsasspirpc.name))
print(" * path: <{0}>".format(lsasspirpc.path))
print(" * fullname: <{0}>".format(lsasspirpc.fullname))
print(" * type: <{0}>".format(lsasspirpc.type))
print(" * target: <{0}>".format(lsasspirpc.target)) # None on non-symlink
print("")
print("Looking for a SymbolicLink in <ArcName>")
slo = [o for o in root["ArcName"].values() if o.type == "SymbolicLink"][0]
print("Object is: {0}".format(slo))
print(" * name: <{0}>".format(slo.name))
print(" * target: <{0}>".format(slo.target))
+22
View File
@@ -0,0 +1,22 @@
import argparse
import windows
import windows.generated_def as gdef
def obj_with_link(obj):
target = obj.target
if target is None:
return str(obj)
return "{0} -> <{1}>".format(obj, target)
def fulllistdir(dir, depth=0):
for name, obj in dir.items():
print("{0} * {1}".format(" " * depth, obj_with_link(obj)))
if obj.type == "Directory":
try:
fulllistdir(obj, depth + 4)
except gdef.NtStatusException as e:
print("{0} * {1}".format(" " * (depth + 4), e))
fulllistdir(windows.system.object_manager.root)
+68 -11
View File
@@ -4,11 +4,11 @@ from collections import namedtuple
import windows
from windows import winproxy
# from windows.generated_def.winstructs import *
import windows.generated_def as gdef
def query_link(linkpath):
"""Resolve the link object with path ``linkpath``"""
obj_attr = gdef.OBJECT_ATTRIBUTES()
obj_attr.Length = ctypes.sizeof(obj_attr)
obj_attr.RootDirectory = 0
@@ -20,11 +20,12 @@ def query_link(linkpath):
x = winproxy.NtOpenSymbolicLinkObject(res, gdef.DIRECTORY_QUERY | gdef.READ_CONTROL , obj_attr)
v = gdef.LSA_UNICODE_STRING.from_string("\x00" * 1000)
s = gdef.ULONG()
winproxy.NtQuerySymbolicLinkObject(res, v, s)
winproxy.NtQuerySymbolicLinkObject(res, v, s) # Handle Buffer-too-small ?
return v.str
class KernelObject(object):
"""Represent an object in the Object Manager namespace"""
def __init__(self, path, name, type):
self.path = path
self.name = name
@@ -35,20 +36,55 @@ class KernelObject(object):
@property
def target(self):
"""Resolve the target of a symbolic link object.
:rtype: :class:`str` or None if object is not a link
"""
try:
return query_link(self.fullname)
except windows.generated_def.ntstatus.NtStatusException as e:
if e.code != gdef.STATUS_OBJECT_TYPE_MISMATCH:
raise
return None
def items(self):
"""Todo: better name ?"""
"""Return the list of tuple (object's name, object) in the current directory object.
:rtype: [(:class:`str`, :class:`KernelObject`)] -- A list of tuple
.. note::
the :class:`KernelObject` must be of type ``Directory`` or
it will raise :class:`~windows.generated_def.ntstatus.NtStatusException` with
code :data:`~windows.generated_def.STATUS_OBJECT_TYPE_MISMATCH`
"""
path = self.fullname
return [(name, KernelObject(path, name, typename)) for name, typename in self._directory_query_generator()]
def keys(self):
"""Return the list of objects' name in the current directory object.
:rtype: [:class:`str`] -- A list of name
.. note::
the :class:`KernelObject` must be of type ``Directory`` or
it will raise :class:`~windows.generated_def.ntstatus.NtStatusException` with
code :data:`~windows.generated_def.STATUS_OBJECT_TYPE_MISMATCH`
"""
return list(self)
def values(self):
"""Return the list of objects in the current directory object.
:rtype: [:class:`KernelObject`] -- A list of object
.. note::
the :class:`KernelObject` must be of type ``Directory`` or
it will raise :class:`~windows.generated_def.ntstatus.NtStatusException` with
code :data:`~windows.generated_def.STATUS_OBJECT_TYPE_MISMATCH`
"""
path = self.fullname
return [KernelObject(path, name, typename) for name, typename in self._directory_query_generator()]
@@ -96,6 +132,16 @@ class KernelObject(object):
yield v.Name.str, v.TypeName.str
def __iter__(self):
"""Iter over the list of name in the Directory object.
:yield: :class:`str` -- The names of objects in the directory.
.. note::
the :class:`KernelObject` must be of type ``Directory`` or
it will raise :class:`~windows.generated_def.ntstatus.NtStatusException` with
code :data:`~windows.generated_def.STATUS_OBJECT_TYPE_MISMATCH`
"""
return (name for name, type in self._directory_query_generator())
def __repr__(self):
@@ -111,20 +157,30 @@ class KernelObject(object):
return KernelObject(self.fullname, name, objtype)
raise KeyError("Could not find WinObject <{0}> under <{1}>".format(name, self.fullname))
def __getitem__(self, value):
print(self, value)
if value.startswith("\\"):
def __getitem__(self, name):
"""Query object ``name`` from the directory, split and subquery on ``\\``::
>>> obj
<KernelObject "\Windows" (type="Directory")>
>>> obj["WindowStations"]["WinSta0"]
<KernelObject "\Windows\WindowStations" (type="Directory")>
>>> obj["WindowStations\\WinSta0"]
<KernelObject "\Windows\WindowStations" (type="Directory")>
:rtype: :class:`KernelObject`
:raise: :class:`KeyError` if ``name`` can not be found.
"""
if name.startswith("\\"):
# Are we the root directory ?
if not self.fullname == "\\" :
raise ValueError("Cannot query an object path begining by '\\' from an object other than '\\'")
elif value == "\\": # Ask for root ? return ourself
elif name == "\\": # Ask for root ? return ourself
return self
else:
value = value[1:]
name = name[1:]
obj = self
print(value.split("\\"))
for part in value.split("\\"):
for part in name.split("\\"):
try:
obj = obj.get(part)
except gdef.NtStatusException as e:
@@ -159,4 +215,5 @@ class ObjectManager(object):
:rtype: :class:`KernelObject`
"""
return self.root[name]
return self.root[name]