学习心得--------关于seh(2)

                          关于seh(2)
     by sssa2000

马家爵被捕了,心中极度的痛苦呀。
Aaah说我中了毒,mydoom,我下了专杀工具,没发现,现在我变得异常警惕,连rundll32这个进程一看就关。
正题。

1、首先,怎么使用seh
    昨天我们说的是c++中封装好的东西,现在我们接触的是赤裸裸的seh哦。

    seh工作原理就是预先设置好处理异常的函数,然后如果有异常
    首先,要使用seh必须先设置处理异常的回调函数。

    怎么设置呢?很简单,3句就可以搞定:

      把回调函数的地址入栈  push offset _handler
      把fs:[0]入栈          push fs:[0]
      把esp存入fs:[0]       mov fs:[0],esp

     为什么要这样呢?这就要说说tib了。
     win32为每个线程定义一个线程信息块tib,这个结构中有一个
     Exceptionlist的指针,它是seh的链入口。

     这个指针指向一个EXCEPTION_REGISTRATION结构,定义如下:
     EXCEPTION_REGISTRATION STRUCT
     prev dd ?       ;前一个EXCEPTION_REGISTRATION的地址
     handler dd ?    ;回调函数的地址
     EXCEPTION_REGISTRATION ENDS

     有了这个结构才能把很多seh联结成链状,注意,这里讲的是基本节构,很多其他资料上还有其他的什么附加数据,那都是自己加上去的,最基本的就这两个。

     现在在来讲解前面的那三句
     由于tib永远载fs:[0] 所以,fs[0]指向的就是Exceptionlist指向的东西,也就是EXCEPTION_REGISTRATION。

     push fs:[0]  把fs:[0]入栈,这时候esp会指向压入的东西,为什么?先去复习一下汇编。 [esp]就是这个EXCEPTION_REGISTRATION的地址。
     这个时候,[esp+0]就是prev字段 [esp+4]是回调函数的地址

     mov fs:[0],esp
     esp放入fs:[0]。我们知道 现在的fs:[0]就是prev,他还没有被附值。现在的esp里面放的就是prev需要的地址,我们要做的就是把prev=esp


     好了,是不是觉得有点不好理解?
     如果第一次接触,那就不妨死记下来
              push offset _handler
              push fs:[0]
              mov fs:[0],esp
       这3句话,只需要把回调函数的名字变一下就可以了,随着以后的学习,你就会熟悉的,别急别急。

看看罗云彬这段代码:


  .386
  .model flat,stdcall
  option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include  windows.inc
include  user32.inc
includelib user32.lib
include  kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  .const
szMsg  db '异常发生位置:%08X,异常代码:%08X,标志:%08X',0
szSafe  db '回到了安全的地方!',0
szCaption db 'SEH例子',0

  .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 错误 Handler
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Handler 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 szMsg,/
   [edi].regEip,[esi].ExceptionCode,[esi].ExceptionFlags
  invoke MessageBox,NULL,addr @szBuffer,NULL,MB_OK
;********************************************************************
; 将 EIP 指向安全的位置并恢复堆栈
;********************************************************************
  mov eax,_lpSEH
  push [eax + 8]
  pop [edi].regEip
  push [eax + 0ch]
  pop [edi].regEbp
  push eax
  pop [edi].regEsp
  assume esi:nothing,edi:nothing
  popad
  mov eax,ExceptionContinueExecution
  ret

_Handler endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Test  proc

;********************************************************************
; 在堆栈中构造一个 EXCEPTION_REGISTRATION 结构
;********************************************************************
  assume fs:nothing
  push ebp
  push offset _SafePlace
  push offset _Handler
  push fs:[0]
  mov fs:[0],esp
;********************************************************************
; 会引发异常的指令
;********************************************************************
  pushad
  xor ebp,ebp
  xor eax,eax
  mov dword ptr [eax],0
  popad  ;这一句将无法被执行
_SafePlace:
  invoke MessageBox,NULL,addr szSafe,addr szCaption,MB_OK
;********************************************************************
; 恢复原来的 SEH 链
;********************************************************************
  pop fs:[0]
  add esp,0ch
  ret

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

 

这段代码我不解释,有一些我还要再下一讲说的,不懂得先记下,好好想一下,下一讲主要就讲一下关于seh的回调函数的问题


好了,现在离我们的目标进入ring0又进了一步,呵呵,虽说技术有点过时,对我们这些小菜还是很有用的,我也是在边学边写哦,cih进入ring0的代码我这几天随身携带,一有空就看,呵呵。  其实我一次写这么一点,是怕到时候我写不出来,延缓以下,呵呵呵。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值