Author: Daniel Wischnewski
This article is based upon the information published in a source code sample at
Sysinternals Freeware http://www.sysinternals.com/ntw2k/info/tips.shtml. This code
will show you how to access and use the MS Native API functions.
Answer:
Today, I came across the Sysinternals Freewarehttp://www.sysinternals.com/ 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 Keyshttp://www.sysinternals.com/ntw2k/info/tips.shtml#RegistryHidden?.
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 :)
1
2 ////////////////////////////////////////////////////////////
3 /////////////////////// uRegHide.pas ///////////////////////
4 ////////////////////////////////////////////////////////////
5
6 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7 *
8 * Unit Name : Unit1
9 * Autor : Daniel Wischnewski
10 * Copyright : Copyright © 2001-2003 by gate(n)etwork. All Rights Reserved.
11 * Urheber : Daniel Wischnewski
12 *
13 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
14
15 // THIS CODE IS DERIVED FROM "Reghide.c" PUBLISHED BY SYSTEM INTERNALS
16
17 //
18 // Reghide.c
19 //
20 // by Mark Russinovich
21 // http://www.sysinternals.com
22 //
23 // This program demonstrates how the Native API can be used to
24 // create object names that are inaccessible from the Win32 API. While
25 // there are many different ways to do this, the method used here it to
26 // include a terminating NULL that is explicitly made part of the key name.
27 // There is no way to describe this with the Win32 API, which treats a NULL
28 // as the end of the name string and will therefore chop it. Thus, Regedit
29 // and Regedt32 won't be able to access this key, though it will be visible.
30 //
31
32 unit uRegHide;
33
34 interface
35
36 uses
37 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
38 Dialogs, StdCtrls;
39
40 type
41 TForm1 = class(TForm)
42 btnDemo: TButton;
43 procedure btnDemoClick(Sender: TObject);
44 private
45 { Private declarations }
46 public
47 { Public declarations }
48 end;
49
50 var
51 Form1: TForm1;
52
53 implementation
54
55 // DEFINE MISSING CONSTANTS
56
57 const
58 ntdll = 'ntdll.dll';
59 OBJ_CASE_INSENSITIVE = $00000040;
60
61 // DEFINE MISSING TYPE DECLARATIONS
62
63 type
64 USHORT = WORD;
65 NTSTATUS = ULONG;
66 PVOID = Pointer;
67
68 // TRANSLATE MACRO
69
70 function NT_SUCCESS(Status: Integer): WordBool;
71 begin
72 Result := Status >= 0;
73 end;
74
75 // DEFINE Native API UNICODE STRING
76
77 type
78 TUnicodeString = packed record
79 Length: USHORT;
80 MaximumLength: USHORT;
81 Buffer: PWideChar;
82 end;
83 UNICODE_STRING = TUnicodeString;
84 PUNICODE_STRING = ^UNICODE_STRING;
85
86 // DEFINE Native API OBJECT ATTRIBUTES
87
88 TObjectAttributes = packed record
89 Length: ULONG;
90 RootDirectory: THandle;
91 ObjectName: PUNICODE_STRING;
92 Attributes: ULONG;
93 SecurityDescriptor: PVOID; // Points to type SECURITY_DESCRIPTOR
94 SecurityQualityOfService: PVOID; // Points to type SECURITY_QUALITY_OF_SERVICE
95 end;
96 OBJECT_ATTRIBUTES = TObjectAttributes;
97 POBJECT_ATTRIBUTES = ^OBJECT_ATTRIBUTES;
98
99 // TRANSLATE MACRO
100
101 procedure InitializeObjectAttributes(var p: TObjectAttributes; n:
102 PUNICODE_STRING; a: ULONG; r: THandle; s: PVOID);
103 begin
104 p.Length := SizeOf(OBJECT_ATTRIBUTES);
105 p.RootDirectory := r;
106 p.Attributes := a;
107 p.ObjectName := n;
108 p.SecurityDescriptor := s;
109 p.SecurityQualityOfService := nil;
110 end;
111
112 // IMPORT NTDLL FUNCTIONS
113
114 function NtCreateKey(var KeyHandle: THandle; DesiredAccess: ULONG; var
115 ObjectAttributes: OBJECT_ATTRIBUTES; TitleIndex: ULONG; Class_:
116 PUNICODE_STRING; CreateOptions: ULONG; var Disposition: ULONG): NTSTATUS;
117 stdcall; external ntdll name 'NtCreateKey';
118
119 function NtSetValueKey(KeyHandle: THandle; ValueName: PUNICODE_STRING;
120 TitleIndex: ULONG; Type_: ULONG; Data: PVOID; DataSize: ULONG): NTSTATUS;
121 stdcall; external ntdll name 'NtSetValueKey';
122
123 function NtDeleteKey(KeyHandle: THandle): NTSTATUS; stdcall; external ntdll
124 name 'NtDeleteKey';
125
126 {$R *.dfm}
127
128 // DEFINE OUR REGISTY STRINGS
129
130 const
131 KeyNameBuffer: AnsiString = '\Registry\Machine\SOFTWARE';
132 NewKeyNameBuffer: AnsiString = 'Systems Internals';
133 HiddenKeyNameBuffer: AnsiString = 'Can''t touch me!'#0;
134 HiddenValueNameBuffer: AnsiString = 'Hidden Value';
135
136 // DEMONSTRATE
137
138 procedure TForm1.btnDemoClick(Sender: TObject);
139 var
140 KeyName, ValueName: UNICODE_STRING;
141 SoftwareKeyHandle, SysKeyHandle, HiddenKeyHandle: THandle;
142 Status: ULONG;
143 ObjectAttributes: OBJECT_ATTRIBUTES;
144 Disposition: ULONG;
145 Buffer: array of WideChar;
146 begin
147 ShowMessage('Reghide'#13#10 + 'Creates a Registry key that cannot be ' +
148 'opened with Regedit/Regedt32'#13#10#13#10'original by Mark Russinovich' +
149 #13#10'Delphi-Version by Daniel Wischnewski'#13#10'http://www.' +
150 'sysinternals.com'#13#10'http://www.gatenetwork.com');
151
152 //
153 // Open the Software key
154 //
155 SetLength(Buffer, Length(KeyNameBuffer));
156 MultiByteToWideChar(CP_UTF8, 0, @KeyNameBuffer[1], Length(KeyNameBuffer),
157 PWideChar(Buffer), Length(Buffer));
158 KeyName.Buffer := @Buffer[0];
159 KeyName.Length := Length(KeyNameBuffer) * SizeOf(WideChar);
160 InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
161 0, nil);
162 Status := NtCreateKey(SoftwareKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
163 nil, REG_OPTION_NON_VOLATILE, Disposition);
164 if not NT_SUCCESS(Status) then
165 raise Exception.Create('Error: Couldn''t open HKLM\Software');
166
167 //
168 // Create the "Systems Internals" key
169 //
170 SetLength(Buffer, Length(NewKeyNameBuffer));
171 MultiByteToWideChar(CP_THREAD_ACP, 0, @NewKeyNameBuffer[1], Length(
172 NewKeyNameBuffer), PWideChar(Buffer), Length(Buffer));
173 KeyName.Buffer := @Buffer[0];
174 KeyName.Length := Length(NewKeyNameBuffer) * SizeOf(WideChar);
175 InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
176 SoftwareKeyHandle, nil);
177 Status := NtCreateKey(SysKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
178 nil, REG_OPTION_NON_VOLATILE, Disposition);
179 if not NT_SUCCESS(Status) then
180 raise Exception.Create(
181 'Error: Couldn''t create HKLM\Software\Systems Internals');
182
183 //
184 // Create the Hidden key
185 //
186 SetLength(Buffer, Length(HiddenKeyNameBuffer));
187 MultiByteToWideChar(CP_UTF8, 0, @HiddenKeyNameBuffer[1], Length(
188 HiddenKeyNameBuffer), PWideChar(Buffer), Length(Buffer));
189 KeyName.Buffer := @Buffer[0];
190 KeyName.Length := Length(HiddenKeyNameBuffer) * SizeOf(WideChar);
191 InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
192 SysKeyHandle, nil);
193 Status := NtCreateKey(HiddenKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
194 nil, REG_OPTION_NON_VOLATILE, Disposition);
195 if not NT_SUCCESS(Status) then
196 raise Exception.Create(
197 'Error: Couldn''t create HKLM\Software\Systems Internals\RegHide');
198
199 //
200 // Create the hidden value
201 //
202 SetLength(Buffer, Length(HiddenValueNameBuffer));
203 MultiByteToWideChar(CP_UTF8, 0, @HiddenValueNameBuffer[1], Length(
204 HiddenValueNameBuffer), PWideChar(Buffer), Length(Buffer));
205 ValueName.Buffer := @Buffer[0];
206 ValueName.Length := Length(HiddenValueNameBuffer) * SizeOf(WideChar);
207 Status := NtSetValueKey(HiddenKeyHandle, @ValueName, 0, REG_SZ,
208 @HiddenValueNameBuffer[1], Length(HiddenValueNameBuffer) * SizeOf(WideChar));
209 if not NT_SUCCESS(Status) then
210 begin
211 NtDeleteKey(HiddenKeyHandle);
212 raise Exception.Create('Error: Couldn''t create our hidden value');
213 end;
214
215 //
216 // Let the user try and open our key!
217 //
218 ShowMessage('Try and open the key "HKLM\SOFTWARE\Systems Internals\Can''t ' +
219 'touch me!"'#13#10'with Regedit or Regedt32 (or any other Registry ' +
220 'editor). There is a value'#13#10'in the key called "Hidden Value".' +
221 #13#10#13#10'When done trying, press any key to have the key deleted ' +
222 'and exit.');
223
224 //
225 // Cleanup the key
226 //
227 NtDeleteKey(HiddenKeyHandle);
228 end;
229
230 end.
231
232 ////////////////////////////////////////////////////////////
233 //////////////////// HiddenRegistry.dpr ////////////////////
234 ////////////////////////////////////////////////////////////
235
236 {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
237 *
238 * Unit Name : Not available
239 * Autor : Daniel Wischnewski
240 * Copyright : Copyright © 2001-2003 by gate(n)etwork. All Rights Reserved.
241 * Urheber : Daniel Wischnewski
242 *
243 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
244
245 program HiddenRegistry;
246
247 uses
248 Windows,
249 uRegHeaders in 'uRegHeaders.pas';
250
251 // DEFINE OUR REGISTY STRINGS
252 const
253 KeyNameBuffer: AnsiString = '\Registry\Machine\SOFTWARE';
254 NewKeyNameBuffer: AnsiString = 'Systems Internals';
255 HiddenKeyNameBuffer: AnsiString = 'Can''t touch me!'#0;
256 HiddenValueNameBuffer: AnsiString = 'Hidden Value';
257
258 var
259 KeyName, ValueName: UNICODE_STRING;
260 SoftwareKeyHandle, SysKeyHandle, HiddenKeyHandle: THandle;
261 Status: ULONG;
262 ObjectAttributes: OBJECT_ATTRIBUTES;
263 Disposition: ULONG;
264 Buffer: array of WideChar;
265
266 begin
267 MessageBox(0, 'Reghide'#13#10'Creates a Registry key that cannot be ' +
268 'opened with Regedit/Regedt32'#13#10#13#10'original by Mark Russinovich' +
269 #13#10'Delphi-Version by Daniel Wischnewski'#13#10'http://www.' +
270 'sysinternals.com'#13#10'http://www.gatenetwork.com', 'Native API Demo',
271 MB_OK);
272
273 //
274 // Open the Software key
275 //
276 SetLength(Buffer, Length(KeyNameBuffer));
277 MultiByteToWideChar(CP_UTF8, 0, @KeyNameBuffer[1], Length(KeyNameBuffer),
278 PWideChar(Buffer), Length(Buffer));
279 KeyName.Buffer := @Buffer[0];
280 KeyName.Length := Length(KeyNameBuffer) * SizeOf(WideChar);
281 InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
282 0, nil);
283 Status := NtCreateKey(SoftwareKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
284 nil, REG_OPTION_NON_VOLATILE, Disposition);
285 if not NT_SUCCESS(Status) then
286 begin
287 MessageBox(0, 'Error: Couldn''t open HKLM\Software', 'Native API Demo',
288 MB_OK);
289 Exit;
290 end;
291
292 //
293 // Create the "Systems Internals" key
294 //
295 SetLength(Buffer, Length(NewKeyNameBuffer));
296 MultiByteToWideChar(CP_THREAD_ACP, 0, @NewKeyNameBuffer[1], Length(
297 NewKeyNameBuffer), PWideChar(Buffer), Length(Buffer));
298 KeyName.Buffer := @Buffer[0];
299 KeyName.Length := Length(NewKeyNameBuffer) * SizeOf(WideChar);
300 InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
301 SoftwareKeyHandle, nil);
302 Status := NtCreateKey(SysKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
303 nil, REG_OPTION_NON_VOLATILE, Disposition);
304 if not NT_SUCCESS(Status) then
305 begin
306 MessageBox(0, 'Error: Couldn''t create HKLM\Software\Systems Internals',
307 'Native API Demo', MB_OK);
308 Exit;
309 end;
310
311 //
312 // Create the Hidden key
313 //
314 SetLength(Buffer, Length(HiddenKeyNameBuffer));
315 MultiByteToWideChar(CP_UTF8, 0, @HiddenKeyNameBuffer[1], Length(
316 HiddenKeyNameBuffer), PWideChar(Buffer), Length(Buffer));
317 KeyName.Buffer := @Buffer[0];
318 KeyName.Length := Length(HiddenKeyNameBuffer) * SizeOf(WideChar);
319 InitializeObjectAttributes(ObjectAttributes, @KeyName, OBJ_CASE_INSENSITIVE,
320 SysKeyHandle, nil);
321 Status := NtCreateKey(HiddenKeyHandle, KEY_ALL_ACCESS, ObjectAttributes, 0,
322 nil, REG_OPTION_NON_VOLATILE, Disposition);
323 if not NT_SUCCESS(Status) then
324 begin
325 MessageBox(0, 'Error: Couldn''t create HKLM\Software\Systems Internals\' +
326 'RegHide', 'Native API Demo', MB_OK);
327 Exit;
328 end;
329
330 //
331 // Create the hidden value
332 //
333 SetLength(Buffer, Length(HiddenValueNameBuffer));
334 MultiByteToWideChar(CP_UTF8, 0, @HiddenValueNameBuffer[1], Length(
335 HiddenValueNameBuffer), PWideChar(Buffer), Length(Buffer));
336 ValueName.Buffer := @Buffer[0];
337 ValueName.Length := Length(HiddenValueNameBuffer) * SizeOf(WideChar);
338 Status := NtSetValueKey(HiddenKeyHandle, @ValueName, 0, REG_SZ,
339 @HiddenValueNameBuffer[1], Length(HiddenValueNameBuffer) * SizeOf(WideChar));
340 if not NT_SUCCESS(Status) then
341 begin
342 MessageBox(0, 'Error: Couldn''t create our hidden value', 'Native API Demo',
343 MB_OK);
344 NtDeleteKey(HiddenKeyHandle);
345 Exit;
346 end;
347
348 //
349 // Let the user try and open our key!
350 //
351 MessageBox(0, 'Try and open the key "HKLM\SOFTWARE\Systems Internals\' +
352 'Can''t touch me!"'#13#10'with Regedit or Regedt32 (or any other ' +
353 'Registry editor). There is a value'#13#10'in the key called "Hidden ' +
354 'Value".'#13#10#13#10'When done trying, press any key to have the key ' +
355 'deleted and exit.', 'Native API Demo', MB_OK);
356
357 //
358 // Cleanup the key
359 //
360 NtDeleteKey(HiddenKeyHandle);
361 end.
|