Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
500 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi







Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (1)


Creating "Hidden" Registry ValuesFormat this article printer-friendly!Bookmark function is only available for registered users!
Using the undocumented MS Native API
Product:
Delphi 5.x (or higher)
Category:
Win API
Skill Level:
Scoring:
Last Update:
04/25/2005
Search Keys:
delphi delphi3000 article borland vcl code-snippet Native API Hidden Registry Values
Times Scored:
5
Visits:
7482
Uploader: Daniel Wischnewski
Company: Delphi-PRAXiS
Reference: sysinternals freeware
 
Question/Problem/Abstract:
This article is based upon the information published in a source code sample at Sysinternals Freeware. This code will show you how to access and use the MS Native API functions.
Answer:



Today, I came across the Sysinternals Freeware website and stopped cold reading the articles on what all you can do with a Windows NT/2K system. A lot of interesting aspects were told there.

Evaluating one of the code samples, provided in C/C++, I decided to try to translate it into Delphi - you all probably understand why ;)

This article is based upon the sample provided by the following link: Hidden Registry Keys?.

Accessing the Windows Registry through the TRegistry object, or using the documented WinAPI routines, you are restricted in the choice of characters used for the Registry key names und value names.

Direct quote from the Website: 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, I started playing around with the code some and want to provide you with the solution I found for Delphi. I would never have made (or tried) it without this great site.

There are two units to this project. The unit uRegHide.pas defines the type structures and imports the Native API routines, the project file HiddenRegistry.dpr does the actual work. Go on and try it :)

////////////////////////////////////////////////////////////
/////////////////////// uRegHide.pas ///////////////////////
////////////////////////////////////////////////////////////

{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Unit Name : uRegHide
* Autor     : Daniel Wischnewski
* Copyright : Copyright © 2001-2003 by gate(n)etwork. All Rights Reserved.
* Urheber   : Daniel Wischnewski
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}

// THIS CODE IS DERIVED FROM "Reghide.c" PUBLISHED BY SYSTEM INTERNALS

//
// Reghide.c
//
// by Mark Russinovich
// http://www.sysinternals.com
//
// This program demonstrates how the Native API can be used to
// create object names that are inaccessible from the Win32 API. While
// there are many different ways to do this, the method used here it to
// include a terminating NULL that is explicitly made part of the key name.
// There is no way to describe this with the Win32 API, which treats a NULL
// as the end of the name string and will therefore chop it. Thus, Regedit
// and Regedt32 won't be able to access this key, though it will be visible.
//

unit uRegHide;

interface

uses
  
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  
TForm1 = class(TForm)
    btnDemo: TButton;
    procedure btnDemoClick(Sender: TObject);
  private
    
{ Private declarations }
  
public
    
{ Public declarations }
  
end;

var
  
Form1: TForm1;

implementation

// DEFINE MISSING CONSTANTS

const
  
ntdll = 'ntdll.dll';
  OBJ_CASE_INSENSITIVE = $00000040;

// DEFINE MISSING TYPE DECLARATIONS

type
  
USHORT = WORD;
  NTSTATUS = ULONG;
  PVOID = Pointer;

// TRANSLATE MACRO

function NT_SUCCESS(Status: Integer): WordBool;
begin
  
Result := Status >= 0;
end;

// DEFINE Native API UNICODE STRING

type
  
TUnicodeString = packed record
    
Length: USHORT;
    MaximumLength: USHORT;
    Buffer: PWideChar;
  end;
  UNICODE_STRING = TUnicodeString;
  PUNICODE_STRING = ^UNICODE_STRING;

// DEFINE Native API OBJECT ATTRIBUTES

  
TObjectAttributes = packed record
    
Length: ULONG;
    RootDirectory: THandle;
    ObjectName: PUNICODE_STRING;
    Attributes: ULONG;
    SecurityDescriptor: PVOID;        // Points to type SECURITY_DESCRIPTOR
    
SecurityQualityOfService: PVOID;  // Points to type SECURITY_QUALITY_OF_SERVICE
  
end;
  OBJECT_ATTRIBUTES = TObjectAttributes;
  POBJECT_ATTRIBUTES = ^OBJECT_ATTRIBUTES;

// TRANSLATE MACRO

procedure InitializeObjectAttributes(var p: TObjectAttributes; n:
    PUNICODE_STRING; a: ULONG; r: THandle; s: PVOID);
begin
  
p.Length := SizeOf(OBJECT_ATTRIBUTES);
  p.RootDirectory := r;
  p.Attributes := a;
  p.ObjectName := n;
  p.SecurityDescriptor := s;
  p.SecurityQualityOfService := nil;
end;

// IMPORT NTDLL FUNCTIONS

function NtCreateKey(var KeyHandle: THandle; DesiredAccess: ULONG; var
    
ObjectAttributes: OBJECT_ATTRIBUTES; TitleIndex: ULONG; Class_:
    PUNICODE_STRING; CreateOptions: ULONG; var Disposition: ULONG): NTSTATUS;
    stdcall; external ntdll name 'NtCreateKey';

function NtSetValueKey(KeyHandle: THandle; ValueName: PUNICODE_STRING;
    TitleIndex: ULONG; Type_: ULONG; Data: PVOID; DataSize: ULONG): NTSTATUS;
    stdcall; external ntdll name 'NtSetValueKey';

function NtDeleteKey(KeyHandle: THandle): NTSTATUS; stdcall; external ntdll
    name 'NtDeleteKey';

{$R *.dfm}

// DEFINE OUR REGISTY STRINGS

const
  
KeyNameBuffer: AnsiString = '\Registry\Machine\SOFTWARE';
  NewKeyNameBuffer: AnsiString = 'Systems Internals';
  HiddenKeyNameBuffer: AnsiString = 'Can''t touch me!'#0;
  HiddenValueNameBuffer: AnsiString = 'Hidden Value';

// DEMONSTRATE

procedure TForm1.btnDemoClick(Sender: TObject);
var
KeyName, ValueName: UNICODE_STRING;
SoftwareKeyHandle, SysKeyHandle, HiddenKeyHandle: THandle;
Status: ULONG;
ObjectAttributes: OBJECT_ATTRIBUTES;
Disposition: ULONG;
  Buffer: array of WideChar;
begin
  
ShowMessage('Reghide'#13#10 + 'Creates a Registry key that cannot be ' +
      'opened with Regedit/Regedt32'#13#10#13#10'original by Mark Russinovich' +
      #13#10'Delphi-Version by Daniel Wischnewski'#13#10'http://www.' +
      'sysinternals.com'#13#10'http://www.gatenetwork.com');

//
// Open the Software key
//
  
SetLength(Buffer, Length(KeyNameBuffer));
  MultiByteToWideChar(CP_UTF8, 0, @KeyNameBuffer[1], Length(KeyNameBuffer),
      PWideChar(Buffer), Length(Buffer));
  KeyName.Buffer := @Buffer[0];
KeyName.Length := Length(KeyNameBuffer) * SizeOf(WideChar);
InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
      0, nil);
Status := NtCreateKey(SoftwareKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
      nil, REG_OPTION_NON_VOLATILE, Disposition);
if not NT_SUCCESS(Status) then
     raise
Exception.Create('Error: Couldn''t open HKLM\Software');

//
// Create the "Systems Internals" key
//
  
SetLength(Buffer, Length(NewKeyNameBuffer));
  MultiByteToWideChar(CP_THREAD_ACP, 0, @NewKeyNameBuffer[1], Length(
      NewKeyNameBuffer), PWideChar(Buffer), Length(Buffer));
  KeyName.Buffer := @Buffer[0];
KeyName.Length := Length(NewKeyNameBuffer) * SizeOf(WideChar);
InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
    SoftwareKeyHandle, nil);
Status := NtCreateKey(SysKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
      nil, REG_OPTION_NON_VOLATILE, Disposition);
if not NT_SUCCESS(Status)  then
    raise
Exception.Create(
        'Error: Couldn''t create HKLM\Software\Systems Internals');

//
// Create the Hidden key
//
  
SetLength(Buffer, Length(HiddenKeyNameBuffer));
  MultiByteToWideChar(CP_UTF8, 0, @HiddenKeyNameBuffer[1], Length(
      HiddenKeyNameBuffer), PWideChar(Buffer), Length(Buffer));
  KeyName.Buffer := @Buffer[0];
KeyName.Length := Length(HiddenKeyNameBuffer) * SizeOf(WideChar);
InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
      SysKeyHandle, nil);
Status := NtCreateKey(HiddenKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
      nil, REG_OPTION_NON_VOLATILE, Disposition);
if not NT_SUCCESS(Status) then
    raise
Exception.Create(
        'Error: Couldn''t create HKLM\Software\Systems Internals\RegHide');

//
// Create the hidden value
//
  
SetLength(Buffer, Length(HiddenValueNameBuffer));
  MultiByteToWideChar(CP_UTF8, 0, @HiddenValueNameBuffer[1], Length(
      HiddenValueNameBuffer), PWideChar(Buffer), Length(Buffer));
  ValueName.Buffer := @Buffer[0];
ValueName.Length := Length(HiddenValueNameBuffer) * SizeOf(WideChar);
Status := NtSetValueKey(HiddenKeyHandle, @ValueName, 0, REG_SZ,
      @HiddenValueNameBuffer[1], Length(HiddenValueNameBuffer) * SizeOf(WideChar));
if not NT_SUCCESS(Status) then
  begin
NtDeleteKey(HiddenKeyHandle);
    raise Exception.Create('Error: Couldn''t create our hidden value');
end;

//
// Let the user try and open our key!
//
  
ShowMessage('Try and open the key "HKLM\SOFTWARE\Systems Internals\Can''t ' +
      'touch me!"'#13#10'with Regedit or Regedt32 (or any other Registry ' +
      'editor). There is a value'#13#10'in the key called "Hidden Value".' +
      #13#10#13#10'When done trying, press any key to have the key deleted ' +
      'and exit.');

//
// Cleanup the key
//
NtDeleteKey(HiddenKeyHandle);
end;

end.

////////////////////////////////////////////////////////////
//////////////////// HiddenRegistry.dpr ////////////////////
////////////////////////////////////////////////////////////

{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Unit Name : Not available
* Autor     : Daniel Wischnewski
* Copyright : Copyright © 2001-2003 by gate(n)etwork. All Rights Reserved.
* Urheber   : Daniel Wischnewski
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}

program HiddenRegistry;

uses
  
Windows,
  uRegHide in 'uRegHide.pas';

// DEFINE OUR REGISTY STRINGS
const
  
KeyNameBuffer: AnsiString = '\Registry\Machine\SOFTWARE';
  NewKeyNameBuffer: AnsiString = 'Systems Internals';
  HiddenKeyNameBuffer: AnsiString = 'Can''t touch me!'#0;
  HiddenValueNameBuffer: AnsiString = 'Hidden Value';

var
KeyName, ValueName: UNICODE_STRING;
SoftwareKeyHandle, SysKeyHandle, HiddenKeyHandle: THandle;
Status: ULONG;
ObjectAttributes: OBJECT_ATTRIBUTES;
Disposition: ULONG;
  Buffer: array of WideChar;

begin
  
MessageBox(0, 'Reghide'#13#10'Creates a Registry key that cannot be ' +
      'opened with Regedit/Regedt32'#13#10#13#10'original by Mark Russinovich' +
      #13#10'Delphi-Version by Daniel Wischnewski'#13#10'http://www.' +
      'sysinternals.com'#13#10'http://www.gatenetwork.com', 'Native API Demo',
      MB_OK);

//
// Open the Software key
//
  
SetLength(Buffer, Length(KeyNameBuffer));
  MultiByteToWideChar(CP_UTF8, 0, @KeyNameBuffer[1], Length(KeyNameBuffer),
      PWideChar(Buffer), Length(Buffer));
  KeyName.Buffer := @Buffer[0];
KeyName.Length := Length(KeyNameBuffer) * SizeOf(WideChar);
InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
      0, nil);
Status := NtCreateKey(SoftwareKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
      nil, REG_OPTION_NON_VOLATILE, Disposition);
if not NT_SUCCESS(Status) then
  begin
  
MessageBox(0, 'Error: Couldn''t open HKLM\Software', 'Native API Demo',
       MB_OK);
   Exit;
  end;

//
// Create the "Systems Internals" key
//
  
SetLength(Buffer, Length(NewKeyNameBuffer));
  MultiByteToWideChar(CP_THREAD_ACP, 0, @NewKeyNameBuffer[1], Length(
      NewKeyNameBuffer), PWideChar(Buffer), Length(Buffer));
  KeyName.Buffer := @Buffer[0];
KeyName.Length := Length(NewKeyNameBuffer) * SizeOf(WideChar);
InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
    SoftwareKeyHandle, nil);
Status := NtCreateKey(SysKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
      nil, REG_OPTION_NON_VOLATILE, Disposition);
if not NT_SUCCESS(Status)  then
  begin
    
MessageBox(0, 'Error: Couldn''t create HKLM\Software\Systems Internals',
        'Native API Demo', MB_OK);
    Exit;
  end;

//
// Create the Hidden key
//
  
SetLength(Buffer, Length(HiddenKeyNameBuffer));
  MultiByteToWideChar(CP_UTF8, 0, @HiddenKeyNameBuffer[1], Length(
      HiddenKeyNameBuffer), PWideChar(Buffer), Length(Buffer));
  KeyName.Buffer := @Buffer[0];
KeyName.Length := Length(HiddenKeyNameBuffer) * SizeOf(WideChar);
InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
      SysKeyHandle, nil);
Status := NtCreateKey(HiddenKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
      nil, REG_OPTION_NON_VOLATILE, Disposition);
if not NT_SUCCESS(Status) then
  begin
    
MessageBox(0, 'Error: Couldn''t create HKLM\Software\Systems Internals\' +
        'RegHide', 'Native API Demo', MB_OK);
    Exit;
  end;

//
// Create the hidden value
//
  
SetLength(Buffer, Length(HiddenValueNameBuffer));
  MultiByteToWideChar(CP_UTF8, 0, @HiddenValueNameBuffer[1], Length(
      HiddenValueNameBuffer), PWideChar(Buffer), Length(Buffer));
  ValueName.Buffer := @Buffer[0];
ValueName.Length := Length(HiddenValueNameBuffer) * SizeOf(WideChar);
Status := NtSetValueKey(HiddenKeyHandle, @ValueName, 0, REG_SZ,
      @HiddenValueNameBuffer[1], Length(HiddenValueNameBuffer) * SizeOf(WideChar));
if not NT_SUCCESS(Status) then
  begin
    
MessageBox(0, 'Error: Couldn''t create our hidden value', 'Native API Demo',
        MB_OK);
NtDeleteKey(HiddenKeyHandle);
    Exit;
end;

//
// Let the user try and open our key!
//
  
MessageBox(0, 'Try and open the key "HKLM\SOFTWARE\Systems Internals\' +
      'Can''t touch me!"'#13#10'with Regedit or Regedt32 (or any other ' +
      'Registry editor). There is a value'#13#10'in the key called "Hidden ' +
      'Value".'#13#10#13#10'When done trying, press any key to have the key ' +
      'deleted and exit.', 'Native API Demo', MB_OK);

//
// Cleanup the key
//
NtDeleteKey(HiddenKeyHandle);
end.


Have fun,
Daniel Wischnewski, Delphi-PRAXiS





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
Be careful
    Tommy Andersen (Feb 6 2003 1:07PM)

I converted the same source to Delphi a couple of years ago to be able to hide the trial period etc. of my applications etc.

Using this method you must be very careful where you put each "hidden" key. In the first versions I placed it some place under HKLM (don't remember where anymore), and it made a users network control panel applet act strange.

After that I've tried several solutions, but in small steps I've come to the point that I don't use this technique anymore.

This solutions doesn't work on some Windows os's too.


Best Regards
Tommy Andersen
EasyWare.org

Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
S. Kucherov
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)