diff --git a/TODO b/TODO index e521f30..b05905b 100644 --- a/TODO +++ b/TODO @@ -40,6 +40,8 @@ TODO: - NtQueryVirtualMemory_32_to_64 (stop using hardcoded value for request type: add it to enum) + - Some test/doc on windows.system.handles + CHANGELOG: * re-check every sample diff --git a/windows/winobject/handle.py b/windows/winobject/handle.py index bc5a562..96e0f52 100644 --- a/windows/winobject/handle.py +++ b/windows/winobject/handle.py @@ -4,79 +4,84 @@ import windows from windows import winproxy from windows.generated_def import windef from windows.winobject.process import WinUnicodeString - from windows.generated_def.winstructs import * +class EPUBLIC_OBJECT_TYPE_INFORMATION(ctypes.Structure): + _fields_ = windows.utils.transform_ctypes_fields(PUBLIC_OBJECT_TYPE_INFORMATION, {"TypeName": windows.winobject.process.WinUnicodeString}) -class ProcessHandle(SYSTEM_HANDLE): + +class Handle(SYSTEM_HANDLE): @windows.utils.fixedpropety def process(self): - # Do better (open process / process by handle) + "TODO: something smart ? :D" return [p for p in windows.system.processes if p.pid == self.dwProcessId][0] + @windows.utils.fixedpropety + def name(self): + return self._get_object_name() - def get_object_name(self): - lh = self._get_local_handle() + @windows.utils.fixedpropety + def type(self): + return self._get_object_type() + + def _get_object_name(self): + lh = self.local_handle size_needed = DWORD() yyy = ctypes.c_buffer(0x1000) - #print("Size = {0}".format(ctypes.sizeof(xxx))) size_needed = DWORD() - #try: winproxy.NtQueryObject(lh, ObjectNameInformation, ctypes.byref(yyy), ctypes.sizeof(yyy), ctypes.byref(size_needed)) return WinUnicodeString.from_buffer_copy(yyy[:size_needed.value]).str - def _public_object_information(self): - lh = self._get_local_handle() - - xxx = PUBLIC_OBJECT_TYPE_INFORMATION() - #print("Size = {0}".format(ctypes.sizeof(xxx))) + def _get_object_type(self): + lh = self.local_handle + xxx = EPUBLIC_OBJECT_TYPE_INFORMATION() size_needed = DWORD() try: winproxy.NtQueryObject(lh, ObjectTypeInformation, ctypes.byref(xxx), ctypes.sizeof(xxx), ctypes.byref(size_needed)) except Exception as e: - #print(e) - #print(size_needed) size = size_needed.value buffer = ctypes.c_buffer(size) winproxy.NtQueryObject(lh, ObjectTypeInformation, buffer, size, ctypes.byref(size_needed)) - xxx = PUBLIC_OBJECT_TYPE_INFORMATION.from_buffer_copy(buffer) - return xxx + xxx = EPUBLIC_OBJECT_TYPE_INFORMATION.from_buffer_copy(buffer) + return xxx.TypeName.str - def _get_local_handle(self): + @windows.utils.fixedpropety + def local_handle(self): if self.dwProcessId == windows.current_process.pid: return self.wValue res = HANDLE() - print("Duplicate <{0}> of {1}".format(self.wValue, self.process)) winproxy.DuplicateHandle(self.process.handle, self.wValue, windows.current_process.handle, ctypes.byref(res), dwOptions=DUPLICATE_SAME_ACCESS) return res.value - def _close_local_handle(self, h): + def __repr__(self): + return "<{0} value=<0x{1:x}> in process pid={2}>".format(type(self).__name__, self.wValue, self.dwProcessId) + + def __del__(self): if self.dwProcessId == windows.current_process.pid: return - return winproxy.Closehandle(h) + if hasattr(self, "_local_handle"): + return winproxy.CloseHandle(self._local_handle) - #def __repr__(self): - # return "YOLO" + object.__repr__(self) -def get_handle_list(): - size_needed = ULONG() - size = 0x1000 - buffer = ctypes.c_buffer(size) - try: - winproxy.NtQuerySystemInformation(16, buffer, size, ReturnLength=ctypes.byref(size_needed)) - except WindowsError as e: - pass +def enumerate_handles(): + size_needed = ULONG() + size = 0x1000 + buffer = ctypes.c_buffer(size) - size = size_needed.value + 0x1000 - buffer = ctypes.c_buffer(size) + try: winproxy.NtQuerySystemInformation(16, buffer, size, ReturnLength=ctypes.byref(size_needed)) + except WindowsError as e: + pass - x = SYSTEM_HANDLE_INFORMATION.from_buffer(buffer) + size = size_needed.value + 0x1000 + buffer = ctypes.c_buffer(size) + winproxy.NtQuerySystemInformation(16, buffer, size, ReturnLength=ctypes.byref(size_needed)) + x = SYSTEM_HANDLE_INFORMATION.from_buffer(buffer) + class _GENERATED_SYSTEM_HANDLE_INFORMATION(ctypes.Structure): + _fields_ = [ + ("HandleCount", ULONG), + ("Handles", Handle * x.HandleCount), + ] + return list(_GENERATED_SYSTEM_HANDLE_INFORMATION.from_buffer_copy(buffer[:size_needed.value]).Handles) - class _GENERATED_SYSTEM_HANDLE_INFORMATION(ctypes.Structure): - _fields_ = [ - ("HandleCount", ULONG), - ("Handles", ProcessHandle * x.HandleCount), - ] - return list(_GENERATED_SYSTEM_HANDLE_INFORMATION.from_buffer_copy(buffer[:size_needed.value]).Handles) \ No newline at end of file diff --git a/windows/winobject/system.py b/windows/winobject/system.py index 90e684e..d666d15 100644 --- a/windows/winobject/system.py +++ b/windows/winobject/system.py @@ -16,6 +16,7 @@ from windows.winobject import service from windows.winobject import volume from windows.winobject import wmi from windows.winobject import kernobj +from windows.winobject import handle from windows.generated_def.winstructs import * @@ -60,27 +61,10 @@ class System(object): @property def handles(self): - size_needed = ULONG() - size = 0x1000 - buffer = ctypes.c_buffer(size) + """The list of system handles - try: - winproxy.NtQuerySystemInformation(16, buffer, size, ReturnLength=ctypes.byref(size_needed)) - except WindowsError as e: - pass - - size = size_needed.value + 0x1000 - buffer = ctypes.c_buffer(size) - winproxy.NtQuerySystemInformation(16, buffer, size, ReturnLength=ctypes.byref(size_needed)) - - x = SYSTEM_HANDLE_INFORMATION.from_buffer(buffer) - - class _GENERATED_SYSTEM_HANDLE_INFORMATION(ctypes.Structure): - _fields_ = [ - ("HandleCount", ULONG), - ("Handles", SYSTEM_HANDLE * x.HandleCount), - ] - return _GENERATED_SYSTEM_HANDLE_INFORMATION.from_buffer_copy(buffer[:size_needed.value]).Handles[:] + :type: [:class:`handle.Handle`] -- A list of Hanlde""" + return handle.enumerate_handles() @utils.fixedpropety def bitness(self):