本帖最后由 chujunci 于 2011-11-26 22:28 编辑
SSDT HOOK实现 :
typedef struct ServiceDescriptorTable{
PVOID pvSSDTBase;
PVOID pvServiceCounterTable;
ULONG ulNumberOfServices;
PVOID pvParamTableBase;
}SSDT, *PSSDT;
DDK 的头文件中声明 KeServiceDescriptorTable,
Extern PSSDT KeServiceDescriptorTable;
//修改SSDT表只读为可
__asm
{
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
}
ULONG Address;
//Windows XP下NtOpenProcess项在SSDT表中的索引为7AH
//因此在SSDT表中的地址为:基址+7AH*4
Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;
//保存原NtOpenProcess地址
RealOPServiceAddress = *(ULONG*)Address;
RealNtOpenProcess = (NTOPENPROCESS)RealOPServiceAddress;
//挂载NtOpenProcess钩子函数
*((ULONG*)Address) = (ULONG)MyNtOpenProcess;
//修改SSDT为只读
__asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
至此,对 NtOpenProcess 函数的 HOOK 完毕,当其他进程调用时就会执行
MyNtOpenProcess。取消 HOOK 的流程与 HOOK 的流程类似,只是将原来保存
的真实服务地址写回 SSDT 表项中即可.
钩子函数的实现:
NTSTATUS __stdcall MyNtOpenProcess( OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId ){
,,
//判断是否为正在保护的进程
if( (ClientId != NULL) ){
pid = (ULONG)ClientId->UniqueProcess;
for(i = 0; i < MAX_ANTIOPEN_NUM; i++)
//如果是则返回打开失败
if( ANTIOPEN_PIDS == pid ){
ProcessHandle = NULL;
rc = STATUS_ACCESS_DENIED;
return rc;
}
}
//非保护进程则调用原打开函数正常打开
rc = (NTSTATUS)(NTOPENPROCESS)RealNtOpenProcess( ProcessHandle, DesiredAccess,
ObjectAttributes, ClientId );
return rc;
}
// GetProcessInfo:从指定进程执行体中获取进程PID及进程名
void GetProcessInfo(IN PEPROCESS pEprocess, OUT PULONG uProcessId, OUT PUCHAR *
szProccessName)
{
PUCHAR eprocess = (PUCHAR) pEprocess;
* uProcessId = *((PULONG)(eprocess + 0x084));
* szProccessName = eprocess + 0x0174;
}
NTSTATUS __stdcall MyNtTerminateProcess( IN HANDLE ProcessHandle,
IN NTSTATUS ExitStatus){
,,
//获取进程句柄随对应的内存块地址
rc = ObReferenceObjectByHandle(ProcessHandle,FILE_READ_DATA,0,KernelMode
,&pEprocess,0);
if(rc != STATUS_SUCCESS)
return (NTSTATUS)(NTTERMINATEPROCESS)RealNtTerminateProcess(
ProcessHandle, ExitStatus);
//从进程执行体数据结构里获取进程PID
GetProcessInfo(pEprocess,&uProcessId,&szProccessName);
//判断是否为正在保护的进程
for(i = 0; i < MAX_ANTITERM_NUM; i++)
if(ANTITERM_PIDS == uProcessId){ //如果是则返回结束失败
rc = STATUS_ACCESS_DENIED;
return rc;
}
//非保护进程则调用原结束函数结束
return (NTSTATUS)(NTTERMINATEPROCESS)RealNtTerminateProcess( ProcessHandle,
ExitStatus);
}
|