INLINE HOOK过简单驱动保护的理论知识和大概思路、、
这里的简单驱动保护就是 简单的 HOOK 掉内核API的现象、、、 找到被HOOK的函数的当前地址在此地址处先修改页面保护属性然后写入5个字节、5个字节就是一个简单的JMP指令、 001 JMP 002 这样我们就会跳到 001 (在此地址写入JMP指令)+ 就是说如果你要跳回NtOpenProcess的原地址、 就应该向被HOOK后的地址处写入这样的指令 JMP 不是很乱思路清晰一些就明白了、、
这里有一个修改页面保护属性的过程、、这里有以下几种方法、、
1 修改注册表相应的键值这样改、 HKLM\SYSTEM\CurrentControlset\Control\SessionManger\MemoryManagement\ EnforceWriteProtection=0 与 HKLM\SYSTEM\CurrentControlset\Control\SessionManger\MemoryManagement\ DisablePagingExecutive=1 2 一个寄存器cr0,32位寄存器、 它的第17位(WP位)如果为1、表示开启页面保护0则是去掉页面保护、 __asm //去掉页保护 { Cli //表示将处理器标志寄存器的中断标志位清0,不允许中断 mov eax,cr0 and eax,not 10000h //and mov cr0,eax
}
__asm //恢复页保护 { mov eax,cr0 or eax,10000h //or mov cr0,eax sti } 3通过内核API函数Memory
现在说一下写入JMP指令注意的知识点、、、 1 汇编写入 2 指针写入 将其定义成一个结构体如下 typedef struct _JMPCODE { BYTE Jmp_Code; ULONG Jmp_Addr; }JMPCODE,*PJMPCODE; (这里就需要 修改对齐方式 #pragma 对齐标志改为1 本来是4、如果是4偏移就要加8、、本来我们是加5的、、 部分代码如下 PJMPCODE Real_Jmp;//保存写入的JMP信息 JMPCODE Save_Jmp;//保护改成之前的指令 Cur_ADDR = GetSSDT_Cur_ADDR();//获取当前的SSDT中函数的地址 Old_ADDR = GetSSDT_Old_ADDR(); //获取函数原地址
if (Cur_ADDR != Old_ADDR) //说明被HOOK了 { Real_Jmp = (PJMPCODE) //下边先保存一下要改写的地址处的内容、用于在Unload驱动的的时候恢复它、、、 Save_Jmp. Jmp_Code = Real_Jmp Save_Jmp. Jmp_Addr = Real_Jmp
__asm //去掉页保护 { Cli //表示将处理器标志寄存器的中断标志位清0,不允许中断 mov eax,cr0 and eax,not 10000h //and mov cr0,eax
} Real_Jmp-> Jmp_Code =E9; Real_Jmp-> Jmp_Addr = Old_ADDR - Cur_ADDR -5; //这两条代码就是INLINE
__asm //恢复页保护 { mov eax,cr0 or eax,10000h mov cr0,eax sti } } 在Unload里恢复如下也需要更改页面保护、、 然后反写之前保护时的语句即可、、 Real_Jmp-> Jmp_Code = Save_Jmp. Jmp_Code; Real_Jmp-> Jmp_Addr = Save_Jmp. Jmp_Addr; //恢复原地址处的指令、、、
思路大致这样、、不是很难理解、、 |