SetUnhandledExceptionFilter 的討論
現在有好多殼用 SetUnhandledExceptionFilter 安裝了最後異常處理例程來愚弄 Ollydbg,
一開始確實難倒了我等菜鳥, 幸好後來有位俄羅斯高人寫了個外掛, 解決了這個問題, 但一直想知道原因.
最近抽空把 Hume 大俠的 SEH 文章反反覆覆看了好幾遍, 又看了外掛的 README, 總算有點明白了.
把他寫出來, 請各位大俠看看, 多多指點.
例項下載:點選此處下載
(一) 發生異常時系統的處理順序(by Jeremy Gordon, Hume):
1.系統首先判斷異常是否應傳送給目標程式的異常處理例程,如果決定應該傳送,並且目標程式正在被除錯,則系統
掛起程式並向偵錯程式傳送EXCEPTION_DEBUG_EVENT訊息.
2.如果你的程式沒有被除錯或者偵錯程式未能處理異常,系統就會繼續查詢你是否安裝了執行緒相關的異常處理例程,如果
你安裝了執行緒相關的異常處理例程,系統就把異常傳送給你的程式seh處理例程,交由其處理.
3.每個執行緒相關的異常處理例程可以處理或者不處理這個異常,如果他不處理並且安裝了多個執行緒相關的異常處理例程,
可交由鏈起來的其他例程處理.
4.如果這些例程均選擇不處理異常,如果程式處於被除錯狀態,作業系統仍會再次掛起程式通知debugger.
5.如果程式未處於被除錯狀態或者debugger沒有能夠處理,並且你呼叫SetUnhandledExceptionFilter安裝了最後異
常處理例程的話,系統轉向對它的呼叫.
6.如果你沒有安裝最後異常處理例程或者他沒有處理這個異常,系統會呼叫預設的系統處理程式,通常顯示一個對話方塊,
你可以選擇關閉或者最後將其附加到偵錯程式上的除錯按鈕.如果沒有偵錯程式能被附加於其上或者偵錯程式也處理不了,系統
就呼叫ExitProcess終結程式.
7.不過在終結之前,系統仍然對發生異常的執行緒異常處理控制程式碼來一次展開,這是執行緒異常處理例程最後清理的機會.
外掛的 README:
THEORY
When exception happens, Win2K/XP gives control to NTDLL!KiUserExceptionFilter,
which in turn calls KERNEL32!UnhandledExceptionFilter. This function checks if
faulty software is being debugged. If not, UnhandledExceptionFilter calls
softwares' exception handler.
SOLUTION:
Patch KERNEL32!UnhandledExceptionFilter so that softwares' exception handler
is always called. Used signatures work for both Win2K SP4/WinXP SP1, and
hopefully for all other versions.
(二) 參考 Hume 的例子寫的第一個 MASM 程式, 沒有最終異常處理例程
;//============================ SEH1.EXE ============================
.386
.model flat, stdcall
option casemap :none ; case sensitive
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib
;//============================
.data
szCap1 db "Thread SEH 1",0
szMsg1 db "We are in thread SEH handler 1. ",0
szCap2 db "Thread SEH 2",0
szMsg2 db "We are in thread SEH handler 2. ",0
szCap db "SEH example",0
szMsg db "It would never get here.",0
.code
start:
;//========prog begin====================
ASSUME FS:NOTHING
push offset pThread_Handler1
push fs:[0]
mov fs:[0],esp ;//建立SEH的基本ERR結構
push offset pThread_Handler2
push fs:[0]
mov fs:[0],esp ;//建立SEH的基本ERR結構
xor ecx,ecx
mov eax,200
cdq
div ecx
;//以下永遠不會被執行
invoke MessageBox,NULL,addr szMsg,addr szCap,MB_OK+MB_ICONEXCLAMATION
invoke ExitProcess,NULL
;//============================
pThread_Handler1:
invoke MessageBox,NULL,addr szMsg1,addr szCap1,MB_OK+MB_ICONINFORMATION
mov eax,1 ;//ExceptionContinueSearch,不處理,由其他例程或系統處理
;mov eax,0 ;//ExceptionContinueExecution,表示已經修復,可從異常發生處繼續執行
ret ;//這裡如果返回0,你會陷入死迴圈,不斷跳出對話方塊....
pThread_Handler2:
invoke MessageBox,NULL,addr szMsg2,addr szCap2,MB_OK+MB_ICONINFORMATION
mov eax,1 ;//ExceptionContinueSearch,不處理,由其他例程或系統處理
;mov eax,0 ;//ExceptionContinueExecution,表示已經修復,可從異常發生處繼續執行
ret ;//這裡如果返回0,你會陷入死迴圈,不斷跳出對話方塊....
;//=============================Prog Ends==============
end start
SEH1.EXE 有兩個執行緒異常處理例程, 但都不處理除零異常.
執行 SEH1.EXE , 你將會看到 5 次對話方塊, 其中第三次是系統預設對話方塊, 最後兩次是執行緒異常展開.
(三) 參考 Hume 的例子寫的第二個 MASM 程式, 有最終異常處理例程
;//=============================== SEH2.EXE =========================
.386
.model flat, stdcall
option casemap :none ; case sensitive
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib
;//============================
.data
szCap1 db "Thread SEH 1",0
szMsg1 db "We are in thread SEH handler 1. ",0
szCap2 db "Thread SEH 2",0
szMsg2 db "We are in thread SEH handler 2. ",0
szCap0 db "Final SEH",0
szMsg0 db "We are in final SEH handler. ",0
szCap db "SEH example",0
szMsg db "It would never get here.",0
.code
start:
;//========prog begin====================
ASSUME FS:NOTHING
push offset pThread_Handler1
push fs:[0]
mov fs:[0],esp ;//建立SEH的基本ERR結構
;lea eax,Final_Handler
;invoke SetUnhandledExceptionFilter,eax ;//呼叫SetUnhandledExceptionFilter來安裝final SEH
;//原型很簡單SetUnhandledExceptionFilter proto
;//pTopLevelExceptionFilter:DWORD
push offset pThread_Handler2
push fs:[0]
mov fs:[0],esp ;//建立SEH的基本ERR結構, 只是說明兩種異常先後載入的順序對系統沒影響
xor ecx,ecx
mov eax,200
cdq
div ecx
;//以下永遠不會被執行
invoke MessageBox,NULL,addr szMsg,addr szCap,MB_OK+MB_ICONEXCLAMATION
invoke ExitProcess,NULL
;//============================
pThread_Handler1:
invoke MessageBox,NULL,addr szMsg1,addr szCap1,MB_OK+MB_ICONINFORMATION
mov eax,1 ;//ExceptionContinueSearch,不處理,由其他例程或系統處理
;mov eax,0 ;//ExceptionContinueExecution,表示已經修復,可從異常發生處繼續執行
ret ;//這裡如果返回0,你會陷入死迴圈,不斷跳出對話方塊....
pThread_Handler2:
invoke MessageBox,NULL,addr szMsg2,addr szCap2,MB_OK+MB_ICONINFORMATION
mov eax,1 ;//ExceptionContinueSearch,不處理,由其他例程或系統處理
;mov eax,0 ;//ExceptionContinueExecution,表示已經修復,可從異常發生處繼續執行
ret ;//這裡如果返回0,你會陷入死迴圈,不斷跳出對話方塊....
Final_Handler:
invoke MessageBox,NULL,addr szMsg0,addr szCap0,MB_OK+MB_ICONEXCLAMATION
mov eax,EXCEPTION_EXECUTE_HANDLER ;//==1 這時不出現非法操作的討厭對話方塊, 已經處理了, 可以結束了.
;mov eax,EXCEPTION_CONTINUE_SEARCH ;//==0 出現,這時是呼叫系統預設的異常處理過程,程式被終結了
;mov eax,EXCEPTION_CONTINUE_EXECUTION ;//==-1 表示已經修復,可從異常發生處繼續執行, 因為我們並沒有修復ecx
ret ;// 所以不斷產生異常,不斷呼叫這個例程, 出現對話方塊,陷入死迴圈,
;//=============================Prog Ends==============
end start
SEH2.EXE 有兩個執行緒異常處理例程, 一個最終異常處理例程, 都不處理除零異常.
執行 SEH2.EXE , 還是會看到 5 次對話方塊, 但是其中第三次換成我們自己的了, 最後兩次還是執行緒異常展開.
還要注意最終異常處理例程不會展開.
(四) 下面我們開始用 OD 除錯 SEH2.EXE, 注意先不要安裝外掛, 不要忽略異常.
載入後, OD 停在 004010C0.
004010C0 >/$ 68 16114000 PUSH SEH2.00401116 ; SE handler installation
004010C5 |. 64:FF35 00000>PUSH DWORD PTR FS:[0]
004010CC |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP
004010D3 |. 8D05 48114000 LEA EAX,DWORD PTR DS:[401148]
004010D9 |. 50 PUSH EAX ; /pTopLevelFilter => SEH2.00401148
004010DA |. E8 89000000 CALL <JMP.&kernel32.SetUnhandledExceptio>; \SetUnhandledExceptionFilter
004010DF |. 68 2F114000 PUSH SEH2.0040112F ; SE handler installation
004010E4 |. 64:FF35 00000>PUSH DWORD PTR FS:[0]
004010EB |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP
004010F2 |. 33C9 XOR ECX,ECX
004010F4 |. B8 C8000000 MOV EAX,0C8
004010F9 |. 99 CDQ
004010FA |. F7F1 DIV ECX ; // 除零異常
004010FC |. 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004010FE |. 68 9B104000 PUSH SEH2.0040109B ; |Title = "SEH example"
00401103 |. 68 A7104000 PUSH SEH2.004010A7 ; |Text = "It would never get here."
00401108 |. 6A 00 PUSH 0 ; |hOwner = NULL
0040110A |. E8 5F000000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
0040110F |. 6A 00 PUSH 0 ; /ExitCode = 0
00401111 \. E8 4C000000 CALL <JMP.&kernel32.ExitProcess> ; \ExitProcess
00401116 /$ 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL; Structured exception handler
00401118 |. 68 14104000 PUSH SEH2.00401014 ; |Title = "Thread SEH 1"
0040111D |. 68 21104000 PUSH SEH2.00401021 ; |Text = "We are in thread SEH handler 1. "
00401122 |. 6A 00 PUSH 0 ; |hOwner = NULL
00401124 |. E8 45000000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
00401129 |. B8 01000000 MOV EAX,1
0040112E \. C3 RETN
0040112F /$ 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL; Structured exception handler
00401131 |. 68 43104000 PUSH SEH2.00401043 ; |Title = "Thread SEH 2"
00401136 |. 68 50104000 PUSH SEH2.00401050 ; |Text = "We are in thread SEH handler 2. "
0040113B |. 6A 00 PUSH 0 ; |hOwner = NULL
0040113D |. E8 2C000000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
00401142 |. B8 01000000 MOV EAX,1
00401147 \. C3 RETN
00401148 . 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
0040114A . 68 72104000 PUSH SEH2.00401072 ; |Title = "Final SEH"
0040114F . 68 7C104000 PUSH SEH2.0040107C ; |Text = "We are in final SEH handler. "
00401154 . 6A 00 PUSH 0 ; |hOwner = NULL
00401156 . E8 13000000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
0040115B . B8 01000000 MOV EAX,1
00401160 . C3 RETN
不要執行, 先看看 OD 的 SEH chain 視窗, 如下, 系統已經為我們設好了一個異常處理例程.
SEH chain of main thread
Address SE handler
0012FFE0 kernel32.7C5C1F44 ; 記住這裡, 稱其為系統執行緒異常處理例程
; 關鍵的地方.
F9 執行, OD 停在 004010FA, 除零異常. 再看一下 SEH chain 視窗.
SEH chain of main thread
Address SE handler
0012FFB4 SEH2.0040112F
0012FFBC SEH2.00401116
0012FFE0 kernel32.7C5C1F44
我們按照 OD 的提示 SHIFT+F7 走, 注意不是 SHIFT+F9
77F9FF60 > 8B4C24 04 MOV ECX,DWORD PTR SS:[ESP+4] ; ntdll.KiUserExceptionDispatcher
77F9FF64 8B1C24 MOV EBX,DWORD PTR SS:[ESP]
77F9FF67 51 PUSH ECX
77F9FF68 53 PUSH EBX
77F9FF69 E8 6F6CFFFF CALL ntdll.77F96BDD ; F7
我們發現系統把控制權交給了 ntdll.KiUserExceptionDispatcher,
而不是 README 裡說的 KiUserExceptionFilter, 這也許是說法上的差異吧.
我們一路 F7 走
77F96BDD 55 PUSH EBP
77F96BDE 8BEC MOV EBP,ESP
77F96BE0 83EC 60 SUB ESP,60
77F96BE3 53 PUSH EBX
77F96BE4 56 PUSH ESI
77F96BE5 8D45 F4 LEA EAX,DWORD PTR SS:[EBP-C]
77F96BE8 57 PUSH EDI
77F96BE9 50 PUSH EAX
77F96BEA 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
77F96BED 50 PUSH EAX
77F96BEE E8 C8FFFFFF CALL ntdll.77F96BBB ; F8
77F96BF3 E8 DEFFFFFF CALL ntdll.77F96BD6 ; F8
77F96BF8 8365 FC 00 AND DWORD PTR SS:[EBP-4],0
77F96BFC 8BD8 MOV EBX,EAX
77F96BFE 83FB FF CMP EBX,-1
77F96C01 74 71 JE SHORT ntdll.77F96C74
77F96C03 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
77F96C06 3B5D F8 CMP EBX,DWORD PTR SS:[EBP-8] ; // 迴圈處理執行緒異常鏈
77F96C09 8D43 08 LEA EAX,DWORD PTR DS:[EBX+8]
77F96C0C 0F82 40AF0100 JB ntdll.77FB1B52
77F96C12 3B45 F4 CMP EAX,DWORD PTR SS:[EBP-C]
77F96C15 0F87 37AF0100 JA ntdll.77FB1B52
77F96C1B F6C3 03 TEST BL,3
77F96C1E 0F85 2EAF0100 JNZ ntdll.77FB1B52
77F96C24 F605 5604FD77 8>TEST BYTE PTR DS:[77FD0456],80
77F96C2B 0F85 AAAE0100 JNZ ntdll.77FB1ADB
77F96C31 FF73 04 PUSH DWORD PTR DS:[EBX+4]
77F96C34 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-10]
77F96C37 50 PUSH EAX
77F96C38 FF75 0C PUSH DWORD PTR SS:[EBP+C]
77F96C3B 53 PUSH EBX
77F96C3C 56 PUSH ESI
77F96C3D E8 3AFFFFFF CALL ntdll.77F96B7C ; F7, 見下面
77F96C42 F605 5604FD77 8>TEST BYTE PTR DS:[77FD0456],80
77F96C49 8BF8 MOV EDI,EAX
77F96C4B 0F85 A0AE0100 JNZ ntdll.77FB1AF1
77F96C51 395D FC CMP DWORD PTR SS:[EBP-4],EBX
77F96C54 0F84 A5AE0100 JE ntdll.77FB1AFF
77F96C5A 8BC7 MOV EAX,EDI
77F96C5C 33C9 XOR ECX,ECX
77F96C5E 2BC1 SUB EAX,ECX
77F96C60 0F84 8A030000 JE ntdll.77F96FF0
77F96C66 48 DEC EAX
77F96C67 0F85 9FAE0100 JNZ ntdll.77FB1B0C
77F96C6D 8B1B MOV EBX,DWORD PTR DS:[EBX]
77F96C6F 83FB FF CMP EBX,-1 ; // 0FFFFFFFFh
77F96C72 ^ 75 92 JNZ SHORT ntdll.77F96C06 ; // 是不是最後一個執行緒異常處理例程
77F96B7C BA AE6DF977 MOV EDX,ntdll.77F96DAE
77F96B81 55 PUSH EBP
77F96B82 8BEC MOV EBP,ESP
77F96B84 FF75 0C PUSH DWORD PTR SS:[EBP+C]
77F96B87 52 PUSH EDX
77F96B88 64:FF35 0000000>PUSH DWORD PTR FS:[0]
77F96B8F 64:8925 0000000>MOV DWORD PTR FS:[0],ESP
77F96B96 FF75 14 PUSH DWORD PTR SS:[EBP+14] ; pDispatch
77F96B99 FF75 10 PUSH DWORD PTR SS:[EBP+10] ; pContext
77F96B9C FF75 0C PUSH DWORD PTR SS:[EBP+C] ; pException_Registration_Record
77F96B9F FF75 08 PUSH DWORD PTR SS:[EBP+8] ; pException_Record
77F96BA2 8B4D 18 MOV ECX,DWORD PTR SS:[EBP+18]
77F96BA5 FFD1 CALL ECX ; 執行緒異常處理例程, F7 跟進,
77F96BA7 64:8B25 0000000>MOV ESP,DWORD PTR FS:[0]
77F96BAE 64:8F05 0000000>POP DWORD PTR FS:[0]
77F96BB5 8BE5 MOV ESP,EBP
77F96BB7 5D POP EBP
77F96BB8 C2 1400 RETN 14 ; ret to 77F96C42
我們將在 77F96BA5 進入執行緒處理例程, 一共三次.
前兩次是我們自己的程式碼, 都不處理除零異常, 返回 EAX=1.
最後一次, 就是前面記下的 系統預設的執行緒處理例程 7C5C1F44, F7 進去
7C5C1F44 55 PUSH EBP
7C5C1F45 8BEC MOV EBP,ESP
7C5C1F47 83EC 08 SUB ESP,8
7C5C1F4A 53 PUSH EBX
7C5C1F4B 56 PUSH ESI
7C5C1F4C 57 PUSH EDI
7C5C1F4D 55 PUSH EBP
7C5C1F4E FC CLD
7C5C1F4F 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+C] ; pException_Registration_Record
7C5C1F52 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ; pException_Record
7C5C1F55 F740 04 0600000>TEST DWORD PTR DS:[EAX+4],6 ; 異常標誌, =6 表示正展開中.
7C5C1F5C 75 77 JNZ SHORT kernel32.7C5C1FD5
7C5C1F5E 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
7C5C1F61 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10] ; pContext
7C5C1F64 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
7C5C1F67 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
7C5C1F6A 8943 FC MOV DWORD PTR DS:[EBX-4],EAX
7C5C1F6D 8B73 0C MOV ESI,DWORD PTR DS:[EBX+C]
7C5C1F70 8B7B 08 MOV EDI,DWORD PTR DS:[EBX+8]
7C5C1F73 83FE FF CMP ESI,-1
7C5C1F76 74 56 JE SHORT kernel32.7C5C1FCE
7C5C1F78 8D0C76 LEA ECX,DWORD PTR DS:[ESI+ESI*2]
7C5C1F7B 837C8F 04 00 CMP DWORD PTR DS:[EDI+ECX*4+4],0
7C5C1F80 74 3A JE SHORT kernel32.7C5C1FBC
7C5C1F82 56 PUSH ESI
7C5C1F83 55 PUSH EBP
7C5C1F84 8D6B 10 LEA EBP,DWORD PTR DS:[EBX+10]
7C5C1F87 FF548F 04 CALL DWORD PTR DS:[EDI+ECX*4+4] ; F7 進入 7C598940
7C598940 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
7C598943 8B08 MOV ECX,DWORD PTR DS:[EAX]
7C598945 8B09 MOV ECX,DWORD PTR DS:[ECX]
7C598947 894D E4 MOV DWORD PTR SS:[EBP-1C],ECX
7C59894A 50 PUSH EAX
7C59894B E8 8C330000 CALL kernel32.UnhandledExceptionFilter ; 我們來到了 README 所說的第二個函式, F7 進去看看.
7C598950 C3 RETN
7C59BCDC > 55 PUSH EBP ; kernel32.UnhandledExceptionFilter
7C59BCDD 8BEC MOV EBP,ESP
7C59BCDF 6A FF PUSH -1
7C59BCE1 68 C02E577C PUSH kernel32.7C572EC0
7C59BCE6 68 441F5C7C PUSH kernel32.7C5C1F44
7C59BCEB 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
7C59BCF1 50 PUSH EAX
7C59BCF2 64:8925 0000000>MOV DWORD PTR FS:[0],ESP
7C59BCF9 51 PUSH ECX
7C59BCFA 51 PUSH ECX
7C59BCFB 81EC D8020000 SUB ESP,2D8
7C59BD01 53 PUSH EBX
7C59BD02 56 PUSH ESI
7C59BD03 57 PUSH EDI
7C59BD04 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP
7C59BD07 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
7C59BD0A 8B06 MOV EAX,DWORD PTR DS:[ESI]
7C59BD0C 8138 050000C0 CMP DWORD PTR DS:[EAX],C0000005
7C59BD12 75 1B JNZ SHORT kernel32.7C59BD2F
7C59BD14 33DB XOR EBX,EBX
7C59BD16 3958 14 CMP DWORD PTR DS:[EAX+14],EBX
7C59BD19 74 16 JE SHORT kernel32.7C59BD31
7C59BD1B FF70 18 PUSH DWORD PTR DS:[EAX+18]
7C59BD1E E8 E8FEFFFF CALL kernel32.7C59BC0B
7C59BD23 83F8 FF CMP EAX,-1
7C59BD26 75 09 JNZ SHORT kernel32.7C59BD31
7C59BD28 0BC0 OR EAX,EAX
7C59BD2A E9 8E020000 JMP kernel32.7C59BFBD
7C59BD2F 33DB XOR EBX,EBX ; EBX = 0 ;
7C59BD31 895D C8 MOV DWORD PTR SS:[EBP-38],EBX ; ProecssInfo = 0;
7C59BD34 53 PUSH EBX ; NULL
7C59BD35 6A 04 PUSH 4 ; sizeof(ProcessInfo)
7C59BD37 8D45 C8 LEA EAX,DWORD PTR SS:[EBP-38]
7C59BD3A 50 PUSH EAX ; &ProcessInfo
7C59BD3B 6A 07 PUSH 7 ; ProcessDebugPort
7C59BD3D E8 7BBBFFFF CALL kernel32.GetCurrentProcess ; 返回 hProcess
7C59BD42 50 PUSH EAX
7C59BD43 FF15 B810577C CALL DWORD PTR DS:[<&ntdll.NtQueryInformationProce>; ntdll.ZwQueryInformationProcess
7C59BD49 3BC3 CMP EAX,EBX ; EAX = 0 表示成功, EAX = -1 表示不成功
7C59BD4B 7C 09 JL SHORT kernel32.7C59BD56
7C59BD4D 395D C8 CMP DWORD PTR SS:[EBP-38],EBX ; [EBP-38]= -1 有偵錯程式, 0 沒有
7C59BD50 0F85 49020000 JNZ kernel32.7C59BF9F ; 所以我們只要把 [EBP-38] 清零
; 就可以瞞過系統, 使其以為目前未在除錯狀態
; 這就是外掛的作用吧.
上面 ZwQueryInformationProcess 某個程式是否正被ring3偵錯程式所除錯。
Blowfish 班主寫過一篇文章, 可以參考.
enum PROCESS_INFO_CLASS { ProcessDebugPort = 7 };
typedef struct _PROCESS_DEBUG_PORT_INFO
{
HANDLE DebugPort;
} PROCESS_DEBUG_PORT_INFO;
PROCESS_DEBUG_PORT_INFO ProcessInfo;
ZwQueryInformationProcess(GetCurrentProcess( ), ProcessDebugPort, &ProcessInfo, sizeof(ProcessInfo), NULL)
我們把 [EBP-38]清零, 到 401148(Final_Handler) 下斷, F9 , 看看發生了什麼, 我們在 OD 裡來到了 Final_Handler.
沒有外掛, 我們也可以對付最終異常處理例程了.
(五) 我的結論
一. 程式沒有被除錯
0.執行緒建立時, 系統安裝一個 系統執行緒異常處理例程
1.異常發生時, Win2K/XP 控制權轉移給 NTDLL.KiUserExceptionDispatcher
2.如果你安裝了執行緒相關的異常處理例程, 系統就把異常傳送給你的處理例程,交由其處理.
3.每個執行緒相關的異常處理例程可以處理或者不處理這個異常,如果他不處理並且安裝了多個執行緒相關的異常處理例程,
可交由鏈起來的其他例程處理.
4.如果這些例程均選擇不處理異常,系統執行緒異常處理例程將起作用, 呼叫 ZwQueryInformationProcess 判斷是否被除錯,
沒有除錯並且你呼叫SetUnhandledExceptionFilter安裝了最後異常處理例程的話,系統轉向對它的呼叫.
5.如果你沒有安裝最後異常處理例程或者他沒有處理這個異常,系統會呼叫預設的系統處理程式,通常顯示一個對話方塊,
你可以選擇關閉或者最後將其附加到偵錯程式上的除錯按鈕.
如果沒有偵錯程式能被附加於其上或者偵錯程式也處理不了,系統就呼叫ExitProcess終結程式.
6.不過在終結之前,系統仍然對發生異常的執行緒異常處理控制程式碼來一次展開,這是執行緒異常處理例程最後清理的機會.
一般只用來釋放資源, 不要試圖修復什麼. 注意只對執行緒異常有展開.
二. 程式被除錯
0.執行緒建立時, 系統安裝一個系統執行緒異常處理例程
1.異常發生時, 系統掛起程式並向偵錯程式傳送 EXCEPTION_DEBUG_EVENT 訊息.
2.偵錯程式未能處理異常(比如我們在 OD 裡按Shift+F7), 控制權轉移給 NTDLL.KiUserExceptionDispatcher
如果你安裝了執行緒相關的異常處理例程,系統就把異常傳送給你的程式seh處理例程,交由其處理.
3.每個執行緒相關的異常處理例程可以處理或者不處理這個異常,如果他不處理並且安裝了多個執行緒相關的異常處理例程,
可交由鏈起來的其他例程處理.
4.如果這些例程均選擇不處理異常,系統執行緒異常處理例程將起作用, 呼叫 ZwQueryInformationProcess 判斷是否被除錯,
5.由於被除錯, 作業系統仍會再次掛起程式通知debugger.
其實這裡, 我也有很多似懂非懂的地方, 各位大俠請多指點.
相關文章
- [iOS Monkey 討論帖] 整套新的 fastmonkey 討論2021-01-08iOSAST
- [技術討論]關於低耦合開發的討論2012-11-09
- 我們現在沒有討論的但有必要討論的模式2005-12-02模式
- js中分號的討論2018-12-04JS
- 《NewSQL與NoSQL的討論》2014-02-23SQL
- 【討論】論 cursor 在測試中的使用2024-09-19
- 關於UI的一次討論——來自專案管理群的討論2011-01-25UI專案管理
- 討論JDK的File.equal()2015-12-15JDK
- 關於oracle SCN 的討論2010-06-09Oracle
- 討論:大家來討論一些連線涉及到的引數2007-06-25
- 關於部落格評論外掛的討論2018-02-11
- [技術討論]多使用者(多公司)的資料庫設計討論2011-01-05資料庫
- [譯] 討論 JS ⚡:文件2019-01-17JS
- httprunner 大佬討論群2020-08-31HTTP
- Ruby語言討論2012-07-27
- 對容器映象的思考和討論2021-01-20
- failover機制的小討論2013-07-14AI
- 眾推專案的最近討論2015-04-30
- 有沒有一些大廠的高階架構技術討論討論2021-11-04架構
- 關於aio的設定的討論2015-06-15AI
- 當我們在討論遊戲社群時,我們在討論什麼?2019-09-16遊戲
- plsql--迴圈討論2009-10-21SQL
- 關於神經網路的討論2020-07-31神經網路
- 網際網路加班的那些討論2012-07-14
- 討論用jetspeed做專案的朋友!!2003-08-26
- 關於rails和Grails的效能討論2007-03-26AI
- 關於HTTP中文翻譯的討論2012-05-22HTTP
- plsql--PRAGMA關鍵字的討論2009-10-22SQL
- PLSQL--變數範圍的討論2009-10-22SQL變數
- [技術討論]科學基礎的分析和探討對話2010-09-01
- [軟體工程]敏捷過程模型的特性研討——源自newsmth上的討論2012-02-22軟體工程敏捷模型
- 討論專案合理分層2020-08-13
- 原始碼防洩密討論2021-08-26原始碼
- 資料分析主題討論2020-11-19
- 【討論】MVC 在前端已死?2016-12-09MVC前端
- OpenStack入門之若干討論2016-04-19
- GoLang之Concurrency再討論2014-01-23Golang
- 表結構設計討論2008-04-22