UID 587
精华
积分 78
威望 点
宅币 个
贡献 次
宅之契约 份
最后登录 1970-1-1
在线时间 小时
本帖最后由 dumingqiao 于 2015-8-4 12:10 编辑
最近需要研究自己实现 KiFastCallEntry的实现,所以我们必须先获取到这个函数的地址,下面我来说说这个玩意儿在哪里能找到,在CPU里有逻辑处理器(Processor)每个处理器内部都有形形色色的寄存器(Registers),其中有一个特殊的寄存器-——MSR(Model Specific Registers 特殊模块寄存器),保存着这个函数的地址,但是呢在x86下保存在0x176的模块号中,x64下则保存在0xc0000082中。
好,废话不多说上WinDbg,先找出这个地址再说,我这里使用的windows XP测试的,所有对应的地址应该在0x176中,在x86下我们可以使用汇编指令rdmsr/wrmsr进行读写MSR寄存器,在X64下由于不能使用内联汇编,读写MSR 可以用_readmsr()/_writemsr(),关于这两个指令和函数的使用请大家查阅相关文档,下面大家看图。
Ok下面我附上代码:
#include<ntddk.h>
ULONG OldAddr;
VOID DriverUnload(PDRIVER_OBJECT pDriver_Object);
__declspec(naked)MyKiFastCallEntry(VOID)
{
__asm jmp OldAddr
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver_Object,PUNICODE_STRING pRegstryString)
{
KAFFINITY ActiveProcessors, CurrentAffinity;
pDriver_Object->DriverUnload=DriverUnload;
ActiveProcessors=KeQueryActiveProcessors();
for(CurrentAffinity = 1;ActiveProcessors;CurrentAffinity <<= 1)
{
if(ActiveProcessors & CurrentAffinity)
{
ActiveProcessors &= ~CurrentAffinity;
KeSetSystemAffinityThread(CurrentAffinity);
__asm
{
int 3
cli
push ecx
push eax
mov ecx,0x176
rdmsr
mov OldAddr,eax
xor eax,eax
mov eax,MyKiFastCallEntry
wrmsr
xor eax,eax
xor ecx,ecx
pop eax
pop ecx
sti
}
DbgPrint("KiFastCallEntry Addr:%08x\n",OldAddr);
}
}
DbgPrint("NewKiFastCallEntry Addr:%08x\n",MyKiFastCallEntry);
return STATUS_SUCCESS;
}
VOID DriverUnload(PDRIVER_OBJECT pDriver_Object)
{
KAFFINITY ActiveProcessors,CurrentAffinity;
ActiveProcessors=KeQueryActiveProcessors();
for(CurrentAffinity = 1;ActiveProcessors;CurrentAffinity <<= 1)
{
if(ActiveProcessors & CurrentAffinity)
{
ActiveProcessors &= ~CurrentAffinity;
KeSetSystemAffinityThread(CurrentAffinity);
_asm
{
cli
push ecx
push eax
mov ecx,0x176
mov eax,OldAddr
wrmsr
xor ecx,ecx
xor eax,eax
pop eax
pop ecx
sti
}
}
}
DbgPrint("驱动卸载成功\n");
}
复制代码
我们把上面附上的这段代码编译为驱动后加载之后再去看看
这里说明下网上有类似的代码,我发现并没有处理多核环境下的问题,虚拟机是两个核心的,而这两个核心都被修改了,到这里我们也就HOOK成功了,接下来我们也就是要自己实现KiFastCallEntry的部分了,希望对大家有帮助,过段时间我再发怎么自己实现这个函数来过滤系统调用,今天就写到这里。