diff --git a/windows/winobject/kernobj.py b/windows/winobject/kernobj.py new file mode 100644 index 0000000..5cc135d --- /dev/null +++ b/windows/winobject/kernobj.py @@ -0,0 +1,106 @@ +import os.path +import ctypes +from collections import namedtuple + +import windows +from windows import winproxy +from windows.generated_def.winstructs import * + + +def query_link(linkpath): + utf16_len = len(linkpath) * 2 + obj_attr = OBJECT_ATTRIBUTES() + obj_attr.Length = ctypes.sizeof(obj_attr) + obj_attr.RootDirectory = 0 + obj_attr.ObjectName = pointer(LSA_UNICODE_STRING(utf16_len, utf16_len, linkpath)) + obj_attr.Attributes = OBJ_CASE_INSENSITIVE + obj_attr.SecurityDescriptor = 0 + obj_attr.SecurityQualityOfService = 0 + + res = HANDLE() + x = winproxy.NtOpenSymbolicLinkObject(res, DIRECTORY_QUERY | READ_CONTROL , obj_attr) + v = LSA_UNICODE_STRING(0x1000, 0x1000, ctypes.cast(ctypes.c_buffer(0x1000), ctypes.c_wchar_p)) + s = ULONG() + winproxy.NtQuerySymbolicLinkObject(res, v, s) + return v.Buffer + + +class KernelObject(object): + def __init__(self, path, name, type): + self.path = path + self.name = name + if path and not path.endswith("\\"): + path += "\\" + self.fullname = path + name + self.type = type + + @property + def target(self): + try: + return query_link(self.fullname) + except windows.generated_def.ntstatus.NtStatusException as e: + return None + + @property + def entries(self): + """Todo: better name ?""" + path = self.fullname + utf16_len = len(path) * 2 + obj_attr = OBJECT_ATTRIBUTES() + obj_attr.Length = ctypes.sizeof(obj_attr) + obj_attr.RootDirectory = None + obj_attr.ObjectName = pointer(LSA_UNICODE_STRING(utf16_len, utf16_len, path)) + obj_attr.Attributes = OBJ_CASE_INSENSITIVE + obj_attr.SecurityDescriptor = 0 + obj_attr.SecurityQualityOfService = 0 + + res = HANDLE() + x = winproxy.NtOpenDirectoryObject(res, DIRECTORY_QUERY | READ_CONTROL , obj_attr) + size = 0x1000 + buf = ctypes.c_buffer(size) + rres = ULONG() + ctx = ULONG() + while True: + try: + winproxy.NtQueryDirectoryObject(res, buf, size, False, False, ctx, rres) + break + except windows.generated_def.ntstatus.NtStatusException as e: + if e.code == STATUS_NO_MORE_ENTRIES: + return {} + if e.code == STATUS_MORE_ENTRIES: + size *= 2 + buf = ctypes.c_buffer(size) + continue + raise + + t = OBJECT_DIRECTORY_INFORMATION.from_buffer(buf) + t = POBJECT_DIRECTORY_INFORMATION(t) + res = {} + for v in t: + if v.Name.Buffer is None: + break + x = KernelObject(path, v.Name.Buffer, v.TypeName.Buffer) + res[x.name] = x + return res + + def __repr__(self): + return """<{0} "{1}" (type="{2}")>""".format(type(self).__name__, self.fullname, self.type) + + +root = KernelObject("", "\\", "Directory") + +#def full_explore(start): +# TODO = [start] +# while TODO: +# path = TODO.pop() +# print("Explore <{0}>".format(path)) +# try: +# for obj in path.subobjects.values(): +# print("{0} -> {1}".format(obj.fullname, obj.type)) +# if obj.type == "Directory": +# TODO.append(obj) +# if obj.type == "SymbolicLink": +# print("* Symblink target -> {0}".format(obj.target)) +# except windows.generated_def.ntstatus.NtStatusException as e: +# print(repr(e)) +#full_explore(yolo) \ No newline at end of file