加密與解密二版菜鳥學習筆記(2) - SEH 結構化異常處理

標 題: 【原創】加密與解密二版菜鳥學習筆記(2) - SEH 結構化異常處理
作 者: ytcswb
時 間: 2005-02-01,16:40:24
鏈 接: http://bbs.pediy.com/showthread.php?t=10651

看學加密與解密二版學習筆記(2) - SEH 結構化異常處理

[ 工 具 ] flyod1.10

[ 目 的 ] 學習SEH的手法,另書中是用SoftICE調試的,看起來不習慣.根據原文內容重新整理一下,便於和我一樣的菜鳥們一起學習.
          今天下決心,好好學習,這是就算是個開始吧!感覺學明白的確很不容易!

[ 注 釋 ] ?--爲不能理解的地方,請大俠們指點一下.學習過程中,有理解錯誤的地方,肯請大俠們多多指教.

[練習對象] 加密與加密二版第10章,光盤配套的練習軟件:seh.exe seh2.exe

[ writer ]  ytcswb  2005.2.1  感謝看學及論壇的大俠們爲我們提供這麼好的學習資料。

1.例子seh.exe學習:
00401000 > $  8D4424 F8     lea eax,dword ptr ss:[esp-8] //程序入口!根據下面的代碼分析,這裏顯然可以
                                                         //理解爲開闢8字節的空間,並把棧頂指針保存到eax
                                                         //相當於sub esp,8 ; lea eax,dword ptr ss:[esp]
00401004   .  64:8705 00000>xchg dword ptr fs:[0],eax    //記住fs[0]永遠是指向當前err結構的指針,
                                                         //執行完成後,fs[0]指向棧頂,準備在堆棧中構造1個err結構
                                                         //eax等於原fs[0],即指向原來的err結構的指針,即那個err結構的地址
0040100B   .  BB 2E104000   mov ebx,Seh.0040102E         //地址40102e-->ebx,建議在此地址上設斷點,才能正常跟蹤入seh代碼中
00401010   .  53            push ebx                     //壓入堆棧,即當前err結構的handler成員,當前異常處理代碼的入口地址
00401011   .  50            push eax                     //壓入原fs[0],即當前err結構的prev成員,即下一個err結構的地址
此時堆棧:
0012FFBC   0012FFE0  指針到下一個 SEH 記錄 //0012FFE0是個指針,看看就知道指向下一個err結構,數值上等於下一個err結構的地址
0012FFC0   0040102E  SE 句柄               //建立了1個當前的err結構
0012FFE0   FFFFFFFF  SEH 鏈尾部 
0012FFE4   77E74809  SE 句柄

err結構的定義[在Essup.INC源文件中定義的---VC++ CRT(CRT含義:C++RunTime library)]:
_EXCEPTION _REGISTERATION stru
   prev    dd ? //指向下一個err結構的指針,數值上等於下一個err結構的首地址(在堆棧中)
   handler dd ? //指向異常處理代碼的指針,數值上等於異常處理代碼的入口地址即首地址
_EXCEPTION _REGISTERATION ends

00401012   .  BE 00000000   mov esi,0                    //簡單的賦值語句
00401017   .  8B06          mov eax,dword ptr ds:[esi]   //讀取線性地址0,產生異常
                                                         //執行後,windows檢查到異常,執行線程馬上被中段,從用戶模式轉到內核模式
                                                         //控制權交到操作系統的異常調試程序(exception dispatcher),由它負責找到
                                                         //處理這個異常的方法,即所有應用程序的異常最終都是由windwos來處理的,
                                                         //同一個版本的windows有固定的異常處理代碼.
//如果你把這句nop掉了,也就等於去除了異常.會接着執行到下面的代碼,並顯示"SEH Fail"!
             
00401019   .  6A 00         push 0                                   ; /Style = MB_OK|MB_APPLMODAL
0040101B   .  68 00304000   push Seh.00403000                        ; |Title = "OK"
00401020   .  68 10304000   push Seh.00403010                        ; |Text = "SEH Fail"
00401025   .  6A 00         push 0                                   ; |hOwner = NULL
00401027   .  E8 1C000000   call <jmp.&USER32.MessageBoxA>           ; \MessageBoxA
0040102C   .  EB 13         jmp short Seh.00401041
0040102E   .  6A 00         push 0                                   ; /Style = MB_OK|MB_APPLMODAL
00401030   .  68 00304000   push Seh.00403000                        ; |Title = "OK"
00401035   .  68 03304000   push Seh.00403003                        ; |Text = "SEH Succeed "
0040103A   .  6A 00         push 0                                   ; |hOwner = NULL
0040103C   .  E8 07000000   call <jmp.&USER32.MessageBoxA>           ; \MessageBoxA
00401041   >  6A 00         push 0                                   ; /ExitCode = 0
00401043   .  E8 06000000   call <jmp.&KERNEL32.ExitProcess>         ; \ExitProcess
00401048   $- FF25 08204000 jmp dword ptr ds:[<&USER32.MessageBoxA>] ;  USER32.MessageBoxA
0040104E   .- FF25 00204000 jmp dword ptr ds:[<&KERNEL32.ExitProcess>;  kernel32.ExitProcess
00401054      00            db 00
00401055      00            db 00
---------------------------------------------------------------------------------------------------
00401017   .  8B06          mov eax,dword ptr ds:[esi]   
//讀取線性地址0,產生異常
//執行完這1條指令,od的狀態行可以看到,產生了什麼異常.狀態行的內容如下:
//訪問違反:讀取[00000000],使用shift+F7/F8/F9鍵跳過異常以繼續執行程序.
//windows檢測到了這個異常,就會向堆棧壓入3個結構.壓入順序爲 EXCEPTION_RECORD,EXCEPTION_CONTEXT,EXCEPTION_POINTERS
//EXCEPTION_POINTERS結構就在棧頂,其定義如下:

typedef strut_EXCEPTION_POINTERS{ 
+0 pEXCEPTION_RECORD ExceptionRecord DWORD ? //指針,指向EXCEPTION_RECORD結構,即EXCEPTION_RECORD的首地址
+4 pCONTEXT ContextRecord            DWORD ? //指針,指向EXCEPTION_CONTEXT結構,即EXCEPTION_CONTEXT的首地址
}_EXCEPTION_POINTERS ends

在看看EXCEPTION_RECORD結構:
EXCEPTION_RECORD struct{      //共6個成員
+0  DWORD ExceptionCode       //異常代碼,定義了產生異常的原因
+4  DWORD ExceptionFlags      //異常標誌 ?
+8  struct EXCEPTION_RECORD   //指針,指向另一個EXCEPTION_RECORD結構
+C  DVOID ExceptionAddress    //異常發生的地址
+10 DWORD NumberParameters    //與異常聯繫的參數個數(0~15)一般=0 ?
+14 ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]   //異常信息 ?
}EXCEPTION_RECORD ends

//執行完401017指令後,我們在od的代碼窗口的看到代碼如下:

77FB4DAF >  8B4C24 04       mov ecx,dword ptr ss:[esp+4]
77FB4DB3    8B1C24          mov ebx,dword ptr ss:[esp] //來到了ntdll領空,即系統領空
  {
  //馬上看看堆棧:
  0012FCCC   0012FCD4 -| //指針,指向EXCEPTION_RECORD結構,即EXCEPTION_RECORD的首地址-----\這就是EXCEPTION_POINTERS
  0012FCD0   0012FCF0 -| //指針,指向EXCEPTION_CONTEXT結構,即EXCEPTION_CONTEXT的首地址---\
  0012FCD4   C0000005---------------\1--異常代碼.這裏開始就是EXCEPTION_RECORD結構
  0012FCD8   00000000               \2--異常標誌=0
  0012FCDC   00000000               \3--指針,指向另一個EXCEPTION_RECORD結構,這裏=0 
                                               沒有另一個EXCEPTION_RECORD結構,爲NULL指針.
  0012FCE0   00401017  Seh.00401017 \4--異常發生的地址,這就是發生異常的那條指令的地址.
  0012FCE4   00000002               \5--與異常聯繫的參數個數=2 ?
  0012FCE8   00000000               \6--異常信息 ?
  0012FCEC   00000000---------------\
  0012FCF0   0001003F---------------\這裏開始就是EXCEPTION_CONTEXT結構,ContextFlags
  0012FCF4   00000000               \Dr0  
  0012FCF8   00000000               \Dr1 
  0012FCFC   00000000               \Dr2
  0012FD00   00000000               \Dr3 
  0012FD04   0000A000               \Dr6
  0012FD08   00000000               \Dr7
  
  我們重點看看0012FCF0 +B8=12FDA8
  0012FDA4   0012FFF0
  0012FDA8   00401017  Seh.00401017 \異常發生的地址,這就是發生異常的那條指令的地址.
  0012FDAC   0000001B
  }
繼續跟蹤:
77FB4DB6    51              push ecx //指針,指向EXCEPTION_CONTEXT結構
77FB4DB7    53              push ebx //指針,指向EXCEPTION_RECORD結構
77FB4DB8    E8 ACBDFAFF     call ntdll.77F60B69 //如果f8過,會出現SEH succeed 提示窗口,即執行了程序自己的異常代碼,
                                                //爲了看系統是如何處理的,我們f7進入
77FB4DBD    0AC0            or al,al
77FB4DBF    74 0C           je short ntdll.77FB4DCD
77FB4DC1    5B              pop ebx
77FB4DC2    59              pop ecx
77FB4DC3    6A 00           push 0
77FB4DC5    51              push ecx
77FB4DC6    E8 480BFCFF     call ntdll.ZwContinue
77FB4DCB    EB 0B           jmp short ntdll.77FB4DD8
77FB4DCD    5B              pop ebx
77FB4DCE    59              pop ecx
77FB4DCF    6A 00           push 0
77FB4DD1    51              push ecx
77FB4DD2    53              push ebx
77FB4DD3    E8 F213FCFF     call ntdll.ZwRaiseException
77FB4DD8    83C4 EC         add esp,-14
77FB4DDB    890424          mov dword ptr ss:[esp],eax
77FB4DDE    C74424 04 01000>mov dword ptr ss:[esp+4],1
77FB4DE6    895C24 08       mov dword ptr ss:[esp+8],ebx
77FB4DEA    C74424 10 00000>mov dword ptr ss:[esp+10],0
77FB4DF2    54              push esp
77FB4DF3    E8 AFC2F9FF     call ntdll.RtlRaiseException
77FB4DF8    C2 0800         retn 8

繼續跟到這段代碼裏:
77F79B7E    55              push ebp
77F79B7F    8BEC            mov ebp,esp
77F79B81    FF75 0C         push dword ptr ss:[ebp+C]
77F79B84    52              push edx
77F79B85    64:FF35 0000000>push dword ptr fs:[0]
77F79B8C    64:8925 0000000>mov dword ptr fs:[0],esp
  {
  //堆棧建立了1個err結構
  0012FC04   0012FFBC  指針到下一個 SEH 記錄 //enter鍵看看
  0012FC08   77F79BB8  SE 句柄
  0012FFBC   0012FFE0  指針到下一個 SEH 記錄
  0012FFC0   0040102E  SE 句柄 // 熟悉這個地址吧
  0012FFE0   FFFFFFFF  SEH 鏈尾部
  0012FFE4   77E74809  SE 句柄
  }
77F79B93    FF75 14         push dword ptr ss:[ebp+14]
77F79B96    FF75 10         push dword ptr ss:[ebp+10]
77F79B99    FF75 0C         push dword ptr ss:[ebp+C]
77F79B9C    FF75 08         push dword ptr ss:[ebp+8]
77F79B9F    8B4D 18         mov ecx,dword ptr ss:[ebp+18]
  {
  //此時我們馬上看看堆棧:
  0012FBF4   0012FCD4 //指針,指向EXCEPTION_RECORD結構,即EXCEPTION_RECORD的首地址  -----回調函數的參數1
  0012FBF8   0012FFBC //指向err結構.可以看看上面我們截取的SEH鏈表                 -----回調函數的參數2
  0012FBFC   0012FCF0 //指針,指向EXCEPTION_CONTEXT結構,即EXCEPTION_CONTEXT的首地址-----回調函數的參數3
  0012FC00   0012FCAC //參數4  _lpDispatchrContext ? 最先被壓入堆棧.
  0012FC04   0012FFBC  指針到下一個 SEH 記錄
  0012FC08   77F79BB8  SE 句柄
  0012FC0C   0012FFBC
  }
77F79BA2    FFD1            call ecx                      //Seh.0040102E到這裏執行,就是程序的自己的異常處理代碼,f7
                                                          //這就是異常處理回調函數,其參數含義請往下看.
  {
  0040102C   . /EB 13         jmp short Seh.00401041
  0040102E   . |6A 00         push 0                                   ; /Style = MB_OK|MB_APPLMODAL
  00401030   . |68 00304000   push Seh.00403000                        ; |Title = "OK"
  00401035   . |68 03304000   push Seh.00403003                        ; |Text = "SEH Succeed "
  0040103A   . |6A 00         push 0                                   ; |hOwner = NULL
  0040103C   . |E8 07000000   call <jmp.&USER32.MessageBoxA>           ; \MessageBoxA
  00401041   > \6A 00         push 0                                   ; /ExitCode = 0
  00401043   .  E8 06000000   call <jmp.&KERNEL32.ExitProcess>         ; \ExitProcess
  00401048   $- FF25 08204000 jmp dword ptr ds:[<&USER32.MessageBoxA>] ;  USER32.MessageBoxA
  0040104E   .- FF25 00204000 jmp dword ptr ds:[<&KERNEL32.ExitProcess>;  kernel32.ExitProcess
  }
77F79BA4    64:8B25 0000000>mov esp,dword ptr fs:[0]
77F79BAB    64:8F05 0000000>pop dword ptr fs:[0]
77F79BB2    8BE5            mov esp,ebp
77F79BB4    5D              pop ebp
77F79BB5    C2 1400         retn 14

[總結]

//讀取線性地址0,產生異常
//執行後,windows檢查到異常,執行線程馬上被中段,從用戶模式轉到內核模式
//控制權交到操作系統的異常調試程序(exception dispatcher),由它負責找到
//處理這個異常的方法,即所有應用程序的異常最終都是由windwos來處理的,
//那麼同一個版本的windows就有固定的異常處理代碼.跟蹤seh保護的程序時,以此爲切入點,可以輕而一舉地找到關鍵!

2.例子seh2.exe學習:

00401000 >/$  68 51104000   push seh2.00401051                       ;  SE handler installation發生異常後到這裏執行
                                                                     //看學強調:提前在這個handler設個斷點,否則程序容易跑飛!
                                                                     //只有這樣才能正常跟進seh處理代碼!
00401005  |.  64:FF35 00000>push dword ptr fs:[0]
0040100C  |.  64:8925 00000>mov dword ptr fs:[0],esp                 //構造1個err結構

0012FFBC   0012FFE0  指針到下一個 SEH 記錄 //fs:[0]=esp=0x0012FFBC
0012FFC0   00401051  SE 句柄
0012FFE0   FFFFFFFF  SEH 鏈尾部
0012FFE4   77E74809  SE 句柄

00401013  |.  BE 00000000   mov esi,0
00401018  |.  8B06          mov eax,dword ptr ds:[esi] //產生異常
//這裏實際是故意引發一個異常,爲的就是通過修改CONTEXT,來實現反跟蹤及改變程序流程(設置暗樁嗎?)
0040101A  |.  6A 00         push 0                                   ; /Style = MB_OK|MB_APPLMODAL
0040101C  |.  68 00304000   push seh2.00403000                       ; |Title = "SEH"
00401021  |.  68 0F304000   push seh2.0040300F                       ; |Text = "SEH程序沒有運行"
00401026  |.  6A 00         push 0                                   ; |hOwner = NULL
00401028  |.  E8 57000000   call <jmp.&USER32.MessageBoxA>           ; \MessageBoxA
0040102D  |.  6A 00         push 0                                   ; /Style = MB_OK|MB_APPLMODAL
0040102F  |.  68 00304000   push seh2.00403000                       ; |Title = "SEH"
00401034  |.  68 04304000   push seh2.00403004                       ; |Text = "Hello,SEH!"
00401039  |.  6A 00         push 0                                   ; |hOwner = NULL
0040103B  |.  E8 44000000   call <jmp.&USER32.MessageBoxA>           ; \MessageBoxA
00401040  |.  64:8F05 00000>pop dword ptr fs:[0]
00401047  |.  83C4 04       add esp,4
0040104A  |.  6A 00         push 0                                   ; /ExitCode = 0
0040104C  \.  E8 39000000   call <jmp.&KERNEL32.ExitProcess>         ; \ExitProcess
00401051  /$  55            push ebp                                 ;  Structured exception handler
00401052  |.  8BEC          mov ebp,esp
00401054  |.  53            push ebx
00401055  |.  8B45 10       mov eax,dword ptr ss:[ebp+10]
00401058  |.  8D1D 2D104000 lea ebx,dword ptr ds:[40102D]
0040105E  |.  8998 B8000000 mov dword ptr ds:[eax+B8],ebx
00401064  |.  33DB          xor ebx,ebx
00401066  |.  8958 04       mov dword ptr ds:[eax+4],ebx
00401069  |.  8958 08       mov dword ptr ds:[eax+8],ebx
0040106C  |.  8958 0C       mov dword ptr ds:[eax+C],ebx
0040106F  |.  8958 10       mov dword ptr ds:[eax+10],ebx
00401072  |.  C740 18 55010>mov dword ptr ds:[eax+18],155
00401079  |.  B8 00000000   mov eax,0
0040107E  |.  5B            pop ebx
0040107F  |.  C9            leave
00401080  \.  C2 1000       retn 10
00401083      CC            int3
發生異常,就來到這裏:
看堆棧:
0012FCCC   0012FCD4  //指針,指向EXCEPTION_RECORD結構,即EXCEPTION_RECORD的首地址-----\這就是EXCEPTION_POINTERS
0012FCD0   0012FCF0  //指針,指向EXCEPTION_CONTEXT結構,即EXCEPTION_CONTEXT的首地址---\
0012FCD4   C0000005  ---------------\1--異常代碼.這裏開始就是EXCEPTION_RECORD結構
0012FCD8   00000000
0012FCDC   00000000
0012FCE0   00401018  seh2.00401018  \4--異常發生的地址,這就是發生異常的那條指令的地址.
0012FCE4   00000002
0012FCE8   00000000
0012FCEC   00000000
0012FCF0   0001003F  ---------------\這裏開始就是EXCEPTION_CONTEXT結構,ContextFlags
0012FCF4   00000000 //dr0
0012FCF8   00000000 //dr1
0012FCFC   00000000 //dr2
0012FD00   00000000 //dr3
0012FD04   0000A000 //dr6
0012FD08   00000000 //dr7
0012FD0C   FFFF027F

77FB4DB3    8B1C24          mov ebx,dword ptr ss:[esp]
77FB4DB6    51              push ecx
77FB4DB7    53              push ebx
77FB4DB8    E8 ACBDFAFF     call ntdll.77F60B69 //f7
77FB4DBD    0AC0            or al,al
77FB4DBF    74 0C           je short ntdll.77FB4DCD
77FB4DC1    5B              pop ebx
77FB4DC2    59              pop ecx
77FB4DC3    6A 00           push 0
77FB4DC5    51              push ecx
77FB4DC6    E8 480BFCFF     call ntdll.ZwContinue
77FB4DCB    EB 0B           jmp short ntdll.77FB4DD8
77FB4DCD    5B              pop ebx
77FB4DCE    59              pop ecx
77FB4DCF    6A 00           push 0
77FB4DD1    51              push ecx
77FB4DD2    53              push ebx
77FB4DD3    E8 F213FCFF     call ntdll.ZwRaiseException
77FB4DD8    83C4 EC         add esp,-14
77FB4DDB    890424          mov dword ptr ss:[esp],eax
77FB4DDE    C74424 04 01000>mov dword ptr ss:[esp+4],1
77FB4DE6    895C24 08       mov dword ptr ss:[esp+8],ebx
77FB4DEA    C74424 10 00000>mov dword ptr ss:[esp+10],0
77FB4DF2    54              push esp
77FB4DF3    E8 AFC2F9FF     call ntdll.RtlRaiseException
77FB4DF8    C2 0800         retn 8
77FB4DFB >^ E9 7DBCFAFF     jmp ntdll.77F60A7D

77F79B7E    55              push ebp
77F79B7F    8BEC            mov ebp,esp
77F79B81    FF75 0C         push dword ptr ss:[ebp+C]
77F79B84    52              push edx
77F79B85    64:FF35 0000000>push dword ptr fs:[0]
77F79B8C    64:8925 0000000>mov dword ptr fs:[0],esp
77F79B93    FF75 14         push dword ptr ss:[ebp+14] //參數4  _lpDispatchrContext ?
77F79B96    FF75 10         push dword ptr ss:[ebp+10] //參數3  _lpDContext,指向Context結構
77F79B99    FF75 0C         push dword ptr ss:[ebp+C]  //參數2  _lpSEH ,指向ERR結構
77F79B9C    FF75 08         push dword ptr ss:[ebp+8]  //參數1  _lpExceptionRecord ,指向ExceptionRecord結構
77F79B9F    8B4D 18         mov ecx,dword ptr ss:[ebp+18]
77F79BA2    FFD1            call ecx         ; seh2.00401051 轉到這裏了 f7
                                             //這就是異常處理回調函數,執行當前異常處理代碼即401051處
                                             //注:回調函數都是由windows調用的!
                                             //看學強調: 在此回調函數上設斷點,可以輕易地對付一些加殼的反跟蹤代碼!!!!!
77F79BA4    64:8B25 0000000>mov esp,dword ptr fs:[0] //恢復原來的SEH鏈表
77F79BAB    64:8F05 0000000>pop dword ptr fs:[0]
77F79BB2    8BE5            mov esp,ebp
77F79BB4    5D              pop ebp
77F79BB5    C2 1400         retn 14

00401051  /$  55            push ebp                                 ;  Structured exception handler
00401052  |.  8BEC          mov ebp,esp
00401054  |.  53            push ebx
00401055  |.  8B45 10       mov eax,dword ptr ss:[ebp+10] // eax是CONTEXT結構的指針
00401058  |.  8D1D 2D104000 lea ebx,dword ptr ds:[40102D] //通過修改CONTEXT.EIP,希望到這裏執行!
0040105E  |.  8998 B8000000 mov dword ptr ds:[eax+B8],ebx //修改CONTEXT.EIP,改變程序執行線路,這大概就是利用seh的常用手法!
                                                          //沒改時,是401018即發生異常的指令地址,經過1輪處理又會到這裏執行
                                                          //又產生異常
00401064  |.  33DB          xor ebx,ebx
00401066  |.  8958 04       mov dword ptr ds:[eax+4],ebx //DR0 清零,使斷點失效,這大概也是利用seh的常用手法,實現反跟蹤!
00401069  |.  8958 08       mov dword ptr ds:[eax+8],ebx //DR1
0040106C  |.  8958 0C       mov dword ptr ds:[eax+C],ebx //DR2
0040106F  |.  8958 10       mov dword ptr ds:[eax+10],ebx//DR3
00401072  |.  C740 18 55010>mov dword ptr ds:[eax+18],155 //DR7
00401079  |.  B8 00000000   mov eax,0 //回調處理函數的返回值ExceptionContinueExcetion-->eax
//ExceptionContinueExcetion=0  回調函數返回後,系統將線程環境恢復到_lpContext參數指定的CONTEXT結構並繼續執行.
                               即,表示已經修復,從異常處繼續執行,如果前面沒有修改CONTEXT.EIP的值,就會到401018即異常發生處
                               繼續執行,由於前面修改了CONTEXT.EIP=40102D,所以就轉到40102D處繼續執行了.
//ExceptionContinueExcetion=1  回調函數拒絕處理這個異常,系統將通過err結構的prev指針得到前一個回掉函數的地址並繼續執行它
                               也就是轉到前一個err結構的異常處理代碼處繼續執行.
//ExceptionContinueExcetion=2  回調函數在執行中又發生了異常,即嵌套異常
//ExceptionContinueExcetion=3  發生嵌套的展開操作 ?
0040107E  |.  5B            pop ebx
0040107F  |.  C9            leave
00401080  \.  C2 1000       retn 10

[總結] 
//看學強調: 在此回調函數上設斷點,可以輕易地對付一些加殼的反跟蹤代碼!!!!!
//看學強調: 要提前在err結構的handler地址上設斷點,否則代碼就可能跑飛跟蹤seh的關鍵斷點!!!!
//看學提示: 可修改CONTEXT結構成員,來實現反跟蹤及改變程序流程(設置暗樁嗎?)                                                                  

**************************************************************************************************************


[附錄] 跟蹤到異常處理回調函數的過程:
注: windows xp-sp1平臺.只要是同樣平臺,就可以按下面步驟,來到系統的異常處理回調函數.
    熟悉一下這段代碼,應該有好處,當發生異常時,可以快速找到那個call ecx異常處理回調函數,從而找到程序自己的異常處理代碼。
00401000 >/$  68 51104000   push seh2.00401051 //  SE handler installation
                                               //只有在這個401051上設斷點,才能跟到異常處理代碼(SEH代碼)處.
                                               //即要提前在err結構的handler地址上設斷點,否則代碼就可能跑飛!
                                               //跟蹤seh的關鍵斷點!!!!
00401005  |.  64:FF35 00000>push dword ptr fs:[0]
0040100C  |.  64:8925 00000>mov dword ptr fs:[0],esp
00401013  |.  BE 00000000   mov esi,0
00401018  |.  8B06          mov eax,dword ptr ds:[esi]  //產生異常,來到 代碼[1]
0040101A  |.  6A 00         push 0                                            ; /Style = MB_OK|MB_APPLMODAL
0040101C  |.  68 00304000   push seh2.00403000                                ; |Title = "SEH"
00401021  |.  68 0F304000   push seh2.0040300F                                ; |Text = "SEH程序沒有運行"
00401026  |.  6A 00         push 0                                            ; |hOwner = NULL
00401028  |.  E8 57000000   call <jmp.&USER32.MessageBoxA>                    ; \MessageBoxA
0040102D  |.  6A 00         push 0                                            ; /Style = MB_OK|MB_APPLMODAL
0040102F  |.  68 00304000   push seh2.00403000                                ; |Title = "SEH"
00401034  |.  68 04304000   push seh2.00403004                                ; |Text = "Hello,SEH!"
00401039  |.  6A 00         push 0                                            ; |hOwner = NULL
0040103B  |.  E8 44000000   call <jmp.&USER32.MessageBoxA>                    ; \MessageBoxA
00401040  |.  64:8F05 00000>pop dword ptr fs:[0]
00401047  |.  83C4 04       add esp,4
0040104A  |.  6A 00         push 0                                            ; /ExitCode = 0
0040104C  \.  E8 39000000   call <jmp.&KERNEL32.ExitProcess>                  ; \ExitProcess
00401051  /$  55            push ebp                                          ;  Structured exception handler
00401052  |.  8BEC          mov ebp,esp
00401054  |.  53            push ebx
00401055  |.  8B45 10       mov eax,dword ptr ss:[ebp+10]
00401058  |.  8D1D 2D104000 lea ebx,dword ptr ds:[40102D]
0040105E      8998 B8000000 mov dword ptr ds:[eax+B8],ebx
00401064  |.  33DB          xor ebx,ebx
00401066  |.  8958 04       mov dword ptr ds:[eax+4],ebx
00401069  |.  8958 08       mov dword ptr ds:[eax+8],ebx
0040106C  |.  8958 0C       mov dword ptr ds:[eax+C],ebx
0040106F  |.  8958 10       mov dword ptr ds:[eax+10],ebx
00401072  |.  C740 18 55010>mov dword ptr ds:[eax+18],155
00401079  |.  B8 00000000   mov eax,0
0040107E  |.  5B            pop ebx
0040107F  |.  C9            leave
00401080  \.  C2 1000       retn 10

代碼[1]
77FB4DB3    8B1C24          mov ebx,dword ptr ss:[esp]
77FB4DB6    51              push ecx
77FB4DB7    53              push ebx
77FB4DB8    E8 ACBDFAFF     call ntdll.77F60B69 //F7 進入,來到代碼 [2]
77FB4DBD    0AC0            or al,al
77FB4DBF    74 0C           je short ntdll.77FB4DCD
77FB4DC1    5B              pop ebx
77FB4DC2    59              pop ecx
77FB4DC3    6A 00           push 0
77FB4DC5    51              push ecx
77FB4DC6    E8 480BFCFF     call ntdll.ZwContinue //代碼[5],F7進入,回到代碼[6]
77FB4DCB    EB 0B           jmp short ntdll.77FB4DD8
77FB4DCD    5B              pop ebx
77FB4DCE    59              pop ecx
77FB4DCF    6A 00           push 0
77FB4DD1    51              push ecx
77FB4DD2    53              push ebx
77FB4DD3    E8 F213FCFF     call ntdll.ZwRaiseException
77FB4DD8    83C4 EC         add esp,-14
77FB4DDB    890424          mov dword ptr ss:[esp],eax
77FB4DDE    C74424 04 01000>mov dword ptr ss:[esp+4],1
77FB4DE6    895C24 08       mov dword ptr ss:[esp+8],ebx
77FB4DEA    C74424 10 00000>mov dword ptr ss:[esp+10],0
77FB4DF2    54              push esp
77FB4DF3    E8 AFC2F9FF     call ntdll.RtlRaiseException
77FB4DF8    C2 0800         retn 8
77FB4DFB >^ E9 7DBCFAFF     jmp ntdll.77F60A7D

代碼 [2]
77F60B69    55              push ebp
77F60B6A    8BEC            mov ebp,esp
77F60B6C    83EC 60         sub esp,60
77F60B6F    56              push esi
77F60B70    FF75 0C         push dword ptr ss:[ebp+C]
77F60B73    8B75 08         mov esi,dword ptr ss:[ebp+8]
77F60B76    56              push esi
77F60B77    E8 AA000000     call ntdll.77F60C26
77F60B7C    84C0            test al,al
77F60B7E    0F85 EB6F0200   jnz ntdll.77F87B6F
77F60B84    53              push ebx
77F60B85    57              push edi
77F60B86    8D45 F8         lea eax,dword ptr ss:[ebp-8]
77F60B89    50              push eax
77F60B8A    8D45 FC         lea eax,dword ptr ss:[ebp-4]
77F60B8D    50              push eax
77F60B8E    E8 3C910100     call ntdll.77F79CCF
77F60B93    E8 52910100     call ntdll.77F79CEA
77F60B98    8365 08 00      and dword ptr ss:[ebp+8],0
77F60B9C    8BD8            mov ebx,eax
77F60B9E    83FB FF         cmp ebx,-1
77F60BA1    0F84 4A1C0100   je ntdll.77F727F1
77F60BA7    3B5D FC         cmp ebx,dword ptr ss:[ebp-4]
77F60BAA    0F82 481C0100   jb ntdll.77F727F8
77F60BB0    8D43 08         lea eax,dword ptr ds:[ebx+8]
77F60BB3    3B45 F8         cmp eax,dword ptr ss:[ebp-8]
77F60BB6    0F87 3C1C0100   ja ntdll.77F727F8
77F60BBC    F6C3 03         test bl,3
77F60BBF    0F85 331C0100   jnz ntdll.77F727F8
77F60BC5    8B43 04         mov eax,dword ptr ds:[ebx+4]
77F60BC8    3B45 FC         cmp eax,dword ptr ss:[ebp-4]
77F60BCB    72 09           jb short ntdll.77F60BD6
77F60BCD    3B45 F8         cmp eax,dword ptr ss:[ebp-8]
77F60BD0    0F82 221C0100   jb ntdll.77F727F8
77F60BD6    F605 4A32FC77 8>test byte ptr ds:[77FC324A],80
77F60BDD    0F85 936F0200   jnz ntdll.77F87B76
77F60BE3    FF73 04         push dword ptr ds:[ebx+4]
77F60BE6    8D45 F0         lea eax,dword ptr ss:[ebp-10]
77F60BE9    50              push eax
77F60BEA    FF75 0C         push dword ptr ss:[ebp+C]
77F60BED    53              push ebx
77F60BEE    56              push esi
77F60BEF    E8 528F0100     call ntdll.77F79B46           // F4下,F7進入,來到代碼[3]
77F60BF4    F605 4A32FC77 8>test byte ptr ds:[77FC324A],80
77F60BFB    8BF8            mov edi,eax
77F60BFD    0F85 896F0200   jnz ntdll.77F87B8C
77F60C03    395D 08         cmp dword ptr ss:[ebp+8],ebx
77F60C06    0F84 8E6F0200   je ntdll.77F87B9A
77F60C0C    8BC7            mov eax,edi
77F60C0E    33C9            xor ecx,ecx
77F60C10    2BC1            sub eax,ecx
77F60C12    0F84 3E340100   je ntdll.77F74056
77F60C18    48              dec eax
77F60C19    0F85 886F0200   jnz ntdll.77F87BA7
77F60C1F    8B1B            mov ebx,dword ptr ds:[ebx]
77F60C21  ^ E9 78FFFFFF     jmp ntdll.77F60B9E
77F60C26    55              push ebp
77F60C27    8BEC            mov ebp,esp
77F60C29    51              push ecx
77F60C2A    51              push ecx
77F60C2B    57              push edi
77F60C2C    BF 1032FC77     mov edi,ntdll.77FC3210
77F60C31    393D 1032FC77   cmp dword ptr ds:[77FC3210],edi
77F60C37    0F85 48E80100   jnz ntdll.77F7F485
77F60C3D    32C0            xor al,al
77F60C3F    5F              pop edi
77F60C40    C9              leave
77F60C41    C2 0800         retn 8
77F60C44 >  55              push ebp

代碼[3]
77F79B46    BA B89BF777     mov edx,ntdll.77F79BB8
77F79B4B    EB 07           jmp short ntdll.77F79B54
77F79B4D    BA DF9BF777     mov edx,ntdll.77F79BDF
77F79B52    8D09            lea ecx,dword ptr ds:[ecx]
77F79B54    53              push ebx
77F79B55    56              push esi
77F79B56    57              push edi
77F79B57    33C0            xor eax,eax
77F79B59    33DB            xor ebx,ebx
77F79B5B    33F6            xor esi,esi
77F79B5D    33FF            xor edi,edi
77F79B5F    FF7424 20       push dword ptr ss:[esp+20]
77F79B63    FF7424 20       push dword ptr ss:[esp+20]
77F79B67    FF7424 20       push dword ptr ss:[esp+20]
77F79B6B    FF7424 20       push dword ptr ss:[esp+20]
77F79B6F    FF7424 20       push dword ptr ss:[esp+20]
77F79B73    E8 06000000     call ntdll.77F79B7E //// F4下,F7進入,來到代碼[4]
77F79B78    5F              pop edi
77F79B79    5E              pop esi
77F79B7A    5B              pop ebx
77F79B7B    C2 1400         retn 14

代碼[4]
77F79B7E    55              push ebp
77F79B7F    8BEC            mov ebp,esp
77F79B81    FF75 0C         push dword ptr ss:[ebp+C]
77F79B84    52              push edx
77F79B85    64:FF35 0000000>push dword ptr fs:[0]
77F79B8C    64:8925 0000000>mov dword ptr fs:[0],esp
77F79B93    FF75 14         push dword ptr ss:[ebp+14]
77F79B96    FF75 10         push dword ptr ss:[ebp+10]
77F79B99    FF75 0C         push dword ptr ss:[ebp+C]
77F79B9C    FF75 08         push dword ptr ss:[ebp+8]
77F79B9F    8B4D 18         mov ecx,dword ptr ss:[ebp+18]
77F79BA2    FFD1            call ecx   //這就是異常處理回調函數!
77F79BA4    64:8B25 0000000>mov esp,dword ptr fs:[0]
77F79BAB    64:8F05 0000000>pop dword ptr fs:[0]
77F79BB2    8BE5            mov esp,ebp
77F79BB4    5D              pop ebp
77F79BB5    C2 1400         retn 14 //返回後繼續跟,回到代碼[5]處
代碼[6]
77F75913 >  B8 20000000     mov eax,20
77F75918    BA 0003FE7F     mov edx,7FFE0300
77F7591D    FFD2            call edx //f7,到代碼[8]
77F7591F    C2 0800         retn 8

代碼[8]
7FFE0300    8BD4            mov edx,esp
7FFE0302    0F34            sysenter
7FFE0304    C3              retn //返回到 代碼[9]

代碼[9]
0040102F  |.  68 00304000   push seh2.00403000                                ; |Title = "SEH"
00401034  |.  68 04304000   push seh2.00403004                                ; |Text = "Hello,SEH!"
00401039  |.  6A 00         push 0                                            ; |hOwner = NULL
0040103B  |.  E8 44000000   call <jmp.&USER32.MessageBoxA>                    ; \MessageBoxA
00401040  |.  64:8F05 00000>pop dword ptr fs:[0]
00401047  |.  83C4 04       add esp,4
0040104A  |.  6A 00         push 0                                            ; /ExitCode = 0
0040104C  \.  E8 39000000   call <jmp.&KERNEL32.ExitProcess>                  ; \ExitProcess //f7,進入,到代碼[10]

代碼[10]-----這段代碼,任何程序只要執行了exitprocess都會看到!留個印象吧!
77E598FD >  55              push ebp
77E598FE    8BEC            mov ebp,esp
77E59900    6A FF           push -1
77E59902    68 B0F3E877     push kernel32.77E8F3B0
77E59907    FF75 08         push dword ptr ss:[ebp+8]
77E5990A    E8 86FFFFFF     call kernel32.77E59895 // 結束了應用程序的生命!
77E5990F  ^ E9 A47DFEFF     jmp kernel32.TerminateProcess
77E59914  - FF25 F413E477   jmp dword ptr ds:[<&ntdll.LdrShutdownProcess>]    ; ntdll.LdrShutdownProcess
77E5991A    391D A470EB77   cmp dword ptr ds:[77EB70A4],ebx
77E59920    0F84 99150000   je kernel32.77E5AEBF
77E59926    53              push ebx
77E59927    53              push ebx
77E59928    53              push ebx
77E59929    E8 D2F4FEFF     call kernel32.WriteProfileStringW
77E5992E    E9 8C150000     jmp kernel32.77E5AEBF
77E59933 >  837C24 04 00    cmp dword ptr ss:[esp+4],0
77E59938    0F84 C4730200   je kernel32.77E80D02
77E5993E    FF7424 08       push dword ptr ss:[esp+8]
77E59942    FF7424 08       push dword ptr ss:[esp+8]
77E59946    FF15 6814E477   call dword ptr ds:[<&ntdll.NtTerminateThread>]    ; ntdll.ZwTerminateThread
77E5994C    85C0            test eax,eax
77E5994E    0F8C B7730200   jl kernel32.77E80D0B
77E59954    33C0            xor eax,eax
77E59956    40              inc eax
77E59957    C2 0800         retn 8
**************************************************************************************************************附件:SEH.rar  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章