在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,选择驱动编译,
插入下列代码实现内存填0杀进程,请见代码分析
void WPOFF() { __asm { //去掉内存保护 cli mov eax,cr0 and eax,not 10000h mov cr0,eax } } void WPON() { __asm { //恢复内存保护 mov eax,cr0 or eax,10000h mov cr0,eax sti } } ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// #ifdef __cplusplus } #endif #endif NTKERNELAPI BOOLEAN KeInsertQueueApc ( PRKAPC Apc, PVOID SystemArgument1, PVOID SystemArgument2, KPRIORITY Increment ); BOOLEAN fake_KeInsertQueueApc(IN PKAPC Apc, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN KPRIORITY PriorityBoost); BOOLEAN Proxy_KeInsertQueueApc(IN PKAPC Apc, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN KPRIORITY PriorityBoost); ULONG g_uCr0; void WPOFF() { ULONG uAttr; _asm { push eax; mov eax, cr0; mov uAttr, eax; and eax, 0FFFEFFFFh; // CR0 16 BIT = 0 mov cr0, eax; pop eax; cli }; g_uCr0 = uAttr; //保存原有的 CRO 屬性 } VOID WPON() { _asm { sti push eax; mov eax, g_uCr0; //恢復原有 CR0 屬性 mov cr0, eax; pop eax; }; } #include <ntddk.h> #include"ntifs.h" typedef unsigned long DWORD; PHYSICAL_ADDRESS g_PhysicalPage; void WPOFF() { __asm { //去掉内存保护 cli mov eax,cr0 and eax,not 10000h mov cr0,eax } } void WPON() { __asm { //恢复内存保护 mov eax,cr0 or eax,10000h mov cr0,eax sti } } VOID DestroyProcess(DWORD eproc) { DWORD VirtualAddr; PHYSICAL_ADDRESS physical_addr; DWORD AddrTmp; PVOID ProcessHandle; KeAttachProcess( (PEPROCESS)eproc ); for ( VirtualAddr = 0x1000; VirtualAddr < *(DWORD*)MmSystemRangeStart; VirtualAddr+=0x1000) { // 跳过不再内存里的 physical_addr = MmGetPhysicalAddress( (PVOID)VirtualAddr); if ( physical_addr.HighPart > g_PhysicalPage.HighPart ) continue; if ( physical_addr.HighPart == g_PhysicalPage.HighPart && physical_addr.LowPart >= g_PhysicalPage.LowPart ) continue; if ( (physical_addr.HighPart | physical_addr.LowPart) == 0 ) continue; AddrTmp = (DWORD)MmGetVirtualForPhysical( physical_addr); if ( AddrTmp != VirtualAddr) continue; WPOFF(); RtlZeroMemory( (PVOID)VirtualAddr, 0x1000); WPON(); } KeDetachProcess(); if ( ObOpenObjectByPointer( (PVOID)eproc, 0, NULL, 0, NULL, KernelMode, &ProcessHandle) != STATUS_SUCCESS) return; ZwTerminateProcess( (HANDLE)ProcessHandle, STATUS_SUCCESS); ZwClose( (HANDLE)ProcessHandle ); return; } VOID OnUnload( IN PDRIVER_OBJECT DriverObject ) { DbgPrint("My Driver UnLoad!"); } //================================================================================================ NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath ) { SYSTEM_BASIC_INFORMATION BasicInfo; ULONG ReturnedLength; PEPROCESS eproc; DbgPrint("My Driver Loaded!"); theDriverObject->DriverUnload = OnUnload; ZwQuerySystemInformation( SystemBasicInformation, &BasicInfo, sizeof(SYSTEM_BASIC_INFORMATION), &ReturnedLength); __asm mov eax,BasicInfo.PhysicalPageSize; __asm mul BasicInfo.NumberOfPhysicalPages; __asm mov g_PhysicalPage.HighPart, edx; __asm mov g_PhysicalPage.LowPart, eax; PsLookupProcessByProcessId((PVOID)1068,&eproc); DestroyProcess((DWORD)eproc); return STATUS_SUCCESS; } //================================================================================================ #include "pe.h" #ifndef GLOBAL_NATIVE_API_DEF_SUDAMI #define GLOBAL_NATIVE_API_DEF_SUDAMI #ifdef __cplusplus extern "C" { #endif //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// typedef long NTSTATUS, *PNTSTATUS; typedef unsigned long DWORD; typedef DWORD * PDWORD; typedef unsigned long ULONG; typedef unsigned long ULONG_PTR; typedef ULONG *PULONG; typedef unsigned short WORD; typedef unsigned char BYTE; typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef void *PVOID; typedef int BOOL; typedef BYTE BOOLEAN; typedef CCHAR KPROCESSOR_MODE; #ifndef LOWORD #define LOWORD(l) ((unsigned short)(unsigned int)(l)) #endif #ifndef HIWORD #define HIWORD(l) ((unsigned short)((((unsigned int)(l)) >> 16) & 0xFFFF)) #endif // 定义ioctl相关的,用于R3和R0间的通信 #ifndef MAKELONG #define MAKELONG(a, b) ((LONG) (((WORD) (a)) | ((DWORD) ((WORD) (b))) << 16)) #endif #define MY_DEVICE_TYPE 0x0000AA71 // 这地方可以自己改 #define DRIVER_IO(code) CTL_CODE (MY_DEVICE_TYPE, code, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; /********************************************************** #define NT_DEVICE_NAME L"\\Device\\sKillTimeProtected" #define DOS_DEVICE_NAME L"\\DosDevices\\sKillTimeProtected" // -- #ifndef ANSI_STRING typedef struct _STRING { USHORT Length; USHORT MaximumLength; PCHAR Buffer; } ANSI_STRING, *PANSI_STRING; #endif #ifndef UNICODE_STRING typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; #endif /* SSDT */ #pragma pack(1) typedef struct ServiceDescriptorEntry { unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; unsigned int NumberOfServices; unsigned char *ParamTableBase; } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t; typedef struct ServiceDescriptorShadowEntry { unsigned int *Win32kTableBase; unsigned int *Win32kCounterTableBase; unsigned int NumberofWin32kServices; unsigned char *Win32kParamTableBase; } ServiceDescriptorTableShadowEntry_t, *PServiceDescriptorTableShadowEntry_t; #pragma pack() __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; PServiceDescriptorTableShadowEntry_t KeServiceDescriptorTableShadow; struct _SYSTEM_THREADS { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientIs; KPRIORITY Priority; KPRIORITY BasePriority; ULONG ContextSwitchCount; ULONG ThreadState; KWAIT_REASON WaitReason; }; struct _SYSTEM_PROCESSES { ULONG NextEntryDelta; ULONG ThreadCount; ULONG Reserved[6]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; ULONG ProcessId; ULONG InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; IO_COUNTERS IoCounters; //windows 2000 only struct _SYSTEM_THREADS Threads[1]; }; // PROCESS_BASIC_INFORMATION #ifdef PROCESS_BASIC_INFORMATION #undef PROCESS_BASIC_INFORMATION typedef struct _PROCESS_BASIC_INFORMATION { NTSTATUS ExitStatus; ULONG PebBaseAddress; ULONG_PTR AffinityMask; LONG BasePriority; ULONG_PTR UniqueProcessId; ULONG_PTR InheritedFromUniqueProcessId; } PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; #endif // SYSTEM_HANDLE_INFORMATION typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO { USHORT UniqueProcessId; USHORT CreatorBackTraceIndex; UCHAR ObjectTypeIndex; UCHAR HandleAttributes; USHORT HandleValue; // 句柄 PVOID Object; // 若HANDLE类型为线程,则它是ETHREAD结构 ULONG GrantedAccess; } SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO; typedef struct _SYSTEM_HANDLE_INFORMATION { ULONG NumberOfHandles; SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1]; } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; // SYSTEM_MODULE_INFORMATION typedef struct _SYSTEM_MODULE_INFORMATION { ULONG Reserved[2]; PVOID Base; ULONG Size; ULONG Flags; USHORT Index; USHORT Unknown; USHORT LoadCount; USHORT ModuleNameOffset; CHAR ImageName[256]; } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; typedef struct { ULONG dwNumberOfModules; SYSTEM_MODULE_INFORMATION smi; } MODULES, *PMODULES; // SYSTEM_BASIC_INFORMATION typedef struct _SYSTEM_BASIC_INFORMATION { ULONG Unknown; //Always contains zero ULONG MaximumIncrement; //一个时钟的计量单位 ULONG PhysicalPageSize; //一个内存页的大小 ULONG NumberOfPhysicalPages; //系统管理着多少个页 ULONG LowestPhysicalPage; //低端内存页 ULONG HighestPhysicalPage; //高端内存页 ULONG AllocationGranularity; ULONG LowestUserAddress; //地端用户地址 ULONG HighestUserAddress; //高端用户地址 ULONG ActiveProcessors; //激活的处理器 UCHAR NumberProcessors; //有多少个处理器 } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; // SYSTEM_INFORMATION_CLASS typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation, SystemProcessorInformation, SystemPerformanceInformation, SystemTimeOfDayInformation, SystemPathInformation, SystemProcessInformation, SystemCallCountInformation, SystemDeviceInformation, SystemProcessorPerformanceInformation, SystemFlagsInformation, SystemCallTimeInformation, SystemModuleInformation, // 11 SystemLocksInformation, SystemStackTraceInformation, SystemPagedPoolInformation, SystemNonPagedPoolInformation, SystemHandleInformation, // 0x10 -- 16 SystemObjectInformation, SystemPageFileInformation, SystemVdmInstemulInformation, SystemVdmBopInformation, SystemFileCacheInformation, SystemPoolTagInformation, SystemInterruptInformation, SystemDpcBehaviorInformation, SystemFullMemoryInformation, SystemLoadGdiDriverInformation, SystemUnloadGdiDriverInformation, SystemTimeAdjustmentInformation, SystemSummaryMemoryInformation, SystemUnused1, SystemPerformanceTraceInformation, SystemCrashDumpInformation, SystemExceptionInformation, SystemCrashDumpStateInformation, SystemKernelDebuggerInformation, SystemContextSwitchInformation, SystemRegistryQuotaInformation, SystemExtendServiceTableInformation, SystemPrioritySeperation, SystemUnused3, SystemUnused4, SystemUnused5, SystemUnused6, SystemCurrentTimeZoneInformation, SystemLookasideInformation, SystemTimeSlipNotification, SystemSessionCreate, SystemSessionDetach, SystemSessionInformation } SYSTEM_INFORMATION_CLASS; #ifndef SECTION_INHERIT typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT; #endif #ifndef LUID typedef struct _LUID { DWORD LowPart; LONG HighPart; } LUID, *PLUID; #endif #ifndef LARGE_INTEGER typedef union _LARGE_INTEGER { struct { ULONG LowPart; LONG HighPart; }; struct { ULONG LowPart; LONG HighPart; } u; LONGLONG QuadPart; } LARGE_INTEGER, *PLARGE_INTEGER; #endif #ifndef TIME_FIELDS typedef struct _TIME_FIELDS { USHORT Year; USHORT Month; USHORT Day; USHORT Hour; USHORT Minute; USHORT Second; USHORT Milliseconds; USHORT Weekday; } TIME_FIELDS, *PTIME_FIELDS; #endif NTSTATUS NTAPI ZwQuerySystemInformation( DWORD SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); NTSYSAPI NTSTATUS NTAPI NtOpenFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions ); NTSYSAPI VOID NTAPI RtlInitUnicodeString( PUNICODE_STRING DestinationString, PCWSTR SourceString ); NTSYSAPI NTSTATUS NTAPI ZwOpenSection( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES objectAttributes ); NTSYSAPI NTSTATUS NTAPI ZwMapViewOfSection( IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG ZeroBits, IN ULONG CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PULONG ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect ); NTSYSAPI NTSTATUS NTAPI NtCreateSection( PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER MaximumSize OPTIONAL, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle ); NTSYSAPI NTSTATUS NTAPI ZwUnmapViewOfSection( IN HANDLE ProcessHandle, IN PVOID BaseAddress ); NTSYSAPI NTSTATUS NTAPI NtReadFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL ); NTSYSAPI VOID NTAPI RtlTimeToTimeFields( IN PLARGE_INTEGER Time, OUT PTIME_FIELDS TimeFields ); NTSYSAPI BOOLEAN NTAPI RtlTimeFieldsToTime( IN PTIME_FIELDS TimeFields, OUT PLARGE_INTEGER Time ); /* VOID NTAPI KeSetSystemTime( IN PLARGE_INTEGER NewTime, OUT PLARGE_INTEGER OldTime, IN BOOLEAN FixInterruptTime, IN PLARGE_INTEGER HalTime OPTIONAL ); */ NTSTATUS NTAPI NtQuerySystemTime ( OUT PLARGE_INTEGER SystemTime ); // 写保护的开&关 void WPOFF() { __asm { //去掉内存保护 cli mov eax,cr0 and eax,not 10000h mov cr0,eax } } void WPON() { __asm { //恢复内存保护 mov eax,cr0 or eax,10000h mov cr0,eax sti } } ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// #ifdef __cplusplus } #endif #endif