|
// 测试环境是 xp
#include<ntddk.h>
#include<windef.h>
extern LONG KeServiceDescriptorTable;//导出函数
#pragma pack(1)
typedef struct _JMPDATE //定义一个结构体,该结构体2个成员变量用来保存数据,
{
BYTE E9;
LONG JMPDDA;
}JMPDATE,*PJMPDATE;
#pragma pack()
JMPDATE POld;//该全局成员在24.25行中被调用 用来恢复被hook的函数。NTSTATUS DriverEntry中被写入参数
PJMPDATE PCurrent;
//-----------------------------------------------卸载例程
void UnLoadDriver(PDRIVER_OBJECT Driver)
{
KdPrint(("Unload Driver Success"));
__asm//去掉页面保护
{
cli//禁止中断发生,该指令只能在内核模式下执行,不可以在用户模式下,而且在内核模式下执行时
//应该尽可能快的恢复中断,因为的cli会禁用硬件中断,长是假的禁止中高端会影响其他的动作执行比如鼠标移动,系统将变得不稳定,在寄存器中
//中断标志清0的情况先可以使用int xx的形式软中断
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
PCurrent->E9 = POld.E9;//恢复数据 该数据在NTSTATUS DriverEntry(PDRIVER_OBJECT Dirver, PUNICODE_STRING str)被写入
PCurrent->JMPDDA = POld.JMPDDA;
__asm//恢复保护
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti//允许中断发生 --cli指令后需要有与其配对的sti指令,否则计算机--最常见的反应就是崩溃
}
}
//------------------------------------------
ULONG GetOldSSDTAddress()//原始地址
{
UNICODE_STRING OldNtOpenProcess;
ULONG OldAddress;
RtlInitUnicodeString(&OldNtOpenProcess, L"NtOpenProcess");
// PVOID MmGetSystemRoutineAddress 返回指向‎‎系统程序名称‎‎指定的函数的指针
//参数1指定要解析的系统例程的名称 ‎如果可以解析函数名称,例程将返回指向函数的指针。否则,例程返回 ‎NULL.
OldAddress = (ULONG)MmGetSystemRoutineAddress(&OldNtOpenProcess);
KdPrint(("Get NtOpenProcessFuntionAddress=%x", OldAddress));
return OldAddress;
}
//---------------------------------------------------------
ULONG GetCurrentSSDTAddress()//获取当前的函数地址
{
ULONG SSDTOpenProcess;
__asm
{
push ebx
push eax
mov ebx,KeServiceDescriptorTable
mov ebx, [ebx]
mov eax,0x7a//16进制的7a刚好是NtOpenProcess进程的pid
imul eax,eax,4//这个是地址的偏移
add ebx,eax
mov ebx, [ebx]
mov SSDTOpenProcess,ebx
pop eax
pop ebx
}
KdPrint(("Read SSDTAddress%x", SSDTOpenProcess));
return SSDTOpenProcess;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT Dirver, PUNICODE_STRING str)
{
ULONG Current, Old;
JMPDATE jmpdate;
Current = GetCurrentSSDTAddress();
Old = GetOldSSDTAddress();
if (Current!=Old)
{
KdPrint(("Funtion hook Now Rewrite Funtion"));
PCurrent = (PJMPDATE)(Current);
POld.E9 = PCurrent->E9;//将当前获取到的数据写入
POld.JMPDDA = PCurrent->JMPDDA;//写入数据
jmpdate.E9 = 0xe9;//e9等于jmp 5个字节的机器码
jmpdate.JMPDDA = Old - Current - 5;//原始地址减去当前的地址-5在写入
KdPrint(("Write In Date%x", jmpdate.JMPDDA));
__asm//去掉页面保护
{
cli//禁止中断
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
PCurrent->E9 = jmpdate.E9;//这里的写入数据是我们在jmpdate.E9 = 0xe9;写入的
PCurrent->JMPDDA = jmpdate.JMPDDA;//这里的数据是jmpdate.JMPDDA = Old - Current - 5; 写入的
__asm//恢复保护
{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti//恢复中断
}
}
//GetOldSSDTAddress();
//GetCurrentSSDTAddress();
Dirver->DriverUnload = UnLoadDriver;
return STATUS_SUCCESS;
}
|
评分
-
查看全部评分
上一篇: deepin系统下C++编程系列(科普,非精通)3.2wxWidgets 2下一篇: deepin系统下C++编程系列(科普,非精通)4.1codeblocks界面设计方式1
|