void PrintHook()
{
DbgPrint(" Now Get In ZwCreateFile Hook: %d...Pid: %d...\n", g_HookNumber++, (DWORD)PsGetCurrentProcessId());
}
__declspec(naked) void NewZwCreateFile()
{
__asm
{
pushfd; // 仅仅适合于 XP 操作系统
call PrintHook;
popfd;
mov eax,0x25;
jmp g_OldCreateFile;
}
}
void SetHB() // set hardware breakpoint 设置硬件断点
{
__asm
{
mov eax, ZwCreateFile; // 想要挂接的函数或者地址
mov dr0, eax;
mov eax, dr7;
or eax, 0x2703; // 也要修改 dr7:GD 位,以免DrX被操作系统或其他程序修改
and eax, 0xfff0ffff;
mov dr7, eax;
}
}
__declspec(naked) void NewDBEntry()
{
__asm
{
pushfd;
push eax;
mov eax, dr6;
test eax, 0x2000;
jz NOT_EDIT_DRX;
// 以下是如果有对DRX的操作的简单处理,如有需要可以修改
// 我只是简单的跳过这些指令
and eax, 0xFFFFDFFF;
mov dr6, eax; // 清除DR6的标志
cmp g_bExit, 0;
jnz MY_DRV_EXIT; // 驱动 Unload
mov eax, [esp+8]; // 获取堆栈中的 EIP
add eax, 3; // 由于所有对 DRX 的操作全都是3个字节的
mov [esp+8], eax; // 修改 EIP ,跳过当前指令,返回时执行下条指令
jmp MY_INT_END;
NOT_EDIT_DRX:
mov eax, dr6;
test eax, 0x1;
jz SYS_INT; // 如果不是Dr0 产生的中断,则跳回原系统中断
mov eax, [esp+8];
cmp eax, ZwCreateFile; // 判断一下是不是 ZwCreateFile 的线性地址
jnz SYS_INT;
mov eax, NewZwCreateFile;
mov [esp+8],eax; // 修改堆栈中的 EIP ,实现返回时跳转
MY_INT_END:
mov eax, dr7;
or eax, 0x2000; // 恢复 GD 位
mov dr7, eax;
MY_DRV_EXIT: // 整个驱动 UnLoad 时,不恢复 Dr7
pop eax;
popfd;
iretd;
SYS_INT:
pop eax;
popfd;
jmp g_OldDBEntry;
}
}
DWORD GetDBEntry()
{
PIDTENTRY IdtEntry;
DWORD Entry;
__asm sidt g_IDTR;
IdtEntry = (PIDTENTRY)(g_IDTR.IDTBase + 8);
Entry = IdtEntry->HiOffset << 16;
Entry |= IdtEntry->LowOffset;
return Entry;
}
void HookDBInt()
{
DWORD NewEntry;
PIDTENTRY IdtEntry;
NewEntry = (DWORD)NewDBEntry;
g_OldCreateFile = (DWORD)ZwCreateFile + 5; // 新的要跳转过去的地址
g_OldDBEntry = GetDBEntry();
IdtEntry = (PIDTENTRY)(g_IDTR.IDTBase + 8);
CliAndDisableWPBit();
IdtEntry->LowOffset = (USHORT)NewEntry;
IdtEntry->HiOffset = (USHORT)( NewEntry >> 16 );
ReLoadCR0AndSti();
SetHB();
g_bExit = FALSE;
return;
}
void UnHookDBInt()
{
PIDTENTRY IdtEntry;
DWORD Entry;
__asm sidt g_IDTR;
IdtEntry = (PIDTENTRY)(g_IDTR.IDTBase + 8);
CliAndDisableWPBit();
g_bExit = TRUE;
__asm mov eax, dr7; // 产生一次例外并且清除Dr7:GD
if ( g_OldDBEntry != 0 )
{
IdtEntry->LowOffset = (USHORT)g_OldDBEntry;
IdtEntry->HiOffset = (USHORT)( g_OldDBEntry >> 16 );
}
ReLoadCR0AndSti();
DbgPrint(" UnLoad drx hook..\n");
return;
}
NTSTATUS DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
UnHookDBInt();
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
HookDBInt();
DriverObject->DriverUnload = DriverUnload;
DbgPrint("Load drxhook Driver Ok...\n");
return STATUS_SUCCESS;
}
/***********************/
以上代码实现了简单的ZwCreateFile 函数的HOOK,可以拿DbgView查看效果.
由于本人水平有限,代码中难免有错误出现,希望指正.
同时也希望各位牛人来指点,yykingking@126.com
/**************下面是罗嗦几句********************/
1.这个方法呢首先不怎么实用,因为你用了调试寄存器后某些壳也想用,因此就冲突了,可能会使某些东西失效,不如传统的HOOK好用(据说利用缺页中断HOOK也比较好用,没试过)。还有人认为呢这个HOOK虽然是HOOK成功了,但是还得HOOK中断向量,没有必要。其实呢,只是多了种思路罢了,多给大家提供一些想法而已。
2.其次呢,这个方法是我在调试某ARK时想到的,这个ARK的作者说他们会恢复函数的inline hook然后才去调用(大面积的恢复,甚至是整个文件的恢复),于是我就用调试器在该函数上下断点,结果自然是没有断下了,因为下的 (0xcc)断点被恢复了。于是就索性下了个硬件断点,这下就断住了,然后呢就想到了拿这个东西来HOOK。然后就去网上搜资料,发现不少人还是稍微提到过这个方法的,包括 vxk,xikug,都说过。
上一页 1 2