Results 1 to 11 of 11

Thread: NtQuerySystemInformation and open handles

  1. #1

    NtQuerySystemInformation and open handles

    I'll forward here a post from microsoft.public.win32.programmer.kernel newsgroup (Message-ID: <cgkcte$1kcp$1@mamut.aster.pl>)
    Quote Originally Posted by qfel
    NtQuerySystemInformation can return all opened handles, but in all infos I
    can find in net, returned array provides 16-bit handle values and handles
    are pointer-precision values (I tested my XP for handle limit and I was able
    to open much more then 2^16 files). Are docs found on the net invalid or
    native system calls are not very compatible..?
    ...and my reply:
    I've just written quick and dirty code to check what this 'handles'
    actually are. All of them are 0 (on w2k sp4). It returns valid type and
    kernel object address, so maybe this is the way.

    Interestingly, there is some sample code in the book "Windows NT/2000
    native API reference" for enumerating any process' open handles. Firstly it
    calls NtQuerySystemInformation with class SystemHandleInformation, and then
    uses ZwDuplicateObject for each handle to get private copy of it. However,
    foreign handle supplied to ZwDuplicateObject is the same abovementioned
    handle - so how it's supposed to work if all of them are null?
    Code:
    #include <windows.h>
    #include <stdio.h>
    
    typedef DWORD (NTAPI *pNtQuerySystemInformation)(DWORD info_class, void *out, DWORD size, DWORD *out_size);
    
    struct SYSTEM_HANDLE_INFORMATION
    {
    	ULONG	ProcessId;
    	UCHAR	ObjectTypeNumber;
    	UCHAR	Flags;
    	USHORT	Handle;
    	PVOID	Object;
    	ACCESS_MASK	GrantedAccess;
    };
    
    SYSTEM_HANDLE_INFORMATION buf[100000];
    
    void main()
    {
    	DWORD size;
    	pNtQuerySystemInformation NtQuerySystemInformation = 
    		(pNtQuerySystemInformation) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
    	NtQuerySystemInformation(16, buf, sizeof(buf), &size);
    	DWORD n = size/sizeof(SYSTEM_HANDLE_INFORMATION);
    	for (DWORD i=0; i<n; i++)
    	{
    		printf("%08x: PID: %08x, type: %02x, handle: %04x, ptr: %08x\n", i,
    			buf[i].ProcessId, buf[i].ObjectTypeNumber, buf[i].Handle, buf[i].Object);
    	}
    	DebugBreak();
    }
    Anyone got some info about this?

  2. #2
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,048
    Blog Entries
    5
    Hi,

    All I can say at the moment after checking out what is returned from SystemHandleInformation (an array of SYSTEM_HANDLE_INFORMATION structures), is that "handles" are indeed 16 bit values, they begin numbering from 04h for each PID and increase to the total number of (open?) handles for each process, 0004h, 0008h, 000Ch,...

    If you type PROC -x <process> in Softice you'll get further Handle info including the total number of handles. This number matches the number of SYSTEM_HANDLE_INFORMATION structures returned for each process.

    As far as I can tell, everything looks fine. I'm not sure what 'pointer-precision values' are supposed to be or why these 16 bit handles don't match what this guy thinks they should be.

    Kayaker

  3. #3
    Well, HANDLE type is 32-bit, but NtQuerySystemInformation returns 16-bit "handles", which are anyway all NULL (at least on my system).
    Code:
    00000000: PID: 00001041, type: 08, handle: 0000, ptr: 00040005
    00000001: PID: 001f0fff, type: 08, handle: 0000, ptr: 00080006
    00000002: PID: 001f03ff, type: 08, handle: 0000, ptr: 000c0012
    00000003: PID: 00000000, type: 08, handle: 0000, ptr: 00100012
    00000004: PID: 00020019, type: 08, handle: 0000, ptr: 00140012
    00000005: PID: 0002001f, type: 08, handle: 0000, ptr: 00180012
    00000006: PID: 0002001f, type: 08, handle: 0000, ptr: 001c0012
    00000007: PID: 00000020, type: 08, handle: 0000, ptr: 00200012
    00000008: PID: 00020019, type: 08, handle: 0000, ptr: 00240012
    00000009: PID: 0002001f, type: 08, handle: 0000, ptr: 00280008
    0000000a: PID: 001f0003, type: 08, handle: 0000, ptr: 002c0012
    0000000b: PID: 0002001f, type: 08, handle: 0000, ptr: 00300008
    0000000c: PID: 001f0003, type: 08, handle: 0000, ptr: 00340012
    0000000d: PID: 0002001f, type: 08, handle: 0000, ptr: 00380006
    0000000e: PID: 001f03ff, type: 08, handle: 0000, ptr: 003c0006
    0000000f: PID: 001f03ff, type: 08, handle: 0000, ptr: 00400006
    ...
    [edit]
    The results seem strange anyway, what those PIDs suppose to be? Have I made some silly error in my code?
    Last edited by omega_red; September 2nd, 2004 at 15:34.

  4. #4
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,048
    Blog Entries
    5
    Hi

    I can tell right off that you seem to be offset by 1 DWORD. The 1st DWORD returned by NtQuerySystemInformation/SystemHandleInformation is the *number* of SYSTEM_HANDLE_INFORMATION structures that follow, an array of arrays.

    The first dword you show is 1041, this is the number of structures to follow, offset your output by 1 dword and it should make sense.

    The PID you have should probably be 00000008 (default System pid)
    ObjectTypeNumber should be your 5, 6 ,12...
    Flags can be 00 or 01 I think
    Handle is 0004, 0008, 000c, etc.
    GrantedAccess will be values like 001f0fff

    If you type PROC in Softice you'll see the pid's of all the processes, these seem to be in the same order (load order?) as the "groups" of SYSTEM_HANDLE_INFORMATION strucs returned by SystemHandleInformation.


    Further comment:
    It would appear then that Object Handles as we know them (passed from API calls for example) are zero-extended 16 bit values from 0004h - 0FFFFh that the system assigns sequentially for each process. This should give a total of 16,383 handles available for each process. Logically enough I suppose, MS decided that was enough (Bugcheck protected?) So what will happen with 64bit processors, zero-extended dword values passed as 64bit? ;-)

  5. #5
    Oh well *slaps his head*. One dword and such a mess
    It also lightened the original question: why this handles are 16-bit, although there can be more than 65536 handles per system.

    Code:
    00000000: PID: 00000008, type: 05, handle: 0004, ptr: 81ad63c0
    00000073: PID: 00000000, type: 1a, handle: 0004, ptr: 81530b08
    000000b5: PID: 000000ac, type: 11, handle: 0004, ptr: e134a830
    000000d6: PID: 000000c4, type: 11, handle: 0004, ptr: e1332910
    ...
    Handle values are not systemwide unique.

  6. #6
    Four-F
    Guest
    The kernel object handles are NOT 16 bit values.

    First, open your copy of "Inside Microsof Windows 2000" and look at Figure 3-14 "Process handle table architecture in Windows 2000". Then go deep into ExpLookupHandleTableEntry and you will see something like this:

    Code:
    //
    //  Decode the handle index into its separate table indicies
    //
    
    l = (Handle.Index >> 24) & 255;
    i = (Handle.Index >> 16) & 255;
    j = (Handle.Index >> 8)  & 255;
    k = (Handle.Index)       & 255;
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  7. #7
    So how do you explain this? Handles returned by NtQuery.. ARE 16bit...

  8. #8
    Quote Originally Posted by omega_red
    So how do you explain this? Handles returned by NtQuery.. ARE 16bit...

    the several components of a 32bit handle are used to select one handletable

    Code:
        if ( l != 0 ) return NULL;
        if (HandleTable->Table[i] == NULL) return NULL;
        if (HandleTable->Table[i][j] == NULL) return NULL;
        return &(HandleTable->Table[i][j][k]);
    and handles returned by NtQuery.. are probably always Table[i] handles

  9. #9
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,048
    Blog Entries
    5
    Hi, thanks for clarifying that those are actually index values.

  10. #10
    Yes, it makes sense now and explains why they are not unique.

  11. #11
    Four-F
    Guest
    The right answer is: ObpCaptureHandleInformation callback truncates handle values down to USHORT.

    Code:
    (*HandleEntryInfo)->HandleValue = (USHORT)((ULONG_PTR)(HandleIndex));
    I've attached the simple msvc6 project. It creates 16384 named events. Run handle -a -p handles at appropriate moment and you will see something like this:

    Code:
     handle -a -p handles
    
     ffe8: Event         \BaseNamedObjects\MyEvent00016360
     ffec: Event         \BaseNamedObjects\MyEvent00016361
     fff0: Event         \BaseNamedObjects\MyEvent00016362
     fff4: Event         \BaseNamedObjects\MyEvent00016363
     fff8: Event         \BaseNamedObjects\MyEvent00016364
     fffc: Event         \BaseNamedObjects\MyEvent00016365
        0: Event
        4: Event
        8: Event
        c: Event
       10: Event
       14: Event
       18: Event
       1c: Event
       20: Event
       24: Event
       28: Event
       2c: Event
       30: Event
       34: Event
       38: Event
       3c: Event
       40: Event
       44: Event         <- This is the last created event with the name
                            "\BaseNamedObjects\MyEvent00016383".  And its
                            handle is 0x10044
    Attached Files Attached Files
    I promise that I have read the FAQ and tried to use the Search to answer my question.

Similar Threads

  1. Dbgeng based handles (PART 2 .............)
    By blabberer in forum Blogs Forum
    Replies: 0
    Last Post: January 29th, 2013, 21:15
  2. The handles button...
    By y0verflow in forum OllyDbg Support Forums
    Replies: 5
    Last Post: April 10th, 2008, 19:28
  3. Window handles
    By Quell in forum Tools of Our Trade (TOT) Messageboard
    Replies: 2
    Last Post: December 26th, 2004, 12:17
  4. Replies: 6
    Last Post: March 19th, 2003, 16:57
  5. Handles window displays list of handles owned by d
    By Anonymous in forum OllyDbg Support Forums
    Replies: 10
    Last Post: March 15th, 2003, 10:41

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •