Three short stories about the Windows registry

Good afternoon, dear readers.

The registry is one of the most visible and significant Windows systems. There is hardly a person who has not heard of him. Being engaged in programming under Windows for about 20 years, I thought I knew everything about him. But from time to time, something new appears that shows me how wrong I was. Therefore, today I want to tell you about the unusual ways of working with the registry, which I met while researching rootkits, and which surprised me.


The first story. Names and registry keys


We all know that in Windows there are some rules for naming objects, whether they are files, directories, or registry keys. File names cannot contain the “\” character. Names cannot be empty. Names have some restrictions on length, etc.

Unwittingly, we extend these restrictions to all Windows systems and comply with them when working with the registry. And here lies our mistake. In the registry of restrictions on creating names, surprisingly little. For example, in the name of values ​​you can use the symbol “\”


Surprised? Not? Then what do you say if I show you that you can use the “\ 0” symbol in the value name? Yes, exactly null character. The one that is traditionally used to indicate the end of a line.

For this we need the NtSetValueKey function, exported from ntdll.dll

HKEY hKey = 0; RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey); UNICODE_STRING uName; uName.Buffer = L"Test\0Zero"; uName.MaxLen = uName.Length = 9 * sizeof(wchar_t); NTSTATUS status = 0; status = NtSetValueKey( hKey, &uName, 0, REG_SZ, (void*)lpData, DataSize); RegCloseKey(hKey); 

To perform the NtSetValueKey function, you will need administrator rights. As a result, you will have a value in the registry named Test \ 0Zero.

Some Microsoft developers will be surprised too, since the standard registry editor cannot display such an unusual registry value.


Second story


The second story, which I will tell you today, occurred in 2013.

At first, a small digression. In Kaspersky Lab, I am a member of a team that, among other things, creates a Kaspersky Rescue Disk. To cure Windows from under Linux, we need to independently parse the registry files. And to verify the correct operation of this mechanism, we use a variety of tests. Among them there is one fairly simple:


And then one day we updated Windows on the test bench to version 8.1, and the test stopped deleting the test values. How so, I was surprised. I copied the file with the registry hive to my work computer - no values! My first thought: you need to add modified keys to the Flush test. Added call to RegFlushKey, restarted test - no values!

Is RegFlushKey not working, I wondered. But, as it turned out, I was only partially correct.

The trick turned out to be that in Windows 8.1, Microsoft changed the mechanism for saving changes to the registry. Previously, all registry changes were accumulated in memory, and then, when the key was closed, when RegFlushKey was executed or after some time, the system saved the changes to the registry hive file. In Windows 8.1, the changes instead of the registry hive file are saved to the same files with the extensions .LOG, .LOG1 and .LOG2, and my code ignored those files at that time.

Changes accumulate in these files for about an hour. And only after that Windows starts the task of integrating changes into the main file. This task is called Reconciliation, and it starts either every 40 minutes or when Windows is shutting down. Calling the RegFlushKey function to launch the Reconciliation task does not result. To force the change integration task to run, you need to call ZwSetSystemInformation with the undocumented SystemRegistryReconciliationInformation argument.

 ZwSetSystemInformation( 0x9b, //SystemRegistryReconciliationInformation NULL, 0); 

To perform the ZwSetSystemInformation function, you will need administrator rights. And the architecture of the executable file must match the system architecture. Calling this function from a 32-bit program in 64-bit Windows will fail.

Third story


Some time ago we discovered a rootkit, which registered the launch of its driver in the registry. Our products deleted the corresponding registry keys, but after a reboot, the keys appeared in their places. It seems that he puts his callback functions on registry changes and recovers his keys after our changes, I thought. But it turned out not. More precisely - yes. The rootkit set the callback functions, but they had nothing to do with the key recovery task. Everything was made simpler and more elegant.

The rootkit driver, when launched, renamed the SYSTEM hive file of the registry in HARDWARE. I created my SYSTEM file and periodically saved the HKLM / System branch to it using the RegSaveKey function. While saving, he restored his keys. When Windows rebooted, the system loaded the SYSTEM file and started the rootkit driver. Handsomely? Handsomely.

Wanted


PS We are here looking for a developer-researcher into a team that cuts the anti-spam engine, and also needs a testing engineer .

Source: https://habr.com/ru/post/415699/


All Articles