我已经了解了使用Sysinternals记录的技术在注册表中隐藏注册表值的可能性,该技术允许您使用本机API(例如,“hello \ 0”)将空字符放入注册表项中: http://technet.microsoft.com/en-us/sysinternals/bb897446.aspx(滚动到“隐藏的注册表项”部分)。
他们还有一个工具来查找和删除这些值: http://technet.microsoft.com/en-us/sysinternals/bb897448.aspx
任何人都知道如何使用这种技术在Delphi中创建/读取/删除隐藏的注册表值?
答案 0 :(得分:12)
您给出的sysinternals链接很好地描述了理论:
“在 Win32 API字符串中 解释为以NULL结尾的ANSI (8位)或宽字符(16位) 字符串。在 Native API名称中 计算Unicode(16位)字符串。 虽然这种区别通常不是 重要的是,它留下了开放的 有趣的情况:有一个 可以引用的名称类 使用Native API,但不能 使用Win32 API进行描述。“
所以,使用win32的RegCreateKeyW(),如果你试图给它一个像“Foo \ 0Bar”这样的键名,它只会使用“Foo \ 0”,而不会看到其余的。
使用本机API等效项,如NtCreateKey,您必须提供字符串缓冲区和长度(作为OBJECT_ATTRIBUTES参数的UNICODE_STRING成员)。所以它会愉快地使用,并创建一个名为“Foo \ 0Bar”的键。
Regedit或使用win32 api的任何其他程序将无法打开此密钥。当他们枚举父级时,他们只会返回名称为“Foo \ 0”的以null结尾的版本,该版本并不存在。因此,如果您在regedit中单击“Foo”,它将引发错误,因为其RegOpenKey(“Foo”)调用失败。
要查找,打开和删除这些内容,您需要转到本机API。
第一步是将函数声明和支持参数类型转换为delphi,并从ntdll.dll动态加载函数。
以下是一些开始玩的转换:
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;
还有一个旧的article over at the codeproject,它有更多的示例代码(C ++),以及解释,让你完成其余部分。
答案 1 :(得分:0)
我想指出一个事实,即这只隐藏了注册表项和regedit(和它一样的工具)。如果您依赖于此来“保护”您的软件免受盗版,您仍然可以使用使用本机API开发的工具对RegMon或程序化注册表访问等程序开放。