tags:

views:

369

answers:

2

I've read about the possibility of hiding a registry value on the registry using a technique documented by Sysinternals that lets you put a null character in a registry key using the native API (eg, "hello\0"): http://technet.microsoft.com/en-us/sysinternals/bb897446.aspx (scroll to the "Hidden Registry Keys" part).

They also have a tool to find and delete these values: http://technet.microsoft.com/en-us/sysinternals/bb897448.aspx

Anyone knows how to create/read/delete a hidden registry value in Delphi using this technique?

+10  A: 

The sysinternals link you gave describes the theory pretty well:

"In the Win32 API strings are interpreted as NULL-terminated ANSI (8-bit) or wide character (16-bit) strings. In the Native API names are counted Unicode (16-bit) strings. While this distinction is usually not important, it leaves open an interesting situation: there is a class of names that can be referenced using the Native API, but that cannot be described using the Win32 API."

So, with win32's RegCreateKeyW(), if you attempt to give it a key name like "Foo\0Bar", it will only use "Foo\0", and not see the rest.

Using the native API equivalent, like NtCreateKey, you have to supply both string buffer and length (as a UNICODE_STRING member of the OBJECT_ATTRIBUTES parameter). So it will happily use, and create a key named "Foo\0Bar".

Regedit, or any other program using the win32 api, won't be able to open this key. When they enumerate the parent, they'll only get back the null-terminated version of the name, "Foo\0", which doesn't really exist. So if you click on "Foo" in regedit, it will throw you an error, since its RegOpenKey("Foo") call failed.

To find, open, and delete these, you'll need to go to the native api.

First step will be to translate the function declarations, and the supporting parameter types, to delphi, and dynamically load the functions from ntdll.dll.

Here are some conversions to start playing with:

type
  NTSTATUS = Longint;
  PLARGE_INTEGER = ^LARGE_INTEGER;
  USHORT   = Word;

  UNICODE_STRING = record
    Length: WORD;
    MaximumLength: WORD;
    Buffer: PWideChar;
  end;
  PUNICODE_STRING = ^UNICODE_STRING;

  OBJECT_ATTRIBUTES = record
    Length: ULONG;
    RootDirectory: THandle;
    ObjectName: PUNICODE_STRING;
    Attributes: ULONG;
    SecurityDescriptor: Pointer;       
    SecurityQualityOfService: Pointer; 
  end;
  POBJECT_ATTRIBUTES = ^OBJECT_ATTRIBUTES;

  // function prototypes
  TNtCreateKey = function(KeyHandle : PHANDLE;
                          DesiredAccess: ACCESS_MASK;
                          ObjectAttributes: POBJECT_ATTRIBUTES;
                          TitleIndex: ULONG;
                          ClassType: PUNICODE_STRING;
                          CreateOptions: ULONG;
                          Disposition: PULONG
                         ): NTSTATUS; stdcall;

  TNtDeleteKey = function(KeyHandle: THANDLE): NTSTATUS; stdcall;

There's also an old article over at the codeproject which has a lot more sample code (C++), and explanation to get you the rest of the way.

otherchirps
A: 

I would like to point out the fact that this only hides the registry item from regedit (and tools like it). If you are relying on this to "protect" your software from piracy, your still open to programs such as RegMon or programmatic registry access using a tool which was developed using the native api.

skamradt