Registro - criando entradas escondidas (hide) no registro

Top  Previous  Next

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 : Unit1 

* 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''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''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''create our hidden value'); 

end; 

 

// 

// Let the user try and open our key! 

// 

  ShowMessage('Try and open the key "HKLM\SOFTWARE\Systems Internals\Can''' + 

      '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, 

  uRegHeaders in 'uRegHeaders.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''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''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''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.