Hook注册表读写后,需要根据注册表项名称(注册表路径)做一些判断,但是hook只能拿到注册表句柄HEY,必要根据HEY获取注册路径。ntdll.dll中ZwQueryKey函数可以根据句柄获取一系列注册表信息,其中KeyNameInformation代表注册表项名称的信息。参考微软定义:
NTSYSAPI NTSTATUS ZwQueryKey(
[in] HANDLE KeyHandle,
[in] KEY_INFORMATION_CLASS KeyInformationClass,
[out, optional] PVOID KeyInformation,
[in] ULONG Length,
[out] PULONG ResultLength
);
转换为Delphi定义
function ZwQueryKey(hkey:THandle;ntype:DWORD;buffer:PVoid;bufferlen:ULONG;ncount:PULONG):integer;stdcall;external ‘ntdll.dll’;
调用过程很简单,32位测试正常,64位下没通过。排查ZwQueryKey函数定义参数是否在64位下大小是否与VS一致,没发现问题。最后检查ZwQueryKey返回结果是80000002,数据对齐错误。最终测试代码如下:
function GetKeyPathFromHKey(hkey:Thandle):string;
var
ntype:dword;
data:pvoid;
buffer,obuffer:pchar;
ncount:ULONG;
bufferlen:LONG;
n:integer;
begin
result:='';
ntype:=3; //KeyNameInformation
bufferlen:=1024*2;
//64位要8位对齐
GetMem(obuffer,bufferlen);
n:=UInt64(obuffer) mod 8;
if n<>0 then
buffer:=obuffer+8-n
else
buffer:=obuffer;
if ZwQueryKey(hKey,ntype,pvoid(buffer),bufferlen,PULONG(@ncount))=0 then begin
buffer:=buffer+2; //前4位是长度
ncount:=ncount-4;
buffer[ncount div 2]:=#0;
result:=buffer;
end;
freeMem(obuffer);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
reg:TRegistry;
begin
Reg:=TRegistry.Create ;
Reg.RootKey := HKEY_LOCAL_MACHINE;
if(Reg.OpenKey('SoftWare\Microsoft',False)) then begin
memo1.Lines.Add(getkeypathfromhkey(Reg.CurrentKey));
end;
Reg.Free;
end;