2008-04-27

In Vista, How Does the FLAGS Switch of REG.EXE Work?

Note: this content originally from http://mygreenpaste.blogspot.com. If you are reading it from some other site, please take the time to visit My Green Paste, Inc. Thank you.


A while back, there was a topic (Virtual Registry vs. "Real registry") in the Sysinternals Forums that brought up the question of how to set the virtualization-related flags of a registry key programmatically in Vista, rather than through the use of the REG.EXE tool's FLAGS switch. (For more information on the flags, see Mark Russinovich's article in TechNet Magazine, "Inside Windows Vista User Account Control"). Even before that topic in the forum, I had wondered how it was done but had not had a chance to explore. It didn't seem that many others were curious about it. That topic had resurrected the idea, but it quickly fell to the bottom of the list. I've finally gotten around to experimenting, and that leads to this write-up. I still don't see much in the way of this discussed anywhere, by searching for terms involved (data types, function param names, etc.), so hopefully this will help someone. (Keep in mind that there very well may be a reason Microsoft hasn't made this available through another, more direct API.)


In the referenced topic, I had gotten so far as determining that REG.EXE was doing its work through the use of NtSetInformationKey, an "undocumented" API in NTDLL.DLL.


NTSYSAPI 

NTSTATUS

NTAPI

NtSetInformationKey(

IN HANDLE KeyHandle,

IN KEY_SET_INFORMATION_CLASS InformationClass,

IN PVOID KeyInformationData,

IN ULONG DataLength );


After a bit of plonking around in WinDbg, I've come up with the following following details. REG.EXE calls NtSetInformationKey, specifying a value of 2 for the InformationClass parameter. This parameter is of type KEY_SET_INFORMATION_CLASS, which wdm.h tells us is an enum:


typedef enum _KEY_SET_INFORMATION_CLASS {

KeyWriteTimeInformation,

KeyWow64FlagsInformation,

KeyControlFlagsInformation,

KeySetVirtualizationInformation,

KeySetDebugInformation,

MaxKeySetInfoClass // MaxKeySetInfoClass should always be the last enum

} KEY_SET_INFORMATION_CLASS;


So the 2 for the InformationClass parameter would correspond to KeyControlFlagsInformation. WDM.H also suggests that this class has a type that one passes for the KeyInformationData parameter - KEY_CONTROL_FLAGS_INFORMATION:


typedef struct _KEY_CONTROL_FLAGS_INFORMATION {

ULONG ControlFlags;

} KEY_CONTROL_FLAGS_INFORMATION, *PKEY_CONTROL_FLAGS_INFORMATION;


We have a basic idea of how to call NtSetInformationKey now. But what are the values that the ControlFlags member of KEY_CONTROL_FLAGS_INFORMATION can be set to? It would appear that the following (self-made) enum covers the pertinent flags - at least the ones REG.EXE FLAGS can handle (there may be more):


typedef enum _CONTROL_FLAGS {

RegKeyClearFlags = 0,

RegKeyDontVirtualize = 2,

RegKeyDontSilentFail = 4,

RegKeyRecurseFlag = 8

} CONTROL_FLAGS;


The control flags are a bitmask, so you can OR them to set more than one.


Now that we have this information, what's left? We need to put it all together in a call to NtSetInformationKey. So, we need to get a pointer to the function in NTDLL.DLL. Then, we can declare a struct of type KEY_CONTROL_FLAGS_INFORMATION, set the ControlFlags member to be what we wish, and open a key to the desired location in the registry, that can be passed to NtSetInformationKey. In the end, we wind up with something like the following (error handling has been omitted):


typedef NTSYSAPI NTSTATUS (NTAPI* FuncNtSetInformationKey) (

HANDLE KeyHandle,

KEY_SET_INFORMATION_CLASS InformationClass,

PVOID KeyInformationData,

ULONG DataLength );

//...

FuncNtSetInformationKey ntsik = (FuncNtSetInformationKey)GetProcAddress(

GetModuleHandle( _T("ntdll.dll") ), "NtSetInformationKey" );

KEY_CONTROL_FLAGS_INFORMATION kcfi = {0};

kcfi.ControlFlags = RegKeyDontVirtualize | RegKeyRecurseFlag;

HKEY hTheKey = NULL;

RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Whatever"), 0, KEY_ALL_ACCESS, &hTheKey );

ntsik( hTheKey, KeyControlFlagsInformation, &kcfi, sizeof( KEY_CONTROL_FLAGS_INFORMATION ) );

RegCloseKey( hTheKey );

hTheKey = NULL;



The code above is the equivalent of invoking REG.EXE FLAGS HKLM\Software\Whatever SET DONT_VIRTUALIZE RECURSE_FLAGS. To clear the flags, just set kcfi.ControlFlags to RegKeyClearFlags (same as REG.EXE FLAGS HKLM\Software\Whatever SET).

Hopefully, this will prove useful to those that have wished to set these flags programmatically. In a future post, I hope to explore querying for these flags, ala REG.EXE FLAGS HKLM\Software\Whatever QUERY.


Note that this exploration was done on Windows Vista SP1. I would expect the content here to also apply to Windows Vista (no SP) as well as Windows Server 2008, but...

2008-04-25

My Answer to "Microsoft Advanced Windows Debugging and Troubleshooting" Puzzler 3

Note: this content originally from http://mygreenpaste.blogspot.com. If you are reading it from some other site, please take the time to visit My Green Paste, Inc. Thank you.

Previously, I had written about the puzzlers on the NTDebugging / Microsoft Advanced Windows Debugging and Troubleshooting blog - specifically, the most recent puzzler which involved reverse engineering some assembler. The answer was posted today - there were a lot of responses, and a lot of correct responses.

I had posted the hashes for my answer (which was correct), that I am now able to disclose...

void myfun( char* param1 )
{
size_t local1 = strlen( param1 );
for( int local2 = local1; local2 > 0; local2-- )
{
for( int local3 = 0; local3 < local2 - 1; local3++ )
{
if( *(param1+local3) > *(param1+local3+1) )
{
char local4 = *(param1+local3);
*(param1+local3) = *(param1+local3+1);
*(param1+local3+1) = local4;
}
}
}
}

2008-04-24

Microsoft Advanced Windows Debugging and Troubleshooting Puzzlers

Note: this content originally from http://mygreenpaste.blogspot.com. If you are reading it from some other site, please take the time to visit My Green Paste, Inc. Thank you.

Over on the Microsoft Advanced Windows Debugging and Troubleshooting blog, they've been posting a "Puzzler" every Monday and providing the answers the following Friday.

The puzzlers are fun to participate in and it is interesting to read people's responses - everyone has their own ideas and own experiences to draw off of.

With the third puzzler, the blog authors have decided to make the challenge a bit more difficult - the latest puzzler requires one to reverse engineer some assembler.

I've not got much experience with reverse engineering assembler - I can read some assembler and can usually get a very basic idea of what a targeted chunk of code is doing. So it was an interesting challenge for me to attempt to C-ify the assembler they provided. It doesn't appear that the authors are posting the responses until they reveal the answer (makes sense to me!). But I thought I'd post hashes of my response, which I'll also post once the NT Debugging blog authors post the answer and submitted comments / responses.

From Sigcheck:


Z:\NTDebuggingPuzzler3>sigcheck -h TheFunc.txt

Sigcheck v1.52
Copyright (C) 2004-2008 Mark Russinovich
Sysinternals - www.sysinternals.com

Z:\NTDebuggingPuzzler3\TheFunc.txt:
Verified: Unsigned
File date: 12:52 PM 4/22/2008
Publisher: n/a
Description: n/a
Product: n/a
Version: n/a
File version: n/a
MD5: 755394f9711b80968f17c8ffcb8f2394
SHA1: e8443f09eef43f2575aa08ba25f68267dba7243e
SHA256: 0e044419ef78f2fa7a8e258098f4f658426a8dc3e8a5b9a121a352c2dbbbfafc


EDIT 2008-04-24: The hashes are for the code that was submitted in my second response (not the entire response - just the code). In my first response, I inadvertently left some garbage in the code (an unnecessary / unused local I had been playing with) and I neglected to remove it before submitting. Not sure how it will all pan out when the comments / responses get posted tomorrow...