SEH资料小集合

http://www.kanxue.com/bbshtml/BBS4/kanxue310.htm SEH  in ASM 研究

 

一个例子:

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming >
; by 罗云彬, http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Unwind.asm
;   演示 SEH 链的回卷操作
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Unwind.asm
; Link /subsystem:windows Unwind.obj
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  .386
  .model flat,stdcall
  option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include  windows.inc
include  user32.inc
includelib user32.lib
include  kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  .data
szMsg1  db '这是外层异常处理程序(将处理异常)',0dh,0ah
  db '异常发生位置:%08X,异常代码:%08X,标志:%08X',0
szMsg2  db '这是内层异常处理程序(对异常不进行处理)',0dh,0ah
  db '异常发生位置:%08X,异常代码:%08X,标志:%08X',0
szCaption db '提示信息',0
szBeforeUnwind db '现在将开始 Unwind,当前的 FS:[0] = %08X',0
szAfterUnwind db 'Unwind 返回,当前的 FS:[0] = %08X',0
szSafe1  db '回到了外层子程序的安全位置!',0
szSafe2  db '回到了内层子程序的安全位置!',0
szone1          db      'start',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 外层错误 Handler,将处理异常
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Handler1 proc _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext;_lpExceptionRecord指向一个Exception_Record结构
             ;_lpContext指向一个CONTEXT的结构,_lpSEH指向注册回调函数时使用的EXCEPTION_REGISTRATION结构的地址,_lpContext记录了异常产生时刻的运行环境
            
  local @szBuffer[256]:byte

  pushad                              ;利于模块化
  mov esi,_lpExceptionRecord
  mov edi,_lpContext
  assume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT,fs:nothing;启用fs寄存器
  
  invoke wsprintf,addr @szBuffer,addr szMsg1,/
   [edi].regEip,[esi].ExceptionCode,[esi].ExceptionFlags;这是外层异常处理程序
   
  invoke MessageBox,NULL,addr @szBuffer,NULL,MB_OK
;********************************************************************
; 将 EIP 指向安全的位置并恢复堆栈
;********************************************************************
  mov eax,_lpSEH;EXCEPTION_REGISTRATION结构的地址
  
  push [eax + 8h]
  
  pop [edi].regEip
  
  push _lpSEH
  
  pop [edi].regEsp
;********************************************************************
; 对前面的 Handler 进行 Unwind 操作
;********************************************************************
  invoke wsprintf,addr @szBuffer,addr szBeforeUnwind,dword ptr fs:[0];现在将开始 Unwind
  invoke MessageBox,NULL,addr @szBuffer,addr szCaption,MB_OK

  invoke RtlUnwind,_lpSEH,NULL,NULL,NULL;对当前回调函数之后的所有其他回调函数进行展开操作,FS[0]的地址发生了改变到handler2了

  invoke wsprintf,addr @szBuffer,addr szAfterUnwind,dword ptr fs:[0];Unwind 返回
  invoke MessageBox,NULL,addr @szBuffer,addr szCaption,MB_OK;FS[0]的地址又变回来了
  
;********************************************************************
  assume esi:nothing,edi:nothing
  popad
  mov eax,ExceptionContinueExecution;如果可以正确处理的话,则写修正错误并将返回值设置为ExceptionContinueExecution
  ;如果返回ExceptionContinuesearch则重复查找
  
  ret

_Handler1 endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 内层错误 Handler,不处理异常
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_Handler2 proc _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
  local @szBuffer[256]:byte

  pushad
  mov esi,_lpExceptionRecord
  mov edi,_lpContext
  assume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT
  invoke wsprintf,addr @szBuffer,addr szMsg2,/
   [edi].regEip,[esi].ExceptionCode,[esi].ExceptionFlags;这是内层异常处理程序
   
  invoke MessageBox,NULL,addr @szBuffer,NULL,MB_OK
  mov eax,_lpSEH;EXCEPTION_REGISTRATION结构的地址
  
  push [eax + 8h];EXCEPTION_REGISTRATION结构have two words,one is prev ,the other is handler,the others is our data
  
  pop [edi].regEip
  
  push _lpSEH
  
  pop [edi].regEsp;continue to point EXCEPTION_REGISTRATION
  
  assume esi:nothing,edi:nothing
  popad
  mov eax,ExceptionContinueSearch;如果返回ExceptionContinuesearch则重复查找
  ret

_Handler2 endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Test2  proc

  assume fs:nothing
  
  push offset _SafePlace
                        ;invoke RtlUnwind,_lpSEH,NULL,NULL,NULL;对当前回调函数之后的所有其他回调函数进行展开操作
                        ;_SafePlace;不是回调函数所以就。。。。。。。。。。。不知道是不是这个原因,那为什么又执行后面的_SafePlace呢
                        ;这句去掉也没什么影响,为什么
  push offset _Handler2
  push fs:[0]
  mov fs:[0],esp;第一条push offset _Handler指令将回调函数的地址推入堆栈;第二条push fs:[0]指令则将当前使用的EXCEPTION_ REGISTRATION结构地址推入堆栈,
  ;现在堆栈指针esp指向的地方刚好是一个新的EXCEPTION_REGISTRATION结构——[esp]等于原结构地址,也就是prev字段,而[esp+4]等于回调函数地址,也就是handler字段;
  ;当第三条指令mov fs:[0],esp将esp的值放入fs:[0]后,设置工作就完成了!需要注意的是,原先的结构地址必须被保存到prev字段中。
;********************************************************************
; 会引发异常的指令
;********************************************************************
  pushad
  invoke MessageBox,NULL,addr szone1,addr szCaption,MB_OK
  xor eax,eax
  mov dword ptr [eax],0
  popad  ;这一句将无法被执行
_SafePlace:                                                    ;这个函数也可以去掉为什么不能执行呢
  invoke MessageBox,NULL,addr szSafe2,addr szCaption,MB_OK;回到了内层子程序的安全位置,竟然没用。。。有问题,没有设置EIP,设置后就正常运行这个消息框
  pop fs:[0]
  add esp,8
  ret

_Test2  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Test1  proc

  assume fs:nothing
  push offset _SafePlace
  push offset _Handler1
  push fs:[0]
  mov fs:[0],esp
  invoke _Test2
_SafePlace:
  invoke MessageBox,NULL,addr szSafe1,addr szCaption,MB_OK;回到了外层子程序的安全位置
  pop fs:[0]
  add esp,8
  ret

_Test1  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
  invoke _Test1
  invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  end start

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值