您的位置:首页 > 其它

HOOK钩子技术5 SSDT Inline Hook

2015-05-14 22:05 579 查看

原理

内联钩子的原理在R3和R0下是相同的,就是不改变SSDT表项,而是改变函数内部前几条指令。

内联钩子的典型伪函数为:

恢复原指令

执行目标操作,或改写参数

执行原函数

返回时重新挂钩

demo

#include "stdafx.h"

#ifdef __cplusplus
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath);
#endif

typedef NTSTATUS (*NtCreateProcess)(
OUT PHANDLE           ProcessHandle,
IN ACCESS_MASK        DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE             ParentProcess,
IN BOOLEAN            InheritObjectTable,
IN HANDLE             SectionHandle OPTIONAL,
IN HANDLE             DebugPort OPTIONAL,
IN HANDLE             ExceptionPort OPTIONAL ,
IN ULONG                JobMemberLevel  );
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PULONG ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG  NumberOfService;
PUCHAR ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TALBE;

NtCreateProcess  real_func_addr = NULL;
unsigned char bOldBytes[5];
unsigned char bNewBytes[5];
extern "C" PSERVICE_DESCRIPTOR_TALBE KeServiceDescriptorTable;//name can't change.  import member must be global variable.

/*
cr0 -16th bit = 0 means page can write
*/
bool REMOVE_ONLYREAD()
{
__asm
{
push eax
mov eax,CR0
and eax, not 10000h
mov CR0,eax
pop eax
}
return TRUE;
}

/*
cr0 -16th bit(WP) = 1,reset to the attribute of ONLY READ
*/
bool RESET_ONLYREAD()
{
__asm
{
push eax
mov eax,CR0
or  eax,10000h
mov CR0,eax
pop eax
}
return TRUE;
}

VOID RelineHookCreateProcess()
{
REMOVE_ONLYREAD();
//writememory with "jmp xxxxxxxx";
RtlCopyMemory((PVOID)real_func_addr,(CONST PVOID)bNewBytes,5);
RESET_ONLYREAD();
}
VOID UnHookCreateProcess()
{
REMOVE_ONLYREAD();
//__asm int 3
RtlCopyMemory((PVOID)real_func_addr,(const PVOID)bOldBytes,5);
RESET_ONLYREAD();
}

void InlineSSDTHookUnload(PDRIVER_OBJECT pDriverObject) //no return ,with return compiler error
{
UnHookCreateProcess();
DbgPrint("GoodBye from InlineHook!\n");

}

NTSTATUS MyNtCreateProcessEx(
OUT PHANDLE           ProcessHandle,
IN ACCESS_MASK        DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE             ParentProcess,
IN BOOLEAN            InheritObjectTable,
IN HANDLE             SectionHandle OPTIONAL,
IN HANDLE             DebugPort OPTIONAL,
IN HANDLE             ExceptionPort OPTIONAL ,
IN ULONG                JobMemberLevel
)
{
NTSTATUS Status = STATUS_SUCCESS;
UnHookCreateProcess();
Status = real_func_addr(
ProcessHandle,
DesiredAccess,
ObjectAttributes,
ParentProcess,
InheritObjectTable,
SectionHandle ,
DebugPort ,
ExceptionPort ,
JobMemberLevel
);
RelineHookCreateProcess();
DbgPrint("have hook CreateProcess!\r\n");

return Status;
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
{
unsigned i;

DbgPrint("Hello from InlineSSDTHook!\n");
DriverObject->DriverUnload = InlineSSDTHookUnload;

//hook
PULONG PSsdt = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
PULONG p_real_func_addr =PSsdt+0x30;       //(unsigned char *) pssdt+0x30*4;
DbgPrint("%08x,%08x",p_real_func_addr,PSsdt+0x30); //diff compared with ssdt hook
real_func_addr = (NtCreateProcess)(*p_real_func_addr);
//__asm int 3
RtlCopyMemory((PVOID)bOldBytes,(CONST PVOID)real_func_addr,5);
bNewBytes[0] ='\xe9';
*(PULONG)&bNewBytes[1]=(ULONG)MyNtCreateProcessEx-(ULONG)real_func_addr-5;
//__asm int 3
RtlCopyMemory((PVOID)real_func_addr,(CONST PVOID)bNewBytes,5);

return STATUS_SUCCESS;
}


今天在做实验的时候,老是出错,无语了。在本地加载了程序的符号文件后调试出现各种奇葩问题,比如说函数入口指令的第一个字节总是没有改回来,后来也不知道怎么解决的。

挂钩后不能打开程序,提示
文件错误
,但是停止服务后恢复正常,所以怀疑是伪函数执行时候有错误,查了半天也没有错误。最后发现是少了一个参数,我函数指针定义成
nt!NtCreatProcess
的参数了,
nt!NtCreateProcessEx
nt!ntCreateProces
多了一个参数
JobMemeberLevel


typedef NTSTATUS (*NtCreateProcessEx)(
OUT PHANDLE           ProcessHandle,
IN ACCESS_MASK        DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE             ParentProcess,
IN BOOLEAN            InheritObjectTable,
IN HANDLE             SectionHandle OPTIONAL,
IN HANDLE             DebugPort OPTIONAL,
IN HANDLE             ExceptionPort OPTIONAL ,
/*************/               IN ULONG                JobMemberLevel  );


可是非常奇怪,参数错误函数执行肯定出错,昨天的SSDT HOOK却也是少了这个参数,挂钩函数也是
nt!ntCreateProcessEx
,按理说应该出错啊,为什么昨天的又是正确的呢???参数不一致也可以?仔细研究一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ssdt-hook