A、实例演示
B、替换IDT处理函数
D、IDT HOOK 代码书写
D、测试效果
课时:36分 断网
//-----------全局变量--------------------------------
ULONG int3proc_addr; //用来存放int 3处理函数地址
ULONG jmpaddr_int3proc_9; //用来存放intproc+9处理函数地址
//-----------全局变量 定义结束-----------------------
1、ULONG ReadIdtBase(ULONG CPUNUM)
2、void __declspec(naked) myInt3Proc()
3、ULONG HookInt3Proc()
4、void __declspec(naked) int3UnHookcode()
{
804dfaa1 6a00 push 0
804dfaa3 66c74424020000 mov word ptr [esp+2],0
}
5、ULONG UnHookInt3Proc()
===================================================
笔记:
本节课实战保护记事本,如果发现OD调试则蓝屏,哇好猛啊!
原理在上节课已经讲清楚了.首先是替换IDT函数,分成 5个步骤:1取得基址,2.处理断点,3进行HOOK,4保存原有代码,5卸载恢复
#include <ntddk.h>
#pragma pack(push)
#pragma pack(1) //
typedef struct _IDTR //IDT基址
{
USHORT limit; //范围占位
ULONG base; //基地址占位_IDT_ENTRY类型指针
}IDTR,*PIDTR;
typedef struct _IDT_ENTRY
{
USHORT offset_low; //中断处理函数地址低位
USHORT selector;
UCHAR reserved;
UCHAR type:4;
UCHAR always0:1;
UCHAR dpl:2;
UCHAR present:1;
USHORT offset_high;//中断处理函数地址低位
}IDT_ENTRY,*PIDT_ENTRY;
#pragma pack(pop) //#pragma pack(pop)
//-----------全局变量--------------------------------
ULONG int3proc_addr; //用来存放int 3处理函数地址
ULONG jmpaddr_int3proc_9; //用来存放intproc+9处理函数地址
//-----------全局变量定义结束-----------------------
#pragma PAGECODE
ULONG ReadIdtBase(ULONG CPUNUM) //1-取得基址
{
IDTR idtr;//获取表基址
PIDT_ENTRY Aidt;
KdPrint(("IDT_ENTRY size=%d \n",sizeof(IDT_ENTRY)));
__asm sidt idtr;//获取表基址信息
KdPrint(("IDT BASE=%x \n",idtr.base));
Aidt=PIDT_ENTRY(idtr.base);
return idtr.base;
}
void __declspec(naked) int3UnHookcode() //4-保存原有代码
{
__asm
{
push 0
mov word ptr [esp+2],0
}
}
#pragma PAGECODE
void __declspec(naked) myInt3Proc() //2-处理断点
{
__asm
{
pushad
pushfd
}
KdPrint(("\n entry my Int3Proc \n"));
//在这里添加自己的条件过滤代码
//获取进程上下文
PEPROCESS EP;
EP=PsGetCurrentProcess();
// (PTSTR)((ULONG)EP+0x174)是否等于需要反断点的进程
if (strcmp((PTSTR)((ULONG)EP+0x174),"notepad.exe")==0)
{
//需要保护的进程直接蓝屏
KdPrint(("\n 蓝屏蓝屏蓝屏\n"));
__asm retn 100;
}
__asm
{
popfd
popad
}
__asm
{
push 0
mov word ptr [esp+2], 0
//前条需要恢复的指令占字节
jmp jmpaddr_int3proc_9
}
}
#pragma PAGECODE
ULONG HookInt3Proc() //3.HOOK处理
{
ULONG status=1;
PIDT_ENTRY Pidt_info=(PIDT_ENTRY)ReadIdtBase(0);
ULONG jmpaddr;
Pidt_info+=3;//转到IDT 数组里边存放着int 3 处理函数地址
//Pidt_info=Pidt_info+sizeof(Pidt_info)*3;
//begin计算出int3处理函数地址
int3proc_addr=Pidt_info->offset_high<<16;//makelong 0x804d0000 高字节存放
//MAKELONG(Pidt_info->offset_high,Pidt_info->offset_Slow) //0xfaa1 =804dfaa1
int3proc_addr=int3proc_addr+Pidt_info->offset_low; //合并高低字节
KdPrint (("\n int proc addr=%x \n",int3proc_addr));
//end;
//begin inline hook int3Proc write
// E9+jmp地址//jmp地址=myInt3Proc-int3proc_addr-5;
jmpaddr=ULONG(&myInt3Proc)-int3proc_addr-5;
jmpaddr_int3proc_9=int3proc_addr+9;
__asm //去掉页面保护
{
cli
mov eax,cr0
and eax,not 10000h //and eax,0FFFEFFFFh
mov cr0,eax
}
__asm //用硬编码写入跳转
{
push ebx
push eax
mov ebx,int3proc_addr
mov byte ptr ds:[ebx],0xE9
mov eax,jmpaddr
mov dword ptr ds:[ebx+1],eax
pop eax
pop ebx
}
//end;inline hook int3proc write
__asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
return status;
}
#pragma PAGECODE
ULONG UnHookInt3Proc() //5.卸载还原
{
ULONG status=1;
KdPrint(("\n 卸载Idt Hook \n"));
__asm //去掉页面保护
{
cli
mov eax,cr0
and eax,not 10000h //and eax,0FFFEFFFFh
mov cr0,eax
}
__asm
{
push ebx
push eax
push ecx
mov ebx,int3proc_addr //0x804dfaa1
lea ecx,int3UnHookcode
//一共9个字节分三次写入
mov eax,[ecx+0]
mov dword ptr ds:[ebx],eax //写入4字节
mov eax,[ecx+4]
mov dword ptr ds:[ebx+4],eax //写入4字节
mov eax,[ecx+8]
mov byte ptr ds:[ebx+8],al //写入1字节
pop ecx
pop eax
pop ebx
}
__asm
{
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
//end;inline hook int3proc write
return status;
}
老师对整个代码进行详解,又在WINDBG里查看卸载过程,一共要恢复9个字节的代码,分3次写回.又将教程中的代码修改一下,最后在虚拟机里加载notepad.exe程序则蓝屏死机,再修改一下代码当检查到调试器时则马上蓝屏…太狠了 |