registry filtering problem

Hi,

Could anybody tell me how should we normally filter NtSaveKey, NtRestoreKey and NtReplaceKey native APIs, which are exported by ntdll.lib in a minifilter? AFAIK the registry callbacks stuff (CmRegisterCallbackEx) does not expose any callbacks for those APIs, not even on the Vista SP1 beta DDK (6001).

thank you very much,

Sandor LUKACS

Sandor,

None of the registry API’s are directly exposed through the CM. What you
need to do is register for callback and then filter out what you want in
the RegNtxxx request types.

The easiest method I have found for determining how calls are
implemented is to implement a skeleton driver which simply logs
requests. Then write a small application which performs the operations
you want to know about and see which requests are made to the CM.

Pete

Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
(303)546-0300

xxxxx@bitdefender.com wrote:

Hi,

Could anybody tell me how should we normally filter NtSaveKey, NtRestoreKey and NtReplaceKey native APIs, which are exported by ntdll.lib in a minifilter? AFAIK the registry callbacks stuff (CmRegisterCallbackEx) does not expose any callbacks for those APIs, not even on the Vista SP1 beta DDK (6001).

thank you very much,

Sandor LUKACS


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@kerneldrivers.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

I confirm that all the Registry operations are indeed properly reflected in the Vista Registry callbacks, and I’ve gone the same route from using hooks on the older Windows versions. One word of warning though. The info at this URL on modifying input parameters is incorrect:

http://msdn2.microsoft.com/en-us/library/aa906579.aspx

Contrary to the docs, one can’t just change input parameters and return the STATUS_SUCCESS as the original parameters are still used in this case. We have to roll our own requests instead and return the STATUS_CALLBACK_BYPASS.

Hope it helps,
Ilya Faenson

Hi,

Thanks for the reply, but I still think, that the registry filtering doesn’t cover ALL registry operations. I have double checked it, with both Process / Registry Monitor and also with a very simple registry filter driver, that only executed a KdPrint() with Argument1 and PID for ALL callbacks recevied on the routine registered with CmRegisterCallbackEx. In both cases (Process Monitor and our driver) the only thing I see (except open & close) is a RegNtPreQuerySecurity / RegNtPostQuerySecurity pair for a key, on which I execute NtSaveKey (for example).

This is an example from a Process Monitor log:

173 12:58:55.4948082 PM ntsavekey.exe 2176 RegOpenKey HKLM\SYSTEM\CurrentControlSet\Services\CLFS REPARSE Desired Access: Read/Write
174 12:58:55.4948454 PM ntsavekey.exe 2176 RegOpenKey HKLM\System\CurrentControlSet\Services\CLFS SUCCESS Desired Access: Read/Write
217 12:58:58.5507911 PM ntsavekey.exe 2176 RegQueryKeySecurity HKLM\System\CurrentControlSet\Services\CLFS SUCCESS
266 12:59:02.4259138 PM ntsavekey.exe 2176 RegCloseKey HKLM\System\CurrentControlSet\Services\CLFS SUCCESS

The user mode code that successfully reads and saves the registry key is:


// open registry key
objName.Buffer = L"\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\CLFS";
objName.Length = (USHORT)(wcslen(objName.Buffer) * sizeof(WCHAR));
objName.MaximumLength = objName.Length;

InitializeObjectAttributes(
&objAttr,
&objName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );

printf(“BEFORE NtOpenKey: press any key to continue…\n”);
_getch();

status = NtOpenKey(
&keyHandle,
GENERIC_READ | GENERIC_WRITE,
&objAttr );
if (!NT_SUCCESS(status))
{
keyHandle = NULL;
printf(“ERROR: could NOT open registry key, error 0x%08x\n”, status);
retVal = -4;
__leave;
}

printf(“AFTER NtOpenKey / BEFORE NtSaveKey: press any key to continue…\n”);
_getch();

// save key to file
status = NtSaveKey(
keyHandle,
fileHandle );
if (!NT_SUCCESS(status))
{
printf(“ERROR: could NOT save key to file, error 0x%08x\n”, status);
retVal = -5;
__leave;
}

printf(“key successfully saved to file\n”);

printf(“AFTER NtSaveKey: press any key to continue…\n”);
_getch();

On request, I can send a full user-mode example :slight_smile:

Any ideas?

Sandor LUKACS

> I confirm that all the Registry operations are indeed properly reflected in the Vista Registry callbacks,

and I’ve gone the same route from using hooks on the older Windows versions.

We actually have a working registry filter driver on Vista, registry callbacks, except those few API calls, that seem to bypass any callback filtering attempt. The problem is, that I have found no clean/normal way to filter those native API calls.

Are you really sure, that those calls (NtSaveKey etc.) are filtered by both your legacy (hook based) and registry callback based drivers?

thank you,

Sandor

If you check the list of REG NOTIFY classes then there is nothing which
suggests it should filter NtSaveKey. On Vista there is RegNtPreLoadKey,
RegNtPostLoadKey, RegNtPreUnLoadKey, RegNtPostUnLoadKey which naturally map
to the RegLoadKey/RegUnloadKey Apis but nothing supports
savekey/restorekey/savekey. You will need to develop a file system filter
driver for this purpose or otherwise resort to some weird heuristics which
will provoke false positives.

/Daniel

wrote in message news:xxxxx@ntfsd…
> Hi,
>
> Thanks for the reply, but I still think, that the registry filtering
> doesn’t cover ALL registry operations. I have double checked it, with both
> Process / Registry Monitor and also with a very simple registry filter
> driver, that only executed a KdPrint() with Argument1 and PID for ALL
> callbacks recevied on the routine registered with CmRegisterCallbackEx. In
> both cases (Process Monitor and our driver) the only thing I see (except
> open & close) is a RegNtPreQuerySecurity / RegNtPostQuerySecurity pair for
> a key, on which I execute NtSaveKey (for example).
>
> This is an example from a Process Monitor log:
> …
> 173 12:58:55.4948082 PM ntsavekey.exe 2176 RegOpenKey
> HKLM\SYSTEM\CurrentControlSet\Services\CLFS REPARSE Desired Access:
> Read/Write
> 174 12:58:55.4948454 PM ntsavekey.exe 2176 RegOpenKey
> HKLM\System\CurrentControlSet\Services\CLFS SUCCESS Desired Access:
> Read/Write
> 217 12:58:58.5507911 PM ntsavekey.exe 2176 RegQueryKeySecurity
> HKLM\System\CurrentControlSet\Services\CLFS SUCCESS
> 266 12:59:02.4259138 PM ntsavekey.exe 2176 RegCloseKey
> HKLM\System\CurrentControlSet\Services\CLFS SUCCESS
> …
>
> The user mode code that successfully reads and saves the registry key is:
>
> …
> // open registry key
> objName.Buffer =
> L"\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\CLFS";
> objName.Length = (USHORT)(wcslen(objName.Buffer) * sizeof(WCHAR));
> objName.MaximumLength = objName.Length;
>
> InitializeObjectAttributes(
> &objAttr,
> &objName,
> OBJ_CASE_INSENSITIVE,
> NULL,
> NULL );
>
> printf(“BEFORE NtOpenKey: press any key to continue…\n”);
> _getch();
>
> status = NtOpenKey(
> &keyHandle,
> GENERIC_READ | GENERIC_WRITE,
> &objAttr );
> if (!NT_SUCCESS(status))
> {
> keyHandle = NULL;
> printf(“ERROR: could NOT open registry key, error 0x%08x\n”,
> status);
> retVal = -4;
> __leave;
> }
>
> printf(“AFTER NtOpenKey / BEFORE NtSaveKey: press any key to
> continue…\n”);
> _getch();
>
> // save key to file
> status = NtSaveKey(
> keyHandle,
> fileHandle );
> if (!NT_SUCCESS(status))
> {
> printf(“ERROR: could NOT save key to file, error 0x%08x\n”,
> status);
> retVal = -5;
>__leave;
> }
>
> printf(“key successfully saved to file\n”);
>
> printf(“AFTER NtSaveKey: press any key to continue…\n”);
> _getch();
> …
>
> On request, I can send a full user-mode example :slight_smile:
>
> Any ideas?
>
> Sandor LUKACS
>

Thanks,

RegLoad / RegUnload are a different thing and have nothing to do with NtSaveKey / NtRestoreKey AFAIK. However, I think that it would be strongly desired to have callbacks for NtSaveKey / NtRestoreKey / NtReplaceKey also… maybe somebody from the MS filtering team working on Vista SP1 / Longhorn reads the forum :slight_smile:

You will need to develop a file system filter driver for this purpose
But what should exactly I really filter with a FS filter driver? any hints?

or otherwise resort to some weird heuristics which will provoke false positives
I don’t think that this would be a viable solution. However, if you can give a more precise hint I would receive it gratefully.

have a nice day,
Sandor LUKACS

One idea is to check for REG_OPTION_BACKUP_RESTORE in the create options.
This flag is necessary for the
RegSaveKey/RegSaveKeyEx/RegRegstoreKey/RegReplaceKey apis to succeed. These
flags will also bypass security checking so the query security approach may
not get your very far.

One idea is to check for the signature of the hive file which is often
‘regf’. But there are three different types of registry hive file formats.
If you also need to make distinction between different API calls it’s going
to be difficult.

There are several things you can do to observe parameters, sequences and
behavior but I am not sure if you can come up with a solution which is not a
gamble. These are just ideas, I have never done this, I always hooked the
SSDT which is much more straightforward. Unless they come up with something
well-though out APIs and cover it with a service pack for all existing OSes
the registry monitoring APIs remain crap. It’s part of a worrying MS trend
to produce crappy APIs tailored to one specific need and one specific OS
which never allow you to do what you want. The new object monitoring APIs
deserve the crown. Patchguard took away a lot of pleasure from my job.

/Daniel

wrote in message news:xxxxx@ntfsd…
> Thanks,
>
> RegLoad / RegUnload are a different thing and have nothing to do with
> NtSaveKey / NtRestoreKey AFAIK. However, I think that it would be strongly
> desired to have callbacks for NtSaveKey / NtRestoreKey / NtReplaceKey
> also… maybe somebody from the MS filtering team working on Vista SP1 /
> Longhorn reads the forum :slight_smile:
>
>> You will need to develop a file system filter driver for this purpose
> But what should exactly I really filter with a FS filter driver? any
> hints?
>
>> or otherwise resort to some weird heuristics which will provoke false
>> positives
> I don’t think that this would be a viable solution. However, if you can
> give a more precise hint I would receive it gratefully.
>
> have a nice day,
> Sandor LUKACS
>

Thanks,

There are several things you can do to observe parameters, sequences and behavior but I
am not sure if you can come up with a solution which is not a gamble.
I have actually tried to analyze quite a lot the issue, but we didn’t found a viable solution :expressionless:

I always hooked the SSDT which is much more straightforward
I have seen it in your system monitoring tool :wink: May I ask you, if you could successfully do the same on x64, or it is one of the reasons why you don’t offer (yet) support for Vista x64?

btw. I have sent a request to xxxxx@Microsoft.com and asked them to include callbacks in the Vista SP1 release… I’m curiously and hopefully waiting for an answer :slight_smile:

thank you,

Sandor LUKACS

No I admit my MultiMon tool has some problems but it takes a lot of work and
I’m so much involved in other things for the moment. Registrar Registry
Manager works well also on Vista x64 also but does not do SaveKey
monitoring.

What may possibly help you further also is ZwQuerySystemInformation with
SystemCallCountInformation class.

/Daniel

wrote in message news:xxxxx@ntfsd…
> Thanks,
>
>> There are several things you can do to observe parameters, sequences and
>> behavior but I
>> am not sure if you can come up with a solution which is not a gamble.
> I have actually tried to analyze quite a lot the issue, but we didn’t
> found a viable solution :expressionless:
>
>> I always hooked the SSDT which is much more straightforward
> I have seen it in your system monitoring tool :wink: May I ask you, if you
> could successfully do the same on x64, or it is one of the reasons why you
> don’t offer (yet) support for Vista x64?
>
> btw. I have sent a request to xxxxx@Microsoft.com and asked them to
> include callbacks in the Vista SP1 release… I’m curiously and hopefully
> waiting for an answer :slight_smile:
>
> thank you,
>
> Sandor LUKACS
>

>What may possibly help you further also is ZwQuerySystemInformation with

SystemCallCountInformation class.

AFAIK call counting works only on Checked build kernels… am I wrong about it?

And, if it works on release builds also, than I could *theoretically* check the call count of NtSaveKey to verify, if it has been called, but I don’t think that this is a solid / implementable way. I see two problems with it: 1) multiple parallel calls on a SMP machine (and not only)? 2) to be able to check that a call is to NtSaveKey I need to be *inside* that call ==> that means, I need some kind of hook on it…

Maybe the SystemCallCountInformation suggestion was with a different purpose :-? (like SSDT length, or other, much more esoteric stuff…)

thanks,

Sandor

I know for sure that SystemCallTimeInformation is normally not implemented,
not sure about call counting, you may be completely right that it’s not
working on release builds. In case you were just monitoring it could
possibly serve in combination with everything else as an extra verification
to see if the call really took place or not, it was just an idea. However
the save key APIs are heavy duty and surely lock the registry database if
not everything else so I am quite sure that these calls are serialized.

/Daniel

wrote in message news:xxxxx@ntfsd…
> >What may possibly help you further also is ZwQuerySystemInformation with
>>SystemCallCountInformation class.
>
> AFAIK call counting works only on Checked build kernels… am I wrong
> about it?
>
> And, if it works on release builds also, than I could theoretically
> check the call count of NtSaveKey to verify, if it has been called, but I
> don’t think that this is a solid / implementable way. I see two problems
> with it: 1) multiple parallel calls on a SMP machine (and not only)? 2) to
> be able to check that a call is to NtSaveKey I need to be inside that
> call ==> that means, I need some kind of hook on it…
>
> Maybe the SystemCallCountInformation suggestion was with a different
> purpose :-? (like SSDT length, or other, much more esoteric stuff…)
>
> thanks,
>
> Sandor
>

Talking about registry - can callbacks registered through CmRegisterCallback on XP filter all registry accesses done from a limited user account? I need it for a sandbox environment where processes run using a restricted token; my goal is to prevent any write access to the registry.

One important point in my and Daniel’s posts above is, that you can’t prevent / block all writes using only CmRegisterCallback callbacks, because you can’t filter all of them. This is valid NOT only for XP, but for 2003, Vista also.

Sandor LUKACS

Even if the user has a token created using CreateRestrictedToken with the most restrictive options available?

AFAIK, I don’t think that some registry operations would bypass the CmRegisterCallback callbacks only because you have a user with any kind of token restriction.

(If I misunderstood your question, please elaborate it or send some sample with CreateRestrictedToken stuff to can see exactly what are you referring to.)

Sandor

What I meant was:
The only ways I know to modify registry without CmRegisterCallback knowing it are RegReplaceKey / RegRestoreKey / RegLoadKey.
All of them need a SeRestorePrivilege enabled. If there are no other methods that would allow the user to modify the registry, then CmRegisterCallback will suffice, since the user has all privileges disabled.

> If there are no other methods that would allow the user to modify the registry, then

CmRegisterCallback will suffice, since the user has all privileges disabled.
I can only say, that AFAIK there is no other know, officially documented etc. mode to modify the registry, so for the vast majority of the applications your approach should be sufficient. However, given that you want sandboxing, I’m not that sure about, because I assume, you would like to be prepared also for let’s say “exceptional” or “not well behaving” applications.

Anyway, my advice is, that you shall write the stuff using CmRegisterCallback and restricted priviledges for the user. That would be a reasonable startup.

Sandor

Yes, there will definietely be “exceptional” code executing. Still, most of the known misbehaving functions require some level of privilege. The bottleneck here is GDI which - as we know - has some security problems.
I will use CmRegisterCallback on XP+ and NtRegCreateKey / NtRegOpenKey hook on Win2k.

>I will use CmRegisterCallback on XP+ and NtRegCreateKey / NtRegOpenKey hook on Win2k.
Be carefully, because on XP, inclusive SP2, only on x86, there are known limitations of CmRegisterCallback stuff (do a search on the forum to find them, for ex. AFAIK, you can’t get the full registry key name on Create/Open). The CmRegisterCallback starts to be usable on XP x64 and Server 2003 x86/x64. Because of this, I would recommend to take into consideration the hooks also for XP on x86 platforms, not only for 2K.

good luck,

Sandor