Thread: NtQueryObject problem

  1. #1
    Registered User
    Join Date
    Mar 2005
    Posts
    69

    NtQueryObject problem

    after obtained all file handles open in the system,i have duplicated them in my
    process,and i've queried them with NtQueryObject for
    retrieving filenames...but with several handles my program goes in deadlock when it does the call , and i've also done checks for finding out what process those handles belong to,and these are some results

    "C:\\WINDOWS\\system32\\ZoneLabs\\vsmon.exe"
    "C:\WINDOWS\\system32\\services.exe"
    "C:\\WINDOWS\\system32\\lsass.exe"
    "C:\\WINDOWS\\system32\\svchost.exe"
    ...

    but sincerely...i don't think that querying an handle that belongs to a system service (like all the processes listed above),makes a call to NtQueryObject to wait forever...however,this is the code

    Code:
    // some defines from ntddk
    
    	 typedef struct _LSA_UNICODE_STRING { 
    		USHORT Length;
    		USHORT MaximumLength;
      		PWSTR Buffer;
    	} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
    
    	typedef struct _STRING { 
      		USHORT  Length;
      		USHORT  MaximumLength;
      		PCHAR  Buffer;
    	} ANSI_STRING, *PANSI_STRING;
    
     typedef struct _OBJECT_ATTRIBUTES {
    	ULONG uLength;
        HANDLE  RootDirectory;
        PUNICODE_STRING  ObjectName;
        ULONG  Attributes;
        PSECURITY_DESCRIPTOR  SecurityDescriptor;
        PVOID SecurityQualityOfService;
     } OBJECT_ATTRIBUTES,*POBJECT_ATTRIBUTES;
    
     typedef struct _CLIENT_ID {
    	 DWORD UniqueProcess;
    	 DWORD UniqueThread;
     } CLIENT_ID, *PCLIENT_ID;
    
    	typedef struct _SYSTEM_HANDLE_INFORMATION {
    		USHORT ProcessId;
            USHORT CreatorBackTraceIndex;
    		UCHAR ObjectTypeNumber;
    		UCHAR Flags;
    		USHORT Handle;
    		PVOID Object;
    		ACCESS_MASK GrantedAccess;
    	} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
    
    	typedef struct _SYSTEM_HANDLE_INFORMATION_EX {
    		ULONG NumberOfHandles;
    		SYSTEM_HANDLE_INFORMATION Information[1];
    	} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
    
    	typedef struct _OBJECT_NAME_INFORMATION {
    		UNICODE_STRING Name;
    	} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;


    Code:
    // the code is incomplete,for readibility purpose
    
    void GetFileHandles(){
    
     HANDLE hThisProcess;
    //.. initialize hThisProcess with GetCurrentProcess() and DuplicateHandle() ...
    
    // ... use NtQueryObject for obtaining the "File" type index,to be compared 
    // with ObjectTypeNumber field of SYSTEM_HANDLE_INFORMATION ,because
    // i'm interested in file handles only... that index will be hold in the
    // uFileTypeIndex variable
    
    // the pStruct variable points to the handle table ,it's a PSYSTEM_HANDLE_INFORMATION_EX
    // obtained via NtQuerySystemInformation() with SystemHandleInformation parameter 
    
        ULONG uLen = sizeof(UNICODE_STRING) + (MAX_PATH + 1) * sizeof(WCHAR);
    
        POBJECT_NAME_INFORMATION pNameInfo = (POBJECT_NAME_INFORMATION)malloc(uLen);  
    
    	HANDLE hSourceProcess;   // remote process
    	OBJECT_ATTRIBUTES oa;
    	CLIENT_ID ClientId;
    
        for(ULONG u = 0;u < pStruct->NumberOfHandles;u++)
    
         if(pStruct->Information[u].ObjectTypeNumber == uFileTypeIndex){  // check handle type,must be a file
    
          HANDLE hSource = (HANDLE)pStruct->Information[u].Handle,hCopy;
    
    	  memset(&oa,0,sizeof(oa));
    	  ClientId.UniqueThread = 0;
    	  ClientId.UniqueProcess = (DWORD)pStruct->Information[u].ProcessId; 
    
    	   if(NtOpenProcess(&hSourceProcess,PROCESS_ALL_ACCESS,&oa,&ClientId))
    	    continue;
    
    	  if(NtDuplicateObject(hSourceProcess,hSource,hThisProcess,&hCopy,PROCESS_QUERY_INFORMATION,0,0))
    	   continue;
    
    // with some file handles this call will not return...???
    
          if(NtQueryObject(hCopy,ObjectNameInformation,pNameInfo,uLen,NULL)){
    CloseHandle(hSourceProcess);
    	   CloseHandle(hCopy); 
    	   continue;
    	  }
    
    //...  do something with the filename,in pNameInfo->Name.Buffer
     
    	  CloseHandle(hCopy); 
                      CloseHandle(hSourceProcess);
    
    	 }
    	 
    	CloseHandle(hThisProcess);
    	free(pNameInfo);
    	free(pStruct); 
    
    }
    Last edited by Lionel; 10-04-2005 at 08:32 PM.

  2. #2
    Unregistered User
    Join Date
    Sep 2005
    Location
    Antarctica
    Posts
    341
    is this code running in user mode? I remember doing something remotely like this, and I had to enable debugging access to the process first to get info on processes like svchost.exe.

    yea, here's the code I wrote in an article on codeproject:

    Code:
    void GetDebugPrivs()
    {
        HANDLE hToken;
        LUID sedebugnameValue;
        TOKEN_PRIVILEGES tp;
    
        if (::OpenProcessToken(GetCurrentProcess(), 
              TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
        {
            if ( !::LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
            {
                ::CloseHandle( hToken );
            }
    
            tp.PrivilegeCount = 1;
            tp.Privileges[0].Luid = sedebugnameValue;
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    
            if ( !::AdjustTokenPrivileges( hToken, 
                 FALSE, &tp, sizeof(tp), NULL, NULL ) )
            {
                ::CloseHandle( hToken );
            }
    
            ::CloseHandle( hToken );
        }
    }
    Maybe you can try doing that before running these calls.

  3. #3
    Registered User
    Join Date
    Mar 2005
    Posts
    69
    Quote Originally Posted by rockytriton
    is this code running in user mode? I remember doing something remotely like this, and I had to enable debugging access to the process first to get info on processes like svchost.exe.

    yea, here's the code I wrote in an article on codeproject:

    Code:
    void GetDebugPrivs()
    {
        HANDLE hToken;
        LUID sedebugnameValue;
        TOKEN_PRIVILEGES tp;
    
        if (::OpenProcessToken(GetCurrentProcess(), 
              TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
        {
            if ( !::LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
            {
                ::CloseHandle( hToken );
            }
    
            tp.PrivilegeCount = 1;
            tp.Privileges[0].Luid = sedebugnameValue;
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    
            if ( !::AdjustTokenPrivileges( hToken, 
                 FALSE, &tp, sizeof(tp), NULL, NULL ) )
            {
                ::CloseHandle( hToken );
            }
    
            ::CloseHandle( hToken );
        }
    }
    Maybe you can try doing that before running these calls.
    it's running in user mode

    i've already enabled SE_DEBUG_NAME , SE_BACKUP_NAME and SE_RESTORE_NAME , and my process went in deadlock...then i tried not to enable them,and it worked!!

    but another little problem came...i could not open an handle to the "svchost.exe" process (with NtOpenProcess) and maybe some other system service,

    and could not duplicate an handle belonging to the "System" process...that's strange,maybe it was the BACKUP privilege that caused problems...i'll try to enable SE_DEBUG_NAME only and see what happens
    Last edited by Lionel; 10-05-2005 at 04:01 PM.

  4. #4
    Registered User
    Join Date
    Mar 2005
    Posts
    69
    someone told me:

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

    Your problem is this:

    When you query for object name on a pipe handle (opened for synchronous io, and where there are pending read operations) then your thread will hang. Permanently. And attempts to terminate the thread will possibly end in a bluescreen.

    There is no difference between system services and other applications, besides that services more often uses pipes.

    I don't know of solutions around this problem. GetFileType(...) and other attempts to determine that is it a pipe object will deadlock aswell. Plain stupid.

    - petter
    --------------------------------------------------------------------------------

    i think that DEBUG privilege is necessary for querying handles
    belonging to system services,and my code worked because "normal" processes were not using synchronized pipes or mailslots or whatever can be classified as a synchronized file object...but if there were such processes running in the system my code would have failed again (see petter's answer above)

    what solutions do you propose?
    Last edited by Lionel; 10-05-2005 at 04:32 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM