首页
社区
课程
招聘
[求助]请问在OD中如何跟踪程序的Top Level SEH ?
发表于: 2013-12-23 11:31 4165

[求助]请问在OD中如何跟踪程序的Top Level SEH ?

2013-12-23 11:31
4165
这是软件加密技术内幕中的一个例子,代码如下:
;******************************************
;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的介绍就不一致了。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//