Udostępnij za pośrednictwem


The Case of the Unexpected PsList Error

Not long after I deployed Windows Vista on my main desktop system I noticed that a process became unresponsive and appeared to be consuming excessive amounts of CPU. I had a command prompt handy, so I ran PsList to dump detailed information about the process as one of my troubleshooting steps. Instead of reporting apage full of statistics like I expected, however, PsList printed its banner, an error message, and exited:

 

PsList obtains information from the system performance counters, which an application accesses using standard Registry functions directed at the virtual HKEY_PERFORMANCE_DATA key, so the message indicated that PsList was unable to query the virtual performance keys. When you point PsList at a remote system and don’t have administrative rights on that system, or the system isn’t running the Remote Registry service, then PsList reports the same error, but I had never seen the message when using PsList to look at a local system. Something was different about Windows Vista and I set out to learn what.

Putting my original troubleshooting mission on hold, I launched Process Monitor and repeated the PsList command with Process Monitor looking on. I didn’t have a firm expectation that it would reveal the cause of the problem, but experience has taught me that Process Monitor (and its predecessors Filemon and Regmon) often solves seemingly unexplainable problems like this. I scanned the trace looking for anomalous error codes, because when they’re present they almost always point to the source of a problem, and found an access denied error:

For some reason, PsList, running as a standard user because I hadn’t elevated the command prompt from which I ran it, was unable to open the PerfLib registry key for read access. I was perplexed because on Windows XP I had been able to run PsList as a standard user. I launched Regedit, navigated to the key, and viewed its permissions. As I suspected, standard users aren’t members of any of the groups the permissions grant access (note the presence of two new performance-related groups, Performance Log Users and Performance Monitor Users):

 

I quickly confirmed that to be the reason for PsList’s failure by granting the Interactive Users group read access to the key and verifying that PsList subsequently worked. Now I was left with the question of what permissions Windows XP assigns the key. I switched to a Windows XP test system and viewed the key’s permissions. Sure enough, Interactive Users have read access, explaining why PsList works as a standard user on Windows XP systems:

I then pondered the reason for the change. I suspected the new permissions close an information disclosure hole, but after some thought I concluded that they aren’t closing any hole.  The PerfLib key is where performance providers register their counters and DLLs, so when a tool like PsList queries a counter the performance API loads the associated DLL into the querying process and calls functions in the DLL that return the desired data. Because the DLLs execute in the context of the process into which they load, they can’t implement security that can’t be easily circumvented by the process. It’s therefore the responsibility of a performance data source, which might be the kernel or an application like Internet Information Server (IIS), to prevent unauthorized access to its performance data.

Preventing read access to the PerfLib key is therefore the equivalent of having a performance DLL implement security. While locking down the key prevents the performance API from determining what counters are available and what DLLs provide performance data, with the exception of add-on applications, the core registrations are constant from system to system. That means that a process can circumvent any protection the locked-down key is attempting to provide by directly loading performance DLLs and calling their data functions.

To make a long story short, I filed a bug against Windows Vista Service Pack 1 (SP1) and Windows Server 2008 to have Interactive Users added back to PerfLib’s permissions. The reliability and diagnostics team reported back that the permissions changed inadvertently during the release of Windows Server 2003, but I convinced them it didn’t make sense, so in SP1 and Windows Server 2008 you won’t need to edit PerfLib’s permissions to be able to run tools like PsList as a standard user.

 

Another case closed by Process Monitor!

Comments

  • Anonymous
    January 01, 2003
    Is this why TCPView doesn't list process name and icons anymore?

  • Anonymous
    July 09, 2007
    Thanks Mark, I was hoping this would be corrected soon.

  • Anonymous
    July 09, 2007
    Why use the perf stuff over whatever taskmgr and process explorer uses?

  • Anonymous
    July 11, 2007
    Why did some of the other comments (including one from Mark) disappear from this post?

  • Anonymous
    July 11, 2007
    So what about the unresponsive process that leads you to launch PsList in the first place ? I'd like to know how you handle a process consuming CPU, because it happens from time to time and i'd be glad to learn from you. Thanks anyway.

  • Anonymous
    July 11, 2007
    Nice job. mark. I love your posts in this blog.

  • Anonymous
    July 12, 2007
    Great Article. Very useful. However, it would be possible for my c++ application to gain read access to the PerfLib key? (having access to HKEY_PERFORMANCE_DATA key without adding manually the Interactive Group to the PerfLib’s permissions).

  • Anonymous
    July 12, 2007
    Thats a very good point Souplounite maybe that will be the next blog entry. You wouldn't have access to the key decoder you would have to load the performance dll's in your application using LoadLibrary() and then using GetProcAddress() on the on the functions you would want to use. It would be easier just to alter the permission. nice work mark the sysinternals tools are invaluable to any sys admin/developer. Also I seen some debate on how they are packaged and I love the small single exe! installer pffff.

  • Anonymous
    July 14, 2007
    hmmmm when ever i hear the words "Windows Vista" i cringe.

  • Steve
  • Anonymous
    July 17, 2007
    The comment has been removed

  • Anonymous
    July 24, 2007
    Ah, thanks for that...     I noticed that as soon as I migrated to Vista, but couldn't figure out why the change was done.  Didn't seem to have the necessary security impact... Glad this will be resolved shortly.

  • Anonymous
    August 05, 2007
    FYI - I had a surprisingly tough time refinding your blog. The bookmark I had for your blog is now a dead link: http://www.microsoft.com/technet/sysinternals/Blog/ Shouldn't a redirect to the current location have been maintained?

  • Anonymous
    August 06, 2007
    Thank you very much for sharing your thoughts. It is always great pleasure to read your posts.

  • Anonymous
    September 20, 2007
    The same thing occurs on Server 2003, it appears. I am running a standalone 2K3 machine, and pslist.exe gives the same "Failed to take process snapshot on %computername%" when run in a remote desktop session as a user. It works when run under an administrative account, and the same workaround you supply above has solved the issue for my user account.

  • Anonymous
    September 30, 2007
    So, I deleted the MMCSS service (sc delete MMCSS) just for test, but how do I re-create it? can you make a .reg file  including info of this service?

  • Anonymous
    August 07, 2008
    Hi Mark, Just a quick one to inform you that i have got an online version of your fabulous process list tool running over at: http://w3dt.net/tools/pslist/ feel free to contact me (dnedved [at] gmail [dot] com) if you have any comments/suggestions. cheers.

  • Anonymous
    April 15, 2009
    The comment has been removed

  • Anonymous
    August 28, 2009
    Hi Mark, I am also facing to similar question about perflib in my test program. However, I haven't got the answer from Microsoft, I also used your tool "Process Monitor" but could not find any hints. Could you help me? My environment is Windows 2008 Enterprise SP2. My code is very simple, just get the content of perflibCounter and re-write back to it. It runs well in getting the content, but when it re-writes back, it reports that registry key handle is bad. My program works well in Windows 2000/2003. I also tried to modify the permission of perflib in registry, it does not work either. Regards, Ben