不久前寫的一個(gè)小例子
利用硬件斷點(diǎn)異常的鉤子方式
截獲到異常后,轉(zhuǎn)到異常處理程序中處理
流程(1) (2) (3)代表執(zhí)行步驟
code:---------------------------------------------
#include <windows.h>
//消息輸出
void WINAPI MsgXXX(DWORD id)
{
char szid[100];
wsprintf(szid,"錯(cuò)誤碼:%08Xh",id);
::MessageBox(NULL,szid,"XXX",0);
}
int main()
{
__asm
{
?? push offset perThread_Handler //異常處理程序入口???????? (1)
?? push fs:[0]
?? mov fs:[0],esp //修改異常處理
?? xor eax,eax
?? mov eax,[eax] //這里故意制造一個(gè)內(nèi)存違規(guī)異常 讀0?? 異常碼 0xC0000005?????? (2)
?? mov eax,eax?? //寫幾條無用指令留點(diǎn)空隙 便于調(diào)試
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
//異常處理程序
perThread_Handler:
?? push ebp?????????????????????????????? (3)從2出現(xiàn)了內(nèi)存異常 直接轉(zhuǎn)到異常處理程序?? & (10)下面的硬件異常同樣會(huì)到這里
?? mov ebp,esp
?? push ecx
?? mov ecx,dword ptr[ebp+08h] //獲取錯(cuò)誤碼指針
?? mov ecx,dword ptr[ecx]?? //獲取錯(cuò)誤碼
?? cmp ecx,0C0000005h??? //比較是否為制造的內(nèi)存錯(cuò)誤
?? je memError????????????????????????????????????????????????????????????????? (4)確定為內(nèi)存異常 跳到memError
?? cmp ecx,080000004h??? //比較是否為硬件斷點(diǎn)
?? je memDRx
?? mov eax,1????? //都不是 那就是程序自身異常 交由程序自身異常處理程序處理
?? jmp End
??
//如果是制造的那個(gè)內(nèi)存錯(cuò)誤
memError:????????????????????????????????????? (5)從4跳到了這里 這里設(shè)置硬件斷點(diǎn)
?? push ecx
?? call MsgXXX
?? mov eax,dword ptr [ebp+10h] //獲取線程寄存器結(jié)構(gòu)
?? mov ecx,offset xxooxx?? //模擬一個(gè)硬件斷點(diǎn)地址?????
?? mov dword ptr [eax+04h],ecx //把斷點(diǎn)地址放入到DR0
?? mov ecx,101h???? //DR7參數(shù)
?? mov dword ptr [eax+18h],ecx //把參數(shù)放到DR7
?? mov ecx,offset NewAddr?? //異常處理程序結(jié)束后要返回的地址
?? mov dword ptr [eax+0B8h],ecx//這里把EIP修改成新地址
?? mov eax,0????? //返回0 表示異常處理程序處理完后繼續(xù)處理
?? jmp End???????????? (6)
//硬件斷點(diǎn)異常
memDRx:
?? push ecx
?? call MsgXXX
?? mov eax,dword ptr [ebp+10h] //獲取結(jié)構(gòu)
?? mov ecx,offset NewAddr?? //設(shè)置新地址
?? mov dword ptr [eax+0B8h],ecx//修改EIP
?? mov eax,0
?? jmp End
End:
?? pop ecx?????? (7)這里ret后 會(huì)到NewAddr 地址處 因?yàn)樵O(shè)置了新EIP是這里
?? pop ebp
?? ret
//新地址 設(shè)置完異常后到這里
NewAddr:???????? (8) 這里繼續(xù)執(zhí)行
?? mov eax,eax
?? push 1
?? call MsgXXX
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
?? mov eax,eax
//硬件異常模擬地址 到這里會(huì)出現(xiàn)硬件單步異常
xxooxx:???????????? (9)到這里 會(huì)觸發(fā)硬件斷點(diǎn)異常 會(huì)跳回到 異常處理程序
?? mov ebx,ebx
?? mov ebx,ebx
?? mov ebx,ebx
?? mov ebx,ebx
?? mov ebx,ebx
?? mov ebx,ebx???? (.?)所以永遠(yuǎn)到不了這里
?? mov ebx,ebx
?? mov ebx,ebx
?? mov ebx,ebx
}
return 0;
}
看上去邏輯很亂 但是調(diào)試一下就真相大白了
同樣可以做很猥瑣的事