|
本帖最后由 HoviDelphic 于 2010-4-25 11:03 编辑
无聊的注册表键值保护,能轻易在Ring 3下绕过。
不过网上键值保护的代码貌似比较少,所以还是公布出来吧!
仅仅Hook了三个函数:NtSetValueKey、NtDeleteValueKey、NtRestoreKey。
要完全保护键值,请参考卡巴斯基2010的SSDT HOOK列表。
KERNEL HOOK这东西,估计很快就没有市场了,因为x64不准HOOK。
破PatchGuard确实可以,不过估计没有人会用于商业软件,因为不稳定。
- PVOID GetPointer( HANDLE handle )
- {
- PVOID pKey;
- if(!handle)
- return NULL;
- if(ObReferenceObjectByHandle( handle, 0, NULL, KernelMode, &pKey, NULL ) != STATUS_SUCCESS )
- pKey = NULL;
- return pKey;
- }
- NTSTATUS fake_NtSetValueKey
- (
- IN HANDLE KeyHandle,
- IN PUNICODE_STRING ValueName,
- IN ULONG TitleIndex OPTIONAL,
- IN ULONG Type,
- IN PVOID Data,
- IN ULONG DataSize
- )
- {
- PVOID pKey;
- UNICODE_STRING *pUniName;
- ULONG actualLen;
- ANSI_STRING keyname;
- NTSTATUS status;
- UNICODE_STRING uStrValueName,OurKey;
- if(pKey = GetPointer( KeyHandle))
- {
- //分配内存
- pUniName = ExAllocatePool(NonPagedPool, 1024*2);
- pUniName->MaximumLength = 512*2;
- //将pUniName里的内容清空
- memset(pUniName,0,pUniName->MaximumLength);
- //得到注册表项的路径
- if(NT_SUCCESS(ObQueryNameString(pKey, pUniName, 512*2, &actualLen)))
- {
- RtlUnicodeStringToAnsiString(&keyname, pUniName, TRUE);
- keyname.Buffer=_strupr(keyname.Buffer);//大写所有字母
- //判断是不是Run项
- if (strcmp(keyname.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN") == 0)
- {
- RtlInitUnicodeString( &OurKey, L"test" );
- if( RtlCompareUnicodeString(ValueName,&OurKey,TRUE)==0 )
- {
- //释放内存
- RtlFreeAnsiString(&keyname);
- if(pUniName) ExFreePool(pUniName);
- return STATUS_ACCESS_DENIED;
- }
- }
- }
- }
- RtlFreeAnsiString(&keyname);
- if(pUniName) ExFreePool(pUniName);
- return Old_NtSetValueKey(KeyHandle,ValueName,TitleIndex,Type,Data,DataSize);
- }
- NTSTATUS fake_NtDeleteValueKey(IN HANDLE KeyHandle,IN PUNICODE_STRING ValueName)
- {
- PVOID pKey;
- UNICODE_STRING *pUniName;
- ULONG actualLen;
- ANSI_STRING keyname;
- NTSTATUS status;
- UNICODE_STRING uStrValueName,OurKey;
- if(pKey = GetPointer( KeyHandle))
- {
- //分配内存
- pUniName = ExAllocatePool(NonPagedPool, 1024*2);
- pUniName->MaximumLength = 512*2;
- //将pUniName里的内容清空
- memset(pUniName,0,pUniName->MaximumLength);
- //得到注册表项的路径
- if(NT_SUCCESS(ObQueryNameString(pKey, pUniName, 512*2, &actualLen)))
- {
- RtlUnicodeStringToAnsiString(&keyname, pUniName, TRUE);
- keyname.Buffer=_strupr(keyname.Buffer); //大写所有字母
- //判断是不是Run项
- if (strcmp(keyname.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN") == 0)
- {
- RtlInitUnicodeString( &OurKey, L"test" );
- if( RtlCompareUnicodeString(ValueName,&OurKey,TRUE)==0 )
- {
- //释放内存
- RtlFreeAnsiString(&keyname);
- if(pUniName) ExFreePool(pUniName);
- return STATUS_ACCESS_DENIED;
- }
- }
- }
- }
- RtlFreeAnsiString(&keyname);
- if(pUniName) ExFreePool(pUniName);
- return Old_NtDeleteValueKey(KeyHandle,ValueName);
- }
- NTSTATUS fake_NtRestoreKey(IN HANDLE KeyHandle, IN HANDLE FileHandle, IN ULONG RestoreOption)
- {
- PVOID pKey;
- UNICODE_STRING *pUniName;
- ULONG actualLen;
- ANSI_STRING keyname;
- NTSTATUS status;
- UNICODE_STRING uStrValueName,OurKey;
- if(pKey = GetPointer( KeyHandle))
- {
- //分配内存
- pUniName = ExAllocatePool(NonPagedPool, 1024*2);
- pUniName->MaximumLength = 512*2;
- //将pUniName里的内容清空
- memset(pUniName,0,pUniName->MaximumLength);
- //得到注册表项的路径
- if(NT_SUCCESS(ObQueryNameString(pKey, pUniName, 512*2, &actualLen)))
- {
- RtlUnicodeStringToAnsiString(&keyname, pUniName, TRUE);
- keyname.Buffer=_strupr(keyname.Buffer); //大写所有字母
- //判断是不是Run项
- if (strcmp(keyname.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN") == 0)
- {
- //释放内存
- RtlFreeAnsiString(&keyname);
- if(pUniName) ExFreePool(pUniName);
- return STATUS_ACCESS_DENIED;
- }
- }
- }
- RtlFreeAnsiString(&keyname);
- if(pUniName) ExFreePool(pUniName);
- return Old_NtRestoreKey(KeyHandle,FileHandle,RestoreOption);
- }
复制代码
经测试,仅对regedit.exe和某菜鸟ARK的注册表键值修改、删除有效。 |
|