Failed HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009

Hello,

We have a KMDF, non-PnP, kernel service that has been working great. During
testing, we’ve discovered that when it tries to open the following key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009

We receive the following error from ZwQueryKey() even though ZwOpenKey() was successful:

status: 0xC00000024, which is STATUS_OBJECT_TYPE_MISMATCH

Of course, our driver converts the user mode path to kernel mode. Anyway, for all other keys that we’ve tested, regular and symbolic, the code works properly.

So, I am hoping that someone may know what is special about this key… I think that it is related to performance information and it has two REG_MULTI_SZ values: “Counter” and “Help”.

I am able to export this key, so I don’t believe that it is corrupt. I was able to get information about it using www.somarsoft.com’s dumpreg.exe. Its output looked correct, but the last edit datetime, was a bizaar negative number.

Anyway, I would really appreciate learning what you know about this key.

Thanks,

Mike

Here is the relevant code…


RtlZeroMemory(&attributes, sizeof(OBJECT_ATTRIBUTES));

InitializeObjectAttributes(&attributes, (UNICODE_STRING*)key,
(OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), NULL, NULL);

status = ZwOpenKey(&hKey, KEY_ALL_ACCESS, &attributes);
.
.
.
status = ZwQueryKey(hKey, KeyFullInformation, NULL, 0, &resultLength);

Oops! Please replace

“During testing, we’ve discovered that when it tries to open the following key:”

with

“During testing, we’ve discovered that when it tries to QUERY the following key:”

If you have tried what I asked (InitializeObjectAttributes without OBJ_KERNEL_HANDLE), you’d notice that this key is special : the handle value is always 0x80000050, with or without OBJ_KERNEL_HANDLE !

And 0x80000050 is exactly the value of HKEY_PERFORMANCE_TEXT as defined in winreg.h.

So it is not actually a handle but kind of magic number. Maybe it cannot be accessed from kernel mode by “conventional means” at all, at least in WinXP 32-bit.

Good luck.
–pa

I did some research on just the registry key and have found an interesting trail to follow…

It seems that there is a known corruption issue for performance data. In my case, the \009 indicates it the English version. In RegEdit, if you open the key and go to the bottom of the Count and Help lists, there are blank lines, which, according to what I have read is bad, bad, bad! I found that this situation existed on my Vista 64-bit development computer and my Win7 64-bit test system.

So, I am thinking that STATUS_OBJECT_TYPE_MISMATCH is trying to say that some of the data was bad when I tried to query this key.

There is a very good summary of this issue at the following link,

http://ferventcoder.com/archive/2008/08/10/possible-performance-counter-corruption-or-performance-counters-are-just-disabled.aspx

and Microsoft has published a manual method to fix it. I will try to fix it and see if this issue disappears. I will report my results…

More to follow…

Mike

Again, the handle value for this key is 0x80000050, *on the usermode side*. The high bit of the handle, 0x8000000, normally means that it is a kernel handle; it is set on handles created with OBJ_KERNEL_HANDLE.
So the object manager (or whatever is responsible for mapping handles to objects) thinks that it is handle 0x50 in the system table - but it is not! Handle 0x50 may already exist and belong to something very different, not a registry key. Hence the type mismatch error.

Good luck once more,
–pa

Hi Pavel,

Thank you for taking the time to reply and reiterate your advice to me. I apologize for the delay in
responding, but my company threw me onto a jet for the last week to take care of some customer issues…

I’ve finally returned and have followed up on your postings. Here is what I’ve learned…

The function on which I am working scans the registry to collect information about keys (last write date, security) and their values. When I reach the key that we are discussing, I get the
STATUS_OBJECT_TYPE_MISMATCH error when OBJ_KERNEL_HANDLE is included in the InitializeObjectAttributes() function call.

I removed OBJ_KERNEL_HANDLE from the init, and now ZwOpenKey() and ZwQueryKey() do not return errors, and the handle contains 0xffffffff`80000050. The query results provided the following information:


+0x000 LastWriteTime : _LARGE_INTEGER 0x1cc0863`e8f42280
+0x008 TitleIndex : 0
+0x00c ClassOffset : 0n4294967295
+0x010 ClassLength : 0
+0x014 SubKeys : 1
+0x018 MaxNameLen : 0n32
+0x01c MaxClassLen : 0
+0x020 Values : 0
+0x024 MaxValueNameLen : 0
+0x028 MaxValueDataLen : 0
+0x02c Class : [1] “”

I was suspicious about these results because the SubKeys field indicated 1 rather than 2. We expect to find “Counters” and “Help” as subkeys. I continued with the debugger and found that when I open the subkey, its name is “Initiator Id 255”, so we definitely do not have the correct handle. Do you agree?

I opened regedit and scanned for “Initiator Id 255” and found that it exists in the following location:
HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi Port 3\Scsi Bus 0\Initiator Id 255

So, it seems that without OBJ_KERNEL_HANDLE, I am absolutely accessing the wrong key. Hopefully, this information will help us generate more ideas…

You’ve mentioned HKEY_PERFORMANCE_DATA… I am going to google and see if I can find anything relating to accessing it in kernel mode.

Thank you for your help and I hope that you have time to provide more suggestions. I will post what I learn from my googling.

Mike

Here are some good links for others who have investigated this same issue… The posting “Getting HKEY_PERFORMANCE_DATA” is the most relevant, but is user mode. My goal is to query and get the two subkeys and their attributes (names, security, last write date), and to emit any performance data as a base64 binary blob. I don’t need to parse it.


http://support.microsoft.com/kb/890648 reported that “You may receive a STATUS_INVALID_HANDLE error or a stop error when you try to close an HKEY_PERFORMANCE_TEXT handle or an HKEY_PERFORMANCE_NLSTEXT handle from a kernel mode device driver”, which implies that it is possible to open the handle and collect information from it.



For anyone that doubts sterni HKEY_PERFORMANCE_DATA does exist, however you won’t see it in Regedit, as its not an actual key nor is the data it retrieves located in the registry database. This “key” only exists in Windows NT, 2000, and XP.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/perfdata_8g55.asp

Pasted from http:
--------------------------

--------------------------
Windows Remote Registry function will open this special key. Is it only available in user mode?

3.1.5.28 OpenPerformanceText (Opnum 32)
The OpenPerformanceText method is called by the client. In response, the server opens a handle to the HKEY_PERFORMANCE_TEXT predefined key. The HKEY_PERFORMANCE_TEXT predefined key is used to retrieve performance information from a registry server using only the BaseRegQueryInfoKey, BaseRegQueryValue, BaseRegEnumValues and BaseRegCloseKey methods.
error_status_t OpenPerformanceText(
[in, unique] PREGISTRY_SERVER_NAME ServerName,
[in] REGSAM samDesired,
[out] PRPC_HKEY phKey
);

Pasted from http:
-------------------------

-------------------------
Getting HKEY_PERFORMANCE_DATA
Filed under: NetBIOS/SMB

Hi everybody,

I spent most of last Saturday exploring how SysInternals? PsList program works, and how I could re-implement it as an Nmap script. I quickly discovered that the HKEY_PERFORMANCE_DATA (HKPD) registry hive was opened, then it got complicated. So I went digging for documentation and discovered a couple journals posts written by Microsoft?s Matt Pietrek wrote back in 1996. Those led me to the WinPerf.h header file. The three of those together were enough to get this working.

To summarize, this is based on these resources:
? Journal post 1
? Journal post 2
? WinPerf.h (included with Visual Studio)

The HKEY_PERFORMANCE_DATA hive can be accessed either locally through standard registry API functions or remotely through MSRPC functions. Since MSRPC is essentially a layer on top of the API functions, these are essentially the same thing; as long as you have an administrator account, it doesn?t matter where you?re coming from, as long as you can call OpenHKPD() and QueryValue().

An important thing to keep in mind is that this isn?t standard registry stuff ? whereas the Windows registry is a (fairly) static collection of data in well known places, the HKEY_PERFORMANCE_DATA is a dynamically generated snapshot of the system?s current state that isn?t necessarily accessed through well known places (although it?s pretty simple to get an index). You basically query for what you want, and get back a huge chunk of data that has to be parsed. The majority of this post will be related to the type of information you get back; how to actually parse it is described better in the references above.

There are likely libraries already written to parse performance data; in fact, in the link I gave above, Pietrek provides C++ code for parsing performance data locally. Since Nmap scripts are Lua, and I highly doubt that there?s a Lua library written. So, everything I?ve written is parsed by hand.
As of Nmap?s SVN revision 11397, it can be found in svn://svn.insecure.org/nmap-exp/ron/nmap-smb (I haven?t put it into the main trunk yet), in the file nselib/msrpcperformance.lua.
Pasted from http:
----------------------------------</http:></http:></http:>

> I removed OBJ_KERNEL_HANDLE from the init, and now ZwOpenKey() and ZwQueryKey()
do not return errors, and the handle contains 0xffffffff`80000050.

So, it seems that without OBJ_KERNEL_HANDLE, I am absolutely accessing the wrong
key. Hopefully, this information will help us generate more ideas…

Ok, so this time the system handle 0x50 was a registry key and ZwQueryKey did not fail.

But why you are so concentrated on the HKEY_PERFORMANCE_DATA key?
It is most likely not broken and does not need fixing.
Now you know the reason of this error, can you just skip it and proceed further?

Regards,
–pa

sss

Hi Pavel,

Hmmm… My browser locked up … Sorry for the junk “sss” message…

The registry scanning function that I have created is based on our company’s software requirements… I am not specifically interested in the HKEY_PERFORMANCE_DATA key, except that when the scanner recursively processes HKEY_LOCAL_MACHINE\SOFTWARE, it hits the
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009 key, and fails. I can catch the error and ignore it, but then this key’s name, last write date, security attributes, and values are lost. Since this scanning function may become part of a backup application, I cannot just discard information.

So… I am kind of stuck… Right now, so I can continue my development work, I catch this error, and log it. I’ve run our scanner on several computers with various versions of Windows, and it works great except for this performance key… This key is the only item that generates an error status.

I haven’t found anything on MSDN that says that I cannot ZwQueryKey() this key in kernel mode. My Management/Bosses will not permit me to just ignore this key unless I find something from Microsoft saying that it is not possible to get the required information in kernel mode.

So… I am kind of stuck… Someone must have hit this issue and resolved it… I still wonder whether this issue isn’t about the query failing because it is a special key, but rather that it is failing because the values in the key are improper… I’ve looked at the Counter and Help lists, and they have two empty items at the end, which is a corruption that has been discussed by users rather than developers. I think that I am going to try to correct the corruption and see if it helps… Arggg… Nothing like being stuck at 99.9999999% done!!!

Mike

>

sss

Snakes on a Mailing List?