Re: [ctypes-users] NtQuerySystemInformation
Brought to you by:
theller
From: Cristian B. <cri...@gm...> - 2015-10-29 18:05:43
|
Thank you, It worked perfectly. I also wanted to get the types and names of the handles, so i duplicated the handles and i used NtQueryObject to get the type information and the name information and it worked On Thu, Oct 29, 2015 at 3:18 PM, eryksun <er...@gm...> wrote: > On 10/29/15, Cristian Badescu <cri...@gm...> wrote: > > After calling NtQuerySystemInformation with _stdcall (windll) as Diez > > suggested, i am getting STATUS_INFO_LENGTH_MISMATCH. After calling > realloc > > to get a new size a few time trying to get to the actual buffer size > > required (for SystemHandleInformation the function does not return the > > required buffer size) the function fails with an 0xC0000005 (Access > > Violation) error. This is the code i use: > > Use SystemExtendedHandleInformation (64) because it handles PIDs > greater than 65535. Note that your version of SYSTEM_HANDLE > incorrectly makes the ProcessId field a c_ulong. Actually it's a > c_ushort followed by another reserved c_ushort. > > Resize the structure to exactly the size returned in the 4th > parameter. Do this by calling ctypes.resize; don't call C realloc > directly. > > Here's a version that I've tested on Windows 7 and 10 in both 32-bit > and 64-bit processes in Python 2.7, 3.4, and 3.5. It has improved type > safety, error handling, and demonstrates using a property to return an > array for a variable-sized array field. > > from ctypes import * > from ctypes.wintypes import * > import functools > > ntdll = WinDLL('ntdll') > > PVOID = c_void_p > PULONG = POINTER(ULONG) > ULONG_PTR = WPARAM > ACCESS_MASK = DWORD > > @functools.total_ordering > class NTSTATUS(c_long): > def __eq__(self, other): > if hasattr(other, 'value'): > other = other.value > return self.value == other > def __ne__(self, other): > if hasattr(other, 'value'): > other = other.value > return self.value != other > def __lt__(self, other): > if hasattr(other, 'value'): > other = other.value > return self.value < other > def __bool__(self): > return self.value >= 0 > def __repr__(self): > value = c_ulong.from_buffer(self).value > return 'NTSTATUS(%08x)' % value > > STATUS_INFO_LENGTH_MISMATCH = NTSTATUS(0xC0000004) > > def WinErrorFromNtStatus(status): > last_error = ntdll.RtlNtStatusToDosError(status) > return WinError(last_error) > > class SYSTEM_INFORMATION_CLASS(c_ulong): > def __repr__(self): > return '%s(%s)' % (type(self).__name__, self.value) > > SystemExtendedHandleInformation = SYSTEM_INFORMATION_CLASS(64) > > class SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX(Structure): > _fields_ = (('Object', PVOID), > ('UniqueProcessId', HANDLE), > ('HandleValue', HANDLE), > ('GrantedAccess', ACCESS_MASK), > ('CreatorBackTraceIndex', USHORT), > ('ObjectTypeIndex', USHORT), > ('HandleAttributes', ULONG), > ('Reserved', ULONG)) > > class SYSTEM_INFORMATION(Structure): > pass > > PSYSTEM_INFORMATION = POINTER(SYSTEM_INFORMATION) > > class SYSTEM_HANDLE_INFORMATION_EX(SYSTEM_INFORMATION): > _fields_ = (('NumberOfHandles', ULONG_PTR), > ('Reserved', ULONG_PTR), > ('_Handles', SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX * 1)) > @property > def Handles(self): > arr_t = (SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX * > self.NumberOfHandles) > return POINTER(arr_t)(self._Handles)[0] > > ntdll.NtQuerySystemInformation.restype = NTSTATUS > ntdll.NtQuerySystemInformation.argtypes = ( > SYSTEM_INFORMATION_CLASS, # SystemInformationClass > PSYSTEM_INFORMATION, # SystemInformation > ULONG, # SystemInformationLength > PULONG) # ReturnLength > > def list_handles(): > info = SYSTEM_HANDLE_INFORMATION_EX() > length = ULONG() > while True: > status = ntdll.NtQuerySystemInformation( > SystemExtendedHandleInformation, > byref(info), > sizeof(info), > byref(length)) > if status != STATUS_INFO_LENGTH_MISMATCH: > break > resize(info, length.value) > if status < 0: > raise WinErrorFromNtStatus(status) > return info.Handles > > if __name__ == '__main__': > import os > import sys > if len(sys.argv) > 1: > pid = int(sys.argv[1]) > else: > pid = os.getpid() > for h in list_handles(): > if h.UniqueProcessId != pid: > continue > t = (h.HandleValue, h.ObjectTypeIndex, h.GrantedAccess) > print('%04x : %04x : %08x' % t) > |