-
-
[求助]请问在OD中如何跟踪程序的Top Level SEH ?
-
发表于: 2013-12-23 11:31 4165
-
这是软件加密技术内幕中的一个例子,代码如下:
我的问题是,用od加载这个程序运行后,按shift+F9将异常传递给程序后,最后提示的是
Debugged process was unable to process exception,Top Level SEH部分的代码完全没执行,但是双击正常运行时,异常就可以传递给Top Level SEH。同时,将Top Level SEH 改为线程相关的SEH后,在OD调试的状态下异常可以传递给源程序的SEH。
为什么OD下不能将异常传递给Top Level SEH?
谢谢!
------------------------------------------------------------------------------------------------------------------------------------
经一哥们点拨,发现 msdn中对SetUnhandledExceptionFilter是这样描述的,
The SetUnhandledExceptionFilter function lets an application supersede the top-level exception handler that Win32 places at the top of each thread and process.
After calling this function, if an exception occurs in a process that is not being debugged, and the exception makes it to the Win32 unhandled exception filter, that filter will call the exception filter function specified by the lpTopLevelExceptionFilter parameter.
LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(
LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
// exception filter function
);
红色的意思是,只有程序不被调试的时候,出现的异常才有可能交给TopLevelExceptionFilter处理。
但是,在软件加密技术内幕书中,第四章windows下的异常处理 4.1.2 异常处理的基本过程
其中第5条,说明TopLevelExceptionFilter在程序被调试时也可以得到调用。这与MSDN中对SetUnhandledExceptionFilter的介绍就不一致了。
;****************************************** ;coded by Hume,2K+ ;****************************************** ;例子1.演示Final型异常处理及参数获取 ;****************************************** ; ######################################################################### .386 .model flat, stdcall option casemap :none ; case sensitive ; ######################################################################### include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib ; ######################################################################### ;include hhd.h ;编译所必需的头文件 .DATA szTit db "SEH例子-Final,written by Hume",0 mes000 db "We are in the Exception handler,Kill Prog",0dh,0ah db "in silence(Y)、noisily(N) or Continue(cancel)?",0 messuc db "Hello,We manage to return after exception!",0 impossible db "It's impossible...",0 .DATA? OldFilter dd ? ;;----------------------------------------- .CODE ;Final 型异常处理回调函数 myFinalHandler proc uses esi edi ebx lpExceptionPointers invoke MessageBox,0,addr mes000,addr szTit,MB_ICONINFORMATION or MB_YESNOCANCEL .if eax==IDYES mov eax,EXCEPTION_EXECUTE_HANDLER ;处理完毕,不会显示对话框 .elseif eax==IDNO orCannotHanle: mov eax,EXCEPTION_CONTINUE_SEARCH ;继续查找,显示对话框 .elseif eax==IDCANCEL ;处理完毕,修改CONTEXT上下文 mov ebx,[lpExceptionPointers] ;继续执行程序 ASSUME ebx:ptr EXCEPTION_POINTERS ASSUME esi:ptr EXCEPTION_RECORD ASSUME edi:ptr CONTEXT mov esi,[ebx].pExceptionRecord mov edi,[ebx].ContextRecord test [esi].ExceptionFlags,3 jnz orCannotHanle cmp [esi].ExceptionCode,STATUS_ACCESS_VIOLATION jne orCannotHanle ;是内存读写异常吗 mov [edi].regEip,offset suc_ret ;改变返回地址 mov eax,EXCEPTION_CONTINUE_EXECUTION .endif ret myFinalHandler endp ;程序入口点 _StArT: invoke SetErrorMode,0 invoke SetUnhandledExceptionFilter,offset myFinalHandler mov [OldFilter],eax xor eax,eax mov [eax],eax ;向地址0处写数据!产生异常 nop ;永不可能执行下面的语句 invoke MessageBox,0,addr impossible,addr szTit,MB_ICONINFORMATION nop suc_ret: ;返回后执行到这里 invoke MessageBox,0,addr messuc,addr szTit,MB_ICONINFORMATION invoke ExitProcess,0 END _StArT
我的问题是,用od加载这个程序运行后,按shift+F9将异常传递给程序后,最后提示的是
Debugged process was unable to process exception,Top Level SEH部分的代码完全没执行,但是双击正常运行时,异常就可以传递给Top Level SEH。同时,将Top Level SEH 改为线程相关的SEH后,在OD调试的状态下异常可以传递给源程序的SEH。
为什么OD下不能将异常传递给Top Level SEH?
谢谢!
------------------------------------------------------------------------------------------------------------------------------------
经一哥们点拨,发现 msdn中对SetUnhandledExceptionFilter是这样描述的,
The SetUnhandledExceptionFilter function lets an application supersede the top-level exception handler that Win32 places at the top of each thread and process.
After calling this function, if an exception occurs in a process that is not being debugged, and the exception makes it to the Win32 unhandled exception filter, that filter will call the exception filter function specified by the lpTopLevelExceptionFilter parameter.
LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(
LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
// exception filter function
);
红色的意思是,只有程序不被调试的时候,出现的异常才有可能交给TopLevelExceptionFilter处理。
但是,在软件加密技术内幕书中,第四章windows下的异常处理 4.1.2 异常处理的基本过程
首先来看一个应用程序发生错误后,Windows是如何结合SEH机制进行处理的。
(1)因为有多种异常,系统首先判断异常是否应发送给目标程序,如果应该发送,并且目标程序正处于被调试状态,则系统挂起程序,填写如下结构:
typedef _EXCEPTION_DEBUG_INFO{
EXCEPTION_RECORD ExceptionRecord;
DWORD dwFirstchance;
} EXCEPTION_DEBUG_INFO;
将成员dwFirstchance置为1,并向调试器发送EXCEPTION_DEBUG_EVENT消息。剩下的事情就由调试器全权负责了,调试器可能处理这个异常,也可能无法处理。
(2)如果调试器未能处理异常或程序根本没有被调试,系统就会查找你是否存在与线程相关的异常处理过程,如果目标程序中存在与线程相关的异常处理过程,系统就调用与程序的线程相关的SEH异常处理例程,交由其处理。
(3)与线程相关的异常处理过程可以有一个或多个,每个可以选择处理或者不处理异常,如果它不处理并且存在多个线程相关的异常处理过程,可交由链起来的其他异常处理过程进行处理,依次类推。
(4)如果程序线程的异常处理均选择不处理异常,并且如果程序处于被调试状态,则操作系统仍会再次挂起程序通知调试器,这时EXCEPTION_DEBUG_INFO 结构的dwFirstchance成员置为0。
(5)如果程序未处于被调试状态或者调试器仍然未能够处理,并且程序调用了API函数SetUnhandledExceptionFilter设置了与进程相关异常处理过程,则系统转向对它的调用。
(6)如果程序没有设置进程相关的异常处理过程或者进程相关的异常处理过程也未能处理这个异常,系统会调用默认的系统异常处理程序,通常显示一个对话框(如图4.1所示),你可以选择“关闭”或者最后将其附加到调试器上的“调试”按钮。如果没有调试器能被附加于其上或调试器还是处理不了异常,系统就调用ExitProcess终结程序。
(7)不过在终结之前,系统再次调用发生异常的线程中所有的异常处理过程,这是线程异常处理过程获得的最后清理未释放资源的机会,其后程序就终结了。
以上大致描述了异常发生时系统的逻辑处理顺序,如果看了后一头雾水的话,别着急,花点时间慢慢理解或者进入下一部分继续,再回过头看就能理解了。
学习SEH时,要树立一个最基本的观念:SEH是系统在发现异常或错误时,在终结应用程序之前给应用程序的一个最后改正错误的机会,从程序设计的角度来说就是系统在终结程序之前给程序的一个执行其预设定的回调函数的机会。
其中第5条,说明TopLevelExceptionFilter在程序被调试时也可以得到调用。这与MSDN中对SetUnhandledExceptionFilter的介绍就不一致了。
赞赏
他的文章
看原图
赞赏
雪币:
留言: