介紹
内存损坏漏洞这个话题,对于初学者来说是一道坎。当我第一次开始在Windows操作系统上探索这个话题时,我立刻被现代的、公开的、专门针对这个话题的信息的奇缺震惊了。因此,这篇文章的目的并不是提供新奇的内容,而是要记录自己在探索这个话题时踩过的坑,同时,也是为相关问题的探索过程做个记录。除此之外,还有一个目的为了整合和更新与漏洞缓解系统演变相关的信息,因为这些信息通常散落在不同的地方,并且有些已经过时了。这种演变使得现有的漏洞利用技术变得更加复杂,在某些情况下甚至使这些技术完全失效。当我探索这个主题时,我决定通过记录自己在现代操作系统上使用现代编译器进行的一些实验和研究,来帮助初学者来解决这些问题。在本文中,我们将专注于Windows 10和Visual Studio 2019,并使用我编写的一系列C/C++工具和易受攻击的应用程序(这些软件可以从本人的Github存储库进行下载)。在这个系列文章中,我们要着手进行的第一项研,将专注于在Wow64下运行的32位程序中的堆栈溢出问题。
经典的堆栈溢出漏洞
经典的堆栈溢出是最容易理解的一种内存破坏漏洞:一个易受攻击的应用程序包含这样一个函数,该函数会在没有验证处于用户控制下的数据的长度的情况下将其写入堆栈。这使得攻击者可以:
- 向堆栈写入一个shellcode;
- 覆盖当前函数的返回地址,使其指向shellcode。
如果堆栈能以这种方式被破坏而不破坏应用程序,那么当被利用的函数返回时,shellcode将被执行,具体如下面的示例所示:
#include#include#includeuint8_t OverflowData[] ="AAAAAAAAAAAAAAAA" // 16 bytes for size of buffer"BBBB"// +4 bytes for stack Cookie"CCCC"// +4 bytes for EBP"DDDD";// +4 bytes for return addressvoid Overflow(uint8_t* pInputBuf, uint32_t dwInputBufSize) {char Buf[16] = { 0 };memcpy(Buf, pInputBuf, dwInputBufSize);}int32_t wmain(int32_t nArgc, const wchar_t* pArgv[]) {printf("... passing %d bytes of data to vulnerable function