引言:_except_handler3是BaseProcessStart的異常處理函數。
7C839AF0 ; int __cdecl _except_handler3(EXCEPTION_RECORD *argExceptionRecord,<br />7C839AF0_EXCEPTION_REGISTRATION *argEstablisherFrame, _CONTEXT *argContextRecord)<br />7C839AF0<br />7C839AF0 varXPointers = dword ptr -8<br />7C839AF0 var_4 = dword ptr -4<br />7C839AF0 argExceptionRecord= dword ptr 8<br />7C839AF0 argEstablisherFrame= dword ptr 0Ch<br />7C839AF0 argContextRecord= dword ptr 10h<br />7C839AF0;<br />7C839AF0;<br />7C839AF0; VC++擴充SEH<br />7C839AF0; [ebp-14];PEXCEPTION_POINTERS xpointers;<br />7C839AF0 ; ;struct _EXCEPTION_REGISTRATION{<br />7C839AF0 ; [ebp-10]; struct _EXCEPTION_REGISTRATION *prev;<br />7C839AF0 ; [ebp-0C]; _except_handler handler;<br />7C839AF0 ; [ebp-08]; struct scopetable_entry *scopetable;<br />7C839AF0 ; [ebp-04]; int trylevel;<br />7C839AF0 ; [ebp-00]; int _ebp;<br />7C839AF0 ; ;};<br />7C839AF0 ; argEstablisherFrame當前指向[ebp-10]<br />7C839AF0 ;<br />7C839AF0 ;<br />7C839AF0 ; _except_handler定義<br />7C839AF0 ; typedef EXCEPTION_DISPOSITION __cdecl (*_except_handler)(<br />7C839AF0 ; _In_ struct _EXCEPTION_RECORD *_ExceptionRecord,<br />7C839AF0 ; _In_ void * _EstablisherFrame,<br />7C839AF0 ; _Inout_ struct _CONTEXT *_ContextRecord,<br />7C839AF0 ; _Inout_ void * _DispatcherContext<br />7C839AF0 ; );<br />7C839AF0 ;<br />7C839AF0;<br />7C839AF0 ; scopetable_entry定義<br />7C839AF0 ; struct scopetable_entry{<br />7C839AF0 ; DWORD prevlevel;<br />7C839AF0 ; PVOID lpfnFilter;<br />7C839AF0 ; PVOID lpfnHandler;<br />7C839AF0 ; }<br />7C839AF0<br />7C839AF0 push ebp<br />7C839AF1 mov ebp, esp<br />7C839AF3 sub esp, 8 ; EXCEPTION_POINTERS varXPointers;<br />7C839AF6 push ebx<br />7C839AF7 push esi<br />7C839AF8 push edi<br />7C839AF9 push ebp<br />7C839AFA cld ; Clear Direction Flag<br />7C839AFB mov ebx, [ebp+argEstablisherFrame]<br />7C839AFE mov eax, [ebp+argExceptionRecord]<br />7C839B01 test dword ptr [eax+4], 6 ;if(argExceptionRecord->ExceptionFlags &<br />7C839B01 ;EXCEPTION_UNWIND_CONTEXT)<br />7C839B01 ;goto loc_7C839BB9<br />7C839B01 ;EXCEPTION_UNWIND_CONTEXT在exsup.inc中定義<br />7C839B08 jnz loc_7C839BB9<br />7C839B0E mov [ebp+varXPointers], eax;varXPointers->ExceptionRecord=argExceptionRecord<br />7C839B11 mov eax, [ebp+argContextRecord]<br />7C839B14 mov [ebp+var_4], eax ;varXPointers->ContextRecord=argContextRecord<br />7C839B17 lea eax, [ebp+varXPointers]<br />7C839B1A mov [ebx-4], eax ;(PEXCEPTION_POINTERS)((DWORD)argEstablisherFrame-4)=xpointers<br />7C839B1D mov esi, [ebx+0Ch] ;esi=argEstablisherFrame->trylevel<br />7C839B20 mov edi, [ebx+8] ;edi=argEstablisherFrame->scopetable<br />7C839B23 push ebx<br />7C839B24 call __ValidateEH3RN<br />7C839B29 add esp, 4<br />7C839B2C or eax, eax<br />7C839B2E jz short loc_7C839BAB<br />7C839B30<br />7C839B30 loc_7C839B30: ;CODE XREF: __except_handler3+B2j<br />7C839B30 cmp esi, 0FFFFFFFFh ;if(argEstablisherFrame->trylevel==0xFFFFFFFF) goto loc_7C839BB2<br />7C839B33 jz short loc_7C839BB2 ;當前異常幀中所有__try/__except(嵌套)遍曆完畢,跳走!<br />7C839B33 ;註:一個函數僅有一個異常幀,__try/__except嵌套也只產生一個異常幀<br />7C839B35 lea ecx, [esi+esi*2]<br />7C839B38 mov eax, [edi+ecx*4+4] ;eax=argEstablisherFrame->scopetable[trylevel].lpfnFilter<br />7C839B3C or eax, eax<br />7C839B3E jz short loc_7C839B99 ;if(lpfnFilter == NULL) goto loc_7C839B99<br />7C839B40 push esi<br />7C839B41 push ebp ;儲存當前ebp<br />7C839B42 lea ebp, [ebx+10h] ;切換ebp,為lpfnFilter調用做準備<br />7C839B45 xor ebx, ebx<br />7C839B47 xor ecx, ecx<br />7C839B49 xor edx, edx<br />7C839B4B xor esi, esi<br />7C839B4D xor edi, edi<br />7C839B4F call eax ;call lpfnFilter<br />7C839B51 pop ebp ;恢複當前ebp<br />7C839B52 pop esi<br />7C839B53 mov ebx, [ebp+argEstablisherFrame]<br />7C839B56 or eax, eax ;檢查lpfnFilter傳回值.<br />7C839B58 jz short loc_7C839B99 ;if(eax==EXCEPTION_CONTINUE_SEARCH) goto loc_7C839B99<br />7C839B5A js short loc_7C839BA4 ;if(eax==EXCEPTION_CONTINUE_EXECUTION) goto loc_7C839BA4<br />7C839B5C mov edi, [ebx+8] ;if(eax==EXCEPTION_EXECUTE_HANDLER) goto 7C839B5F<br />7C839B5F push ebx<br />7C839B60 call __global_unwind2 ;全域展開<br />7C839B65 add esp, 4<br />7C839B68 lea ebp, [ebx+10h] ;切換ebp,注意之前沒有儲存當前ebp.<br />7C839B6B push esi<br />7C839B6C push ebx<br />7C839B6D call __local_unwind2 ;局部展開<br />7C839B72 add esp, 8<br />7C839B75 lea ecx, [esi+esi*2]<br />7C839B78 push 1<br />7C839B7A mov eax, [edi+ecx*4+8]<br />7C839B7E call __NLG_Notify<br />7C839B83 mov eax, [edi+ecx*4] ;eax = =argEstablisherFrame->scopetable[trylevel].prelevel<br />7C839B86 mov [ebx+0Ch], eax ;argEstablisherFrame->trylevel=eax<br />7C839B89 mov eax, [edi+ecx*4+8] ;eax=argEstablisherFrame->scopetable[trylevel].lpfnHandler<br />7C839B8D xor ebx, ebx<br />7C839B8F xor ecx, ecx<br />7C839B91 xor edx, edx<br />7C839B93 xor esi, esi<br />7C839B95 xor edi, edi<br />7C839B97 call eax ;call lpfnHandler 不再返回!<br />7C839B99<br />7C839B99 loc_7C839B99: ;CODE XREF: __except_handler3+4Ej<br />7C839B99 ;__except_handler3+68j<br />7C839B99 mov edi, [ebx+8] ;lpfnFilter返回EXCEPTION_CONTINUE_SEARCH的情況下<br />7C839B99 ;edi=argEstablisherFrame->scopetable<br />7C839B9C lea ecx, [esi+esi*2]<br />7C839B9F mov esi, [edi+ecx*4];esi=argEstablisherFrame->scopetable[trylevel].prevlevel<br />7C839BA2 jmp short loc_7C839B30<br />7C839BA4 ; ---------------------------------------------------------------------------<br />7C839BA4<br />7C839BA4 loc_7C839BA4: ;CODE XREF: __except_handler3+6Aj<br />7C839BA4 mov eax, 0 ;eax=ExceptionContinueExecution<br />7C839BA9 jmp short loc_7C839BCE ; 退出<br />7C839BAB ; ---------------------------------------------------------------------------<br />7C839BAB<br />7C839BAB loc_7C839BAB: ;CODE XREF: __except_handler3+3Ej<br />7C839BAB mov eax, [ebp+argExceptionRecord]<br />7C839BAE or dword ptr [eax+4], 8<br />7C839BB2<br />7C839BB2 loc_7C839BB2: ;CODE XREF: __except_handler3+43j<br />7C839BB2 mov eax, 1 ;7C839BAB ~ 7C839BB7的分析<br />7C839BB2 ;if(argExceptionRecord->ExceptionFlags==EXCEPTION_STACK_INVALID){<br />7C839BB2 ; eax = ExceptionContinueSearch<br />7C839BB2 ; goto loc_7C839BCE<br />7C839BB2 ;}<br />7C839BB7 jmp short loc_7C839BCE ; 退出<br />7C839BB9 ; ---------------------------------------------------------------------------<br />7C839BB9<br />7C839BB9 loc_7C839BB9: ; CODE XREF: __except_handler3+18j<br />7C839BB9 push ebp ; 儲存當前ebp<br />7C839BBA lea ebp, [ebx+10h] ; 切換ebp<br />7C839BBD push 0FFFFFFFFh<br />7C839BBF push ebx<br />7C839BC0 call __local_unwind2 ; 局部展開<br />7C839BC5 add esp, 8<br />7C839BC8 pop ebp ; 恢複當前ebp<br />7C839BC9 mov eax, 1 ; eax = ExceptionContinueSearch<br />7C839BCE<br />7C839BCE loc_7C839BCE: ; CODE XREF: __except_handler3+B9j<br />7C839BCE ; __except_handler3+C7j<br />7C839BCE pop ebp<br />7C839BCF pop edi<br />7C839BD0 pop esi<br />7C839BD1 pop ebx<br />7C839BD2 mov esp, ebp<br />7C839BD4 pop ebp<br />7C839BD5 retn<br />7C839BD5 __except_handler3 endp
相應的虛擬碼:
// VC++擴充SEH的異常幀結構<br />// [ebp-14];PEXCEPTION_POINTERS xpointers;<br />// ;struct _EXCEPTION_REGISTRATION{<br />// [ebp-10]; struct _EXCEPTION_REGISTRATION *prev;<br />// [ebp-0C]; _except_handler handler;<br />// [ebp-08]; struct scopetable_entry *scopetable;<br />// [ebp-04]; int trylevel;<br />// [ebp-00]; int _ebp;<br />// ;};<br />//<br />// typedef enum _EXCEPTION_DISPOSITION {<br />// ExceptionContinueExecution,<br />// ExceptionContinueSearch,<br />// ExceptionNestedException,<br />// ExceptionCollidedUnwind<br />// } EXCEPTION_DISPOSITION;<br />//<br />// _except_handler定義<br />// typedef EXCEPTION_DISPOSITION __cdecl (*_except_handler)(<br />// _In_ struct _EXCEPTION_RECORD *_ExceptionRecord,<br />// _In_ void * _EstablisherFrame,<br />// _Inout_ struct _CONTEXT *_ContextRecord,<br />// _Inout_ void * _DispatcherContext<br />// );<br />//<br />//<br />// scopetable_entry定義<br />// struct scopetable_entry{<br />// DWORD prevtrylevel;<br />// PVOID lpfnFilter;<br />// PVOID lpfnHandler;<br />// }</p><p>EXCEPTION_DISPOSITION __cdecl __except_handler3 (<br /> _In_ struct _EXCEPTION_RECORD *argExceptionRecord,<br /> _In_ void * argEstablisherFrame,<br /> _Inout_ struct _CONTEXT *argContextRecord,<br /> _Inout_ void * argDispatcherContext<br /> )<br />{<br />EXCEPTION_POINTERS varXPointers;<br />DWORD dwTryLevel,dwRetFilter;</p><p>//方向標誌複位<br />__asm cld</p><p>if(!(argExceptionRecord->ExceptionFlags & EXCEPTION_UNWIND_CONTEXT))<br />{<br />varXPointers->ExceptionRecord = argExceptionRecord;<br />varXPointers->ContextRecord = argContextRecord;</p><p>//提供VC++擴充SEH的異常幀結構中的[ebp-14]值<br />//內嵌函式GetExceptionInformation將從[ebp-14]提取資訊<br />(PEXCEPTION_POINTERS)((DWORD)argEstablisherFrame-4)= &varXPointers;</p><p>//驗證SEH異常幀<br />if(__ValidateEH3RN(argEstablisherFrame))<br />{<br />//一個函數僅有一個異常幀,一個函數可以有多個__try/__except結構<br />//嵌套的__try/__except通過scopetable->prevtrylevel關聯起來<br />//向上搜尋當前異常幀中嵌套的__try/__except過濾函數和處理函數<br />dwTryLevel = argEstablisherFrame->trylevel;<br />while(dwTryLevel != 0xFFFFFFFF)<br />{<br />//不存在過濾函數,繼續向上一層__try/__except搜尋<br />if(!argEstablisherFrame->scopetable[dwTryLevel].lpfnFilter)<br />{<br />dwTryLevel = argEstablisherFrame->scopetable[dwTryLevel].prevtrylevel;<br />continue;<br />}</p><p>//儲存當前ebp<br />__asm push ebp<br />//切換ebp回lpfnFilter所在位置<br />__asm lea ebp,&argEstablisherFrame->_ebp;<br />//調用過濾函數<br />dwRetFilter = argEstablisherFrame->scopetable[dwTryLevel].lpfnFilter();<br />//恢複當前ebp<br />__asm pop ebp<br />//檢查過濾函數的傳回值<br />if(dwRetFilter == EXCEPTION_CONTINUE_SEARCH)<br />{<br />dwTryLevel = argEstablisherFrame->scopetable[dwTryLevel].prevtrylevel;<br />continue;<br />}<br />else if(dwRetFilter == EXCEPTION_CONTINUE_EXECUTION)<br />{<br />//異常已經修複,重新執行引發異常的指令<br />return ExceptionContinueExecution;<br />}<br />//找到__except(EXCEPTION_EXECUTE_HANDLER)<br />//全域展開<br />__global_unwind2(argEstablisherFrame);<br />//切換ebp,注意:之前沒有儲存當前ebp<br />__asm lea ebp,&argEstablisherFrame->_ebp;<br />//對當前__try/__except進行局部展開<br />__local_unwind2(argEstablisherFrame,dwTryLevel);<br />//作用未知!<br />__NLG_Notify(1);<br />//把異常幀的trylevel設定成__except(EXCEPTION_EXECUTE_HANDLER)<br />//的上一個__try/__except<br />argEstablisherFrame->trylevel =<br />argEstablisherFrame->scopetable[dwTryLevel].prevtrylevel;<br />//調用__except {}塊,這個調用並不會返回<br />argEstablisherFrame->scopetable[dwTryLevel].lpfnHandler();<br />}</p><p>//當前異常幀搜尋結束,但仍然沒有找到__except(EXCEPTION_EXECUTE_HANDLER)<br />//向下一個異常幀搜尋,也就是向__except_handler3的調用函數搜尋異常幀<br />return ExceptionContinueSearch;</p><p>}<br />else<br />{<br />//異常幀的棧無效<br />//向下一個異常幀搜尋,也就是向__except_handler3的調用函數搜尋異常幀<br />if(argExceptionRecord->ExceptionFlags==EXCEPTION_STACK_INVALID)<br />{<br />return ExceptionContinueSearch;<br />}<br />}<br />}<br />else<br />{<br />//儲存當前ebp<br />__asm push ebp<br />//切換ebp回引發異常的函數<br />__asm lea,&argEstablisherFrame->_ebp;<br />//對引發異常的函數進行局部展開<br />__local_unwind2(argEstablisherFrame,0xFFFFFFFF);<br />//恢複當前ebp<br />__asm pop ebp</p><p>return ExceptionContinueSearch;<br />}<br />}
(也就是__try/__except的):
遺留:還不太清楚__NLG_Notify的作用,哪位朋友可以提點一下,非常感謝!!附__NLG_Notify:
7C80E01B __NLG_Notify proc near ; CODE XREF: __local_unwind2+57p<br />7C80E01B ; __except_handler3+8Ep<br />7C80E01B push ebx<br />7C80E01C push ecx<br />7C80E01D mov ebx, offset __NLG_Destination<br />7C80E022 mov ecx, [ebp+8]<br />7C80E025<br />7C80E025 loc_7C80E025: ; CODE XREF: __NLG_Notify1+7j<br />7C80E025 mov [ebx+8], ecx<br />7C80E028 mov [ebx+4], eax ; eax=pEstablisherFrame->scopetable[trylevel].lpfnHandler<br />7C80E02B mov [ebx+0Ch], ebp<br />7C80E02E push ebp<br />7C80E02F push ecx<br />7C80E030 push eax<br />7C80E030 __NLG_Notify endp ; sp-analysis failed<br />7C80E030<br />7C80E031<br />7C80E031 ; =============== S U B R O U T I N E =======================================<br />7C80E031<br />7C80E031<br />7C80E031 __NLG_Dispatch2 proc near<br />7C80E031 pop eax<br />7C80E032 pop ecx<br />7C80E033 pop ebp<br />7C80E034 pop ecx<br />7C80E035 pop ebx<br />7C80E036 retn 4<br />7C80E036 __NLG_Dispatch2 endp ; sp-analysis failed<br />7C80E036