Re: NtQuerySystemInformation

Cristian Badescu <[email protected]> Thu, 29 Oct 2015 20:05:15 +0200
Newsgroups gmane.comp.python.ctypes
Message-ID <CA+NeSDKn_vo3aGBCWhghejq-d92G0a=rJWijpHf3wGPHKquzFA@mail.gmail.com>
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 <[email protected]> wrote:

> On 10/29/15, Cristian Badescu <[email protected]> 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)
>

------------------------------------------------------------------------------

_______________________________________________
ctypes-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ctypes-users