钩子的内存空间
用户空间的钩子的问题之一是为了编写LoadLibrary参数或编写代码,钩子通常必须在远程进程中分配空间。在内核中存在一个可写区域,它映射到每个进程的地址空间。另一个技术利用了两个虚拟地址映射到同一个物理地址这个事实。内核地址0xFFDF0000和用户地址0x7FFE0000都指向同义物理页面。该共享区域内核地址是可写的,但用户地址则不能写。利用MDL的方法可以将代码写到内核地址并以用户地址来访问它。
该共享区域的大小是4k,内核占用其中的一部分,但还可以使用大约3k的空间用于代码和变量。该内存区域的名称是KUSER_SHARED_DATA,以下是一个写入该区域的示例:
DWORD d_shareM = 0x7ffe0800; // A user Address
DWORD d_sharedK = 0xffdf0800; // A Kernel Address
Unsigned char new_code[]= {
0x90, // NOP make INT 3 to see
0xb8, 0xff, 0xff, 0xff,0xff, // move ax, 0xffffffff
0xff, 0xe0 // jmp eax
};
If ( !gb_Hooked )
{
RtlCopyMemory((PVOID)d_sharedK, new_code, 8);
RtlCopyMemory( (PVOID)(d_sharedK +2), (PVOID)&pd_IAT[index], 4);
gb_Hooked = TRUE;
}
第一字节是操作码,若希望观察行为,则使用NOP指令或INT3(break)指令,后续7个字节只是将一个哑地址移入EAX,然后跳转到该地址。此时钩子函数的编写者需要向内存中写入一个更高级的函数以便真正函数的输出进行过滤。