// 定义一下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;
// 自定义的NtOpenProcess函数 ZwOpenProcess
#pragma PAGECODE
extern "C" NTSTATUS __declspec(naked) __stdcall MyNtOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId )
{
NTSTATUS rc;
HANDLE PID;
DbgPrint("++++++++++++Entry MyNtOpenProcess int ++++++++++++++\n");
//rc = (NTSTATUS)RealNtOpenProcess( ProcessHandle, DesiredAccess, ObjectAttributes, ClientId );
if( (ClientId != NULL) )
{
PID = ClientId->UniqueProcess;
DbgPrint( "------------------------- PID=%d--------------\n",(int*)PID);
// 如果是被保护的PID,则拒绝访问,并将句柄设置为空
if(PID == MyPID)
{
DbgPrint("被保护进程 MyPID=%d \n",(int)MyPID);
//调试输出 类似C语言的 Printf
ProcessHandle = NULL; //这个是关键
rc = STATUS_ACCESS_DENIED; //这个返回值
//PsLookupProcessByProcessId((ULONG)PID,&EP);
EP=PsGetCurrentProcess();
DbgPrint(" ACESS Process Name --:%s-- \n",(PTSTR)((ULONG)EP+0x174));
__asm
{
retn 0x10
}
}
}
__asm
{
//int 3
push 0C4h
mov eax,RealNtOpenProcess //
add eax,5
jmp eax
}
//return rc;
}
//HOOK 函数构建
#pragma PAGECODE
VOID Hook()
{
ssdthook_flag = true;//设置被HOOK标志
DbgPrint("++++HOOK START ++++-\n");
LONG *SSDT_Adr,SSDT_NtOpenProcess_Cur_Addr,t_addr;
DbgPrint("驱动成功被加载中.............................\n");
//读取SSDT表中索引值为0x7A的函数
//poi(poi(KeServiceDescriptorTable)+0x7a*4)
t_addr=(LONG)KeServiceDescriptorTable->ServiceTableBase;
SSDT_Adr=(PLONG)(t_addr+0x7A*4);
SSDT_NtOpenProcess_Cur_Addr=*SSDT_Adr;
RealNtOpenAddress = *SSDT_Adr;
RealNtOpenProcess = (NTOPENPROCESS *)RealNtOpenAddress;
DbgPrint("真实的NtOpenProcess地址: %x\n",(int) RealNtOpenAddress);
DbgPrint("伪造NTOpenProcess地址: %x\n", (int)MyNtOpenProcess );
__asm //去掉页面保护
{
cli
mov eax,cr0
and eax,not 10000h //and eax,0FFFEFFFFh
mov cr0,eax
}
//[804e5a88]=MyNtOpenProcess
//[8058270a]=jmp MyNtOpenProcess=E9 jmpaddr
ULONG jmpaddr=(ULONG)MyNtOpenProcess-RealNtOpenAddress-5;
SSDT_Adr= (PLONG) *SSDT_Adr; //SSDT HOOK jmp jz jnz
// in line hook
__asm
{
mov ebx,SSDT_Adr //RealNtOpenAddress
mov byte ptr ds:[ebx],0xe9
mov eax,jmpaddr
mov DWORD ptr ds:[ebx+1],eax
}
__asm
{ int 3
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
return;
}
//exe部分
int Hook(HANDLE hDevice, ULONG pid) //pid 需要被保护进程ID
{
int port[2];
int bufret;
ULONG dwWrite;
port[0]=pid;
DeviceIoControl(hDevice, hook_code , &port, 8, &bufret, 4, &dwWrite, NULL);
return bufret;
}
int main(int argc, char* argv[])
{
//add
//CreateFile 打开设备 获取hDevice
HANDLE hDevice =
CreateFile("\\\\.\\My_DriverLinkName", //\\??\\My_DriverLinkName
GENERIC_READ | GENERIC_WRITE,
0, // share mode none
NULL, // no security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL ); // no template
printf("start\n");
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("获取驱动句柄失败: %s with Win32 error code: %d\n","MyDriver", GetLastError() );
getchar();
return -1;
}
ULONG pid;
printf("请键入需要被保护的进程PID=");
scanf("%d", &pid);
Hook(hDevice, pid);
return 0;
}
这个是inline hook 的NtOpenProcess 可以正常钩住函数 确实跳转到自己自定义的函数了 但是就是无法获取线程的PID 导致无法保护某个进程的目的。