A、初识内核进程相关结构
B、内核函数PsGetCurrentProcess
C、进程保护原理
D、实例测试
dd nt!KeServiceDescriptorTable
NTSTATUS NtOpenProcess(
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in_opt PCLIENT_ID ClientId
);
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;//进程PID
HANDLE UniqueThread; //线程PID
} CLIENT_ID;
dt _CLIENT_ID
dt _eprocess
dt -v -r _eprocess (加上-v -r显示详细结构)
MyNtOpenProcess()
{ 如果要打开进程是我们要保护的
ProcessHandle=NULL
不是
ProcessHandle=NtOpenProcess()//HANDLE hProcess
}
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <NTDDK.h> //这里包含需要用C方式编译的头文件
#ifdef __cplusplus
}
#endif
#include <windef.h>
bool ssdthook_flag=false;
extern "C" extern PServiceDescriptorTable KeServiceDescriptorTable;
//extern "C" NTSTATUS __stdcall PsLookupProcessByProcessId( IN ULONG ulProcId, OUT PEPROCESS * pEProcess );
// 定义一下NtOpenProcess的原型
extern "C" typedef NTSTATUS (__stdcall NTOPENPROCESS)( OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId );
NTOPENPROCESS * RealNtOpenProcess;
PEPROCESS EP;
// 真实的函数地址
ULONG RealServiceAddress;
HANDLE MyPID; //要保护的进程ID
// 自定义的NtOpenProcess函数
#pragma PAGECODE
//************************************
extern "C" NTSTATUS __stdcall MyNtOpenProcess( OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId )
{
NTSTATUS rc;
HANDLE PID;
KdPrint(("++++++++++++Entry MyNtOpenProcess int ++++++++++++++\n"));
rc = (NTSTATUS)RealNtOpenProcess( ProcessHandle, DesiredAccess, ObjectAttributes, ClientId );
if( (ClientId != NULL) )
{
PID = ClientId->UniqueProcess;
KdPrint(( "------------------------- PID=%d--------------\n",(int*)PID ));
// 如果是被保护的PID,直接返回权限不足,并将句柄设置为空
if(PID == MyPID)
{
KdPrint(( "++++++++++++++++++++++++++++被保护进程 MyPID=%d++++++++++++++++++++++++\n",MyPID ));
ProcessHandle = NULL; //这个是关键
rc = STATUS_ACCESS_DENIED;
//PsLookupProcessByProcessId((ULONG)PID,&EP);
EP=PsGetCurrentProcess();
KdPrint(("AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACESS Process Name --:%s-- AAAAAAAAAAAAAAAAAA \n",(PTSTR)((ULONG)EP+0x174)));
KdPrint(( "++++++++++++++++++++++++++++=======================================================+++++++++++++++++++++++\n" ));
}
}
return rc;
}
#pragma PAGECODE
VOID Hook()
{
KdPrint(("++++++++++++++++++++HOOK START +++++++++++++++++++++++++++++++ ---------------------------------\n"));
LONG *SSDT_Adr,SSDT_NtOpenProcess_Cur_Addr,t_addr;
KdPrint(("驱动成功被加载中.............................\n"));
//读取SSDT表中索引值为0x7A的函数
//poi(poi(KeServiceDescriptorTable)+0x7a*4)
t_addr=(LONG)KeServiceDescriptorTable->ServiceTableBase;
KdPrint(("当前ServiceTableBase地址为%x \n",t_addr));
SSDT_Adr=(PLONG)(t_addr+0x7A*4);
KdPrint(("当前t_addr+0x7A*4=%x \n",SSDT_Adr));
SSDT_NtOpenProcess_Cur_Addr=*SSDT_Adr;
RealServiceAddress = *SSDT_Adr;
RealNtOpenProcess = ( NTOPENPROCESS *)RealServiceAddress;
KdPrint(( "真实的NtOpenProcess地址: %x\n",(int) RealServiceAddress ));
KdPrint((" 伪造NTOpenProcess地址: %x\n", (int)MyNtOpenProcess ));
__asm //去掉页面保护
{
cli
mov eax,cr0
and eax,not 10000h //and eax,0FFFEFFFFh
mov cr0,eax
}
*SSDT_Adr= (ULONG)MyNtOpenProcess;
__asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
return;
}
//////////////////////////////////////////////////////
#pragma PAGECODE
VOID UnHook()
{
ULONG Old_ssdt;
Old_ssdt = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;
if (ssdthook_flag)
{ ssdthook_flag=false;
__asm
{
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
}
// 还原SSDT
*((ULONG*)Old_ssdt) = (ULONG)RealServiceAddress;
__asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
KdPrint(("UnHook还原SSDT OK \n"));
}
return;
}
#define hook_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_NEITHER,FILE_ANY_ACCESS)
#define unhook_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_NEITHER,FILE_ANY_ACCESS)