是这样的,有可能我是没有说清楚吧,我详细的说一下哈。
我想写个注册表监视的驱动,同时用了SSDT和Inline Hook,去HOOK了ZwQueryValueKey,SSDT用的网上流传很多的常用的一个宏,Inline是在函数的前五个字节去跳转的,也是网上
的大侠们共享出来的,同时进入我的HookedNtQueryValueKey,也就是这句代码
if ( !_strnicmp( szipmsg, pName, strlen(szipmsg) ) )//测试用的ipmsg.exe
{
DbgPrint( "-------I am ipmsg.exe !!!---------" );
KdPrint(( "SubKey Name: %ws \n", valueName->Buffer ));
}
发现打出来的信息不相同,SSDT比较全,应该是对的,inline打出来的就太少了
,相对比之下总觉得inline有哪儿不对,可是又找不到原因,唯一我可以想到的就是inline和SSDT
他们的原理有点不同,还有个问题是ZwQueryValueKey这个函数系统调用很频繁,部分inline代码如下,望请大侠们帮忙看看.
//////////////////////////////////////////////////////////////////////////
VOID HookOn()
{
//====================================================
// 获取函数地址
//====================================================
UNICODE_STRING funcName;
RtlInitUnicodeString(&funcName,FUNC_NAME); //预hook的函数名字
Old_FuncAddress=MmGetSystemRoutineAddress(&funcName);
//DbgPrint("Hook [NtOpenProcess] -*Inline Hook Sample");
//DbgPrint("NtOpenProcess -> :%x",(LONG*)Old_FuncAddress);
//RtlFreeUnicodeString(&funcName);
//====================================================
// 改变原始函数头字节跳转
//====================================================
RtlCopyMemory(oricode,(UCHAR*)Old_FuncAddress,5); //备份前5字节
*((ULONG*)(nowcode+1)) = (ULONG)HookFunc - (ULONG)Old_FuncAddress - 5; //计算跳转地址
//DbgPrint("%x -> jmp %x",Old_FuncAddress,(ULONG)HookFunc); //上面计算的地址显示
DisableWP(); //关中断保护
RtlCopyMemory((UCHAR*)Old_FuncAddress,nowcode,5); //(*)写新地址到原函数中
RtlCopyMemory((UCHAR*)JmpFunc,oricode,5); //备份的5个字节写入到jmpfunc里
*((ULONG*)(jmpcode+1)) = (ULONG)Old_FuncAddress - (ULONG)JmpFunc - 5; //生成一条JMP ****指令跳转到原函数+5的位置
//DbgPrint("Hook Return -> jmp %x",(ULONG)Old_FuncAddress+5); //上面生成的地址显示
RtlCopyMemory((UCHAR*)JmpFunc+5,jmpcode,5); //将这个指令写入到jmpfunc里
EnableWP(); //开
中断保护
return;
}
//////////////////////////////////////////////////////////////////////////
NTSTATUS NTAPI
HookedNtQueryValueKey(
IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength
)
{
NTSTATUS status = STATUS_SUCCESS;
PEPROCESS pProcess;
char* pName = NULL;
pProcess = PsGetCurrentProcess();
pName = ((char *)pProcess+g_ProcessNameOffset);
// DbgPrint( "-------I am here!!!---------" );
if ( !_strnicmp( szipmsg, pName, strlen(szipmsg) ) )//测试用的ipmsg.exe
{
DbgPrint( "-------I am ipmsg.exe !!!---------" );
KdPrint(( "SubKey Name: %ws \n", valueName->Buffer ));
}
status = JmpNtQueryValueKey(KeyHandle,ValueName,KeyValueInformationClass,KeyValueInformation,Length,ResultLength);
return status;
}
//*************************************************//
__declspec(naked)
//这里声明做一个编译器免优化指令 《__declspec(naked)》
NTSTATUS NTAPI
JmpNtQueryValueKey(
IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength
)
{
//***********************************//
__asm
{
//伪指令
//0x90 = nop
//nop用于写入指令
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
_emit 0x90
}
//***********************************//
}