首页
社区
课程
招聘
[原创]SEH之浮想联翩
发表于: 2010-11-12 15:31 10905

[原创]SEH之浮想联翩

2010-11-12 15:31
10905

首先得感谢XFish的Virus系列教程,让我学到了很多东西。
感谢翻译组riusksk组织的exploit翻译教程。让我领略了Exploit的美妙。
有翻译组提供的exploit教程,在Tutorials Part 8 :Win32 Egg Hunting中看到了一段代码,觉得十分美妙,令我浮想联翩。代码如下:


这段代码在我此种菜鸟看来非常美妙,原因如下:
一、重定位技术
这个是基础知识,经常用在PE病毒的感染上。为了获得某条指令运行时的绝对地址,
采用方式如下:
call GetBase
BaseAddr:
........................       ;一堆变量或者函数定义   
GetBase:
        pop eax                ;  eax存储了BaseAddr的绝对地址       

在call某个函数时,会将下一条指令地址压栈。这里是将BaseAddr标签运行时的绝对地址压入栈中。调用GetBase后,该地址被放入了eax中。

在上面的代码中,一开始Jmp short 0x23,在0x23处call 0x2。
也就是将0x28处指令运行时的绝对地址压入了栈中。同时在0x2处,执行pop ecx,将0x28处运行时的绝对地址放到了ecx中。

二、SEH
在此段代码中,为了在整个地址空间进行搜索同时保证程序能稳定运行,采用了SEH。如果你搜索的地址还没有分配,就会触发一个异常。没有SEH保护的话,被搜索的进程就死掉了。我想先介绍下SEH(主要是针对跟我一样的菜鸟)以及SEH的几个应用,最后再介绍下上面这段代码的原理。

1.  SEH原型说明
   注意,这里我不涉及编译器提供的异常处理技术。所以,如果你用__try{}__except(){}和__try{}__finally{}写了一段代码,然后反汇编后让我看,让我说明是怎么做的,怎样进行扩展unwind和tryblock trylevel是怎样对应到每个函数的,我很抱歉。
   对Asm Fan来说,SEH简化成了这样一段代码:
   seh:
        mov eax,seh_handler
        push eax
        push fs:[0]
        mov fs:[0],esp
        ..........
        .........             ;中间处理
   end_seh:
        pop fs:[0]
        add esp,4

   这里面涉及到几个结构体和一个函数原型。这两个东西弄清楚了,对我们下面的SEH应用会有很大帮助。
        结构体:
        EXCEPTION_REGISTRATION struc
        prev dd ?                                   //前一个EXCEPTION_REGISTRATION的地址
        handler dd ?             //异常处理函数
        EXCEPTION_REGISTRATION ends
        这里可以看到,EXCEPTION_REGISTRAION是一个链的形式,就是传说中的SEH链了。这个链结尾的标志是prev=0xFFFFFFFF,也就是-1。链的起始处,也就是当前函数的异常处理结构EXCEPTION_REGISTRATION由fs:[0]指向。
        这就意味着,你如果要给当前的函数添加你自己定义的异常处理函数,只要在堆栈上新建一个这样的结构体,接入链中,并由fs:[0]指向就好了。
       
        异常发生时处理顺序如下:
        如果该进程正在被调试,系统将处理异常的机会交给了调试器(正好可以探测调试器的存在)
        如果调试器不能处理该异常或者进程没有被调试,系统则调用你安装的异常处理函数。
        你安装的异常处理函数如果不处理该异常,系统会从你安装的_EXCEPTION_REGISTRATION处向上遍历,直到找到处理该异常的函数
        如果没有,则调用系统自带的处理函数,弹出一个很难看的框
   
   下面来看看异常处理函数原型。
        EXCEPTION_DISPOSITION (*handler)
        (PEXCEPTION_RECORD,
        PEXCEPTION_REGISTRATION,
        PCONTEXT,
        PEXCETION_RECORD) (参见A Crash Course on the depths of Win32 SEH)
        这里需要注意,异常处理函数被调用时,栈上esp+0为要返回的eip,esp+4为第一个参数EXCEPTION_RECORD的地址,esp+8为第二个参数EXCETPION_REGISTRATION的地址,esp+0x0c为CONTEXT的地址。CONTEXT结构体中含有异常发生时各个寄存器的值。系统会使用CONTEXT结构体中的值从异常发生处恢复执行。
        异常处理函数执行时的堆栈状况要牢牢记住。下面的SEH exploit和使用SEH对抗硬件断点都要用到。
        常见的SEH handler的代码如下:

        Seh_handler:
         mov eax,[esp+0xc]      ;获得CONTEXT地址
         ...............              ;一些中间操作 通常是操作CONTEXT中的各个寄存器
         mov cl,0xb8
         add dword [eax+ecx],xxx ; [eax+ecx]是CONTEXT.EIP,这里修改eip的值
         xor eax,eax
         ret


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (10)
雪    币: 611
活跃值: (251)
能力值: ( LV12,RANK:390 )
在线值:
发帖
回帖
粉丝
2
谈过理论,下面是应用。
二. SEH在virus中的应用
   SEH能让我们的asm代码更健壮,xfish的系列文章已经有描述了。直接看:
        http://bbs.pediy.com/showthread.php?t=86452
   同时可以用SEH去做免杀,对抗模拟器。
   前提假设是模拟器没法模拟异常。思路如下:
   call seh
   seh_handler:
            mov eax,[esp+0xc]
        mov cl,0xb8
        add dword [eax+ecx],5     ;跳过jmp语句,到virus处执行
        xor eax,eax
        ret
  seh:
        push fs:[0]
        mov fs:[0],esp
  @except:
        xor eax,eax
        mov [eax],0   
        jmp @except
  virus:
        .......
       
此处需要注意两点:
   a. 由于seh handler需要是绝对地址,故需要重定位
   b. 如果被感染文件有SEH保护,还需要修改PE文件中的SEH表。因为被感染后的可执行文件发生异常,控制权转移到系统,要调用SEH处理函数时,系统会判断该SEH处理函数有没有在PE文件的SEH表中。我感染后调试时发现异常处理函数总是未被调用才意识到该问题。

三、SEH在exploit中的应用
   在看exploit tutorial part 3 SEH Based Exploit时,我产生了很大的困惑。使用了SEH的函数栈的结构如下:
   
  图中Params下面的Address of exception handler,完整的来说,是一个EXCEPTION_REGISTRATION结构。所谓的SEH exploit就是覆EXCEPTION_REGISTRATION结构,让系统执行我们的shellcode。
exploit tutorial part 3 SEH Based Exploit 中给予的覆盖时的流程解释如下:
a. 覆盖的eip产生一个异常
b. 当前的SE Handler地址被修改成进程空间里某个dll中的pop,pop,ret的地址
c. 系统执行pop,pop,ret。在exception handler执行前,下一个SEH的地址被放在了ESP+8的位置上。通过pop.pop,ret 将这个地址放到eip中,执行在next SEH地址中的代码

a,b两步比较容易理解。c乍看之下,让人云里雾里的,尤其后面作者反复提到fake exception,我这种菜鸟就彻底晕了。其实,将c联系我们前面提到的异常处理函数原型,异常处理函数调用时栈的布局就不难理解了。
pop  ;esp+0 被弹出  
pop  ;esp+4 被弹出
ret   ;esp+8被弹出,作为eip
esp+8存储的是EXCEPTION_REGISTRATION的地址。通过pop,pop,ret ,函数将会跳转到EXCEPTION_REGISTRATION地址处执行。我们写在EXCEPTION_REGISTRATION的prev中的数据将会被当成代码执行。
于是乎,我们的seh exploit就能构造成如下的形式了:
[Junk][nSEH][SEH][Nop-Shellcode]
其中nSEH=jmp xxx的机器码
    SEH=某个dll中pop,pop,ret的地址

四、SEH在反调试中的应用
        调试器发现:
        push seh_handler
        push fs:[0]
        mov fs:[0],esp
       
        xor eax,eax
        int 3
   
        pop fs:[0]
        add esp,4
       
        test eax,eax
        je debugger_found
        ....
        ...
        seh_handler:
        mov eax,[esp+0xc]
        mov dword [eax+0xb0],0xffffffff
        inc [eax+0xb8]
        xor eax,eax
        ret
       
        硬件断点发现:
        硬件断点的原理是Dr0-Dr3寄存器存储四个断点的地址,Dr6存储哪个断点被触发,Dr7存储控制四个断点启用/禁用的标识。所以只要查看该四个寄存器就知道是否有硬件断点了。要在用户态查看寄存器的值,得触发一个异常,通过SEH handler中的PCONTEXT获得
        Push seh
        Push fs:[0]
        Mov fs:[0],esp
       
        Xor eax,eax
        Mov dword ptr [eax],0
        Pop fs:[0]
        Add esp,4
       
        Test eax,eax
        Jnz bp_found
        ....
        ...
        Seh_handler:
        Mov eax,[esp+0xc]
        cmp dword ptr[eax+0x04],0
        Jne hdbp_found
        Cmp dword ptr[eax+0x08],0
        Jne hdbp_found
        Cmp dword ptr[eax+0x0c],0
        Jne hdbp_found
        Cmp dword ptr[eax+0x10],0
        Jne hdbp_found
        Jmp seh_ret
Hdbp_found:
        Mov dword ptr[eax+0xb0],0xffffffff
Seh_ret:
        Add dword ptr[eax+0xb8],6
        Xor eax,eax
        ret
上传的附件:
2010-11-12 18:45
0
雪    币: 656
活跃值: (448)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
3
收藏一下 图片用什么做的?
2010-11-12 18:57
0
雪    币: 611
活跃值: (251)
能力值: ( LV12,RANK:390 )
在线值:
发帖
回帖
粉丝
4
直接从exploit tutorial part 3 存下来的。。。。
2010-11-12 19:25
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
5
如果本文早点写的话,还可以作为附录加入exploit 教程中,呵呵……
2010-11-13 21:54
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
6
现在加上也不晚啊
2010-11-14 12:53
0
雪    币: 585
活跃值: (578)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
7
SEH,标记备查
2010-12-13 12:21
0
雪    币: 216
活跃值: (144)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
8
有利用veh的吗?
2010-12-13 12:28
0
雪    币: 231
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
好文章呀,学习,看来我还差的很远呀
2010-12-27 13:03
0
雪    币: 67
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hqm
10
顶楼主一记
2010-12-27 20:49
0
雪    币: 123
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
楼主好文章,收藏学习
2010-12-28 08:48
0
游客
登录 | 注册 方可回帖
返回
//