反調試——Windows異常-SEH


反調試——Windows異常-SEH

概念:

SEH:Structured Exception Handling

SEH是Windows默認的異常處理機制

如何使用

在代碼中使用

__try


__except()//結構類型的語句

__except()小括號里面填寫表達式,表達式為真的時候執行里面的內容

__try里面包含的是可能觸發異常的語句,except里面包含的是出現了異常后執行的操作。

__except()括號中表達式的取值范圍:
1:處理異常
0:不處理異常交給下一個異常節點去處理
-1:繼續執行也就是繼續EIP處理執行,但是這里又有異常,所以這里就會一直卡在這里

 

例子:

int main()
{
__try
{
cout<<"hello,world"<<endl;
}
__except(1)
{
cout<<"異常"<<endl;
}
return 0;
}

異常的作用

1 便於查找錯誤

2 可以用在反調試里面

異常處理機制

當我們在非調試狀態下運行一個程序,程序如果觸發了異常,會先判斷是否有異常處理器,如果存在則跳轉到異常處理函數去執行,如果不存在則退出程序

如果程序處於被調試狀態,觸發異常時,操作系統會先把異常拋給調試進程,也就是讓調試器來處理異常。可以看到的現象就是觸發了異常后,程序會暫停下來,也就是斷下來,也就是斷點的原理。當異常拋給調試器后,調試器可以選擇:

1 修改觸發異常的代碼繼續執行(程序會停在觸發異常的代碼處,導致異常的代碼無法執行)

2 忽略異常交給SEH執行

也就是說Windows發生異常后的處理順序為:1、調試器處理。2、SEH處理 3、崩潰

剖析SEH

SEH結構:

typedef struct _EXCEPTION_REGISTRATION_RECORD {
  struct _EXCEPTION_REGISTRATION_RECORD *Next;
  PEXCEPTION_ROUTINE Handler;//異常處理器,異常處理函數
} EXCEPTION_REGISTRATION_RECORD;

SEH在程序中實際上是以鏈表形式存在,每一個next都指向下一個SEH,這個鏈表也叫SEH鏈(如圖):

 

 

每次添加一個異常就會添加該異常到異常鏈的頭結點的位置

觀察SEH是如何生成和使用的

生成兩個程序觀察,兩個程序的區別就是一個有異常SEH,一個沒有

//有異常的程序代碼
#include<Windows.h>
#include<iostream>
int main()
{
__try
{
char* str = NULL;
str[0] = 'a';
}
__except(1)
{
printf("觸發異常了\n");
}
printf("Sna1lGo\n");
return 0;
}

 

//沒有異常的程序代碼
#include<Windows.h>
#include<iostream>
int main()
{
char* str = NULL;
str[0] = 'a';
printf("Sna1lGo\n");
return 0;
}

分別生成后,都用od打開調試比對

 

 

然后都進入main函數

 

 

重點查看SEH的代碼:

 

 

這四條指令就是SEH的關鍵代碼,這一系列操作相當於創建了一個異常的結構體,然后添加到異常鏈的表頭里面。

分析為什么是這樣:

首先,大概畫一個堆棧圖:

 

 

先存進來了一個0x01293609,然后調用了fs:[0]這個東西,這個東西有點眼熟之前的TEP-PEB查找核心模塊的時候有用過,但是這里,可以將fs:[0]直接理解為SEH鏈的表頭。

這里取出來fs:[0]給eax后又把eax入棧,然后將fs:[0]賦值為esp

 

 

可以理解為在棧中創建了一個SEH變量,然后第一個字段存放了函數地址也就是0x01293690,next字段指向了fs:[0]也就是SEH鏈的第一個節點,然后再把fs:[0]的值修改為該節點的首地址,也就是讓fs:[0]指向新的節點。(可能你的代碼有點不一樣,但是稍微分析下,對於異常處理這里也是一樣的)

下面進入異常處理函數的地址查看(這里是0x01293690)

 

 

然后再運行會暫停下來,因為出現了異常,異常優先給調試器處理,但是調試器也是可以選擇處理異常的:

在od的選項中選擇調試選項,再選擇異常:

 

 

就可以設置要捕獲的異常類型了,選擇忽略掉一些異常后再遇到就不會中斷下來了。

也可以選擇插件的StrongOD:

 

 

在取消掉Skip Some Exceptions之后,OD就會捕獲所有異常了

SEH鏈存放的位置

 

經過上面的分析可以知道了,SEH存放的位置在fs:[0]這里

操作系統如何使用SEH

創建異常后,操作系統會自動把異常添加到頭結點,然后把頭指針指向新的異常節點

 

總結:

Windows中有一個機制叫異常處理機制,當出現異常的時候操作系統會先把異常拋給調試器並停止在該指令位置,如果沒有調試器就會拋給SEH來處理,SEH實現的原理是內部是一個SEH鏈表包含了一系列異常處理函數,當有異常類添加進來的時候操作系統會把異常添加到SEH鏈表里面,然后當異常出現的時候遍歷異常類看看有沒有對應的異常處理,如果該異常沒有異常處理則直接程序崩潰。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM