在 C 语言中为堆栈溢出而苦苦挣扎

Struggling with stack overflowing in C

提问人:Roee Toledano 提问时间:10/26/2023 更新时间:10/26/2023 访问量:53

问:

我正在尝试堆栈溢出我编写的这个简单程序:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int win(){
    printf("%s\n", "you overflowed this stack succesfully!");
    return 0;
}

int main(int argc, char** argv){
    char buffer[100];
    strcpy(buffer, argv[1]);
    return 0;
}

这是使用 GDB 的反汇编:

(gdb) disas main
Dump of assembler code for function main:
   0x0000000000001163 <+0>:    push   %rbp
   0x0000000000001164 <+1>:    mov    %rsp,%rbp
   0x0000000000001167 <+4>:    add    $0xffffffffffffff80,%rsp
   0x000000000000116b <+8>:    mov    %edi,-0x74(%rbp)
   0x000000000000116e <+11>:    mov    %rsi,-0x80(%rbp)
   0x0000000000001172 <+15>:    mov    -0x80(%rbp),%rax
   0x0000000000001176 <+19>:    add    $0x8,%rax
   0x000000000000117a <+23>:    mov    (%rax),%rdx
   0x000000000000117d <+26>:    lea    -0x70(%rbp),%rax
   0x0000000000001181 <+30>:    mov    %rdx,%rsi
   0x0000000000001184 <+33>:    mov    %rax,%rdi
   0x0000000000001187 <+36>:    call   0x1030 <strcpy@plt>
   0x000000000000118c <+41>:    mov    $0x0,%eax
   0x0000000000001191 <+46>:    leave
   0x0000000000001192 <+47>:    ret
End of assembler dump.
(gdb) disas win
Dump of assembler code for function win:
   0x0000000000001149 <+0>:    push   %rbp
   0x000000000000114a <+1>:    mov    %rsp,%rbp
   0x000000000000114d <+4>:    lea    0xeb4(%rip),%rax        # 0x2008
   0x0000000000001154 <+11>:    mov    %rax,%rdi
   0x0000000000001157 <+14>:    call   0x1040 <puts@plt>
   0x000000000000115c <+19>:    mov    $0x0,%eax
   0x0000000000001161 <+24>:    pop    %rbp
   0x0000000000001162 <+25>:    ret
End of assembler dump.
(gdb)

我的想法是将主函数的返回地址覆盖到 win() 的地址。我以为给出 100 个 NOP 操作码之类的参数(也尝试了更大和更小的数字),然后 win() 中第一行的地址会起作用,但我一直收到分段错误。

我的想法有问题吗? 这是我执行的命令(在 gdb 中):run $(perl -e 'print"\x90"x100 . "\x4911000000000000"')

注意:我在 x86 机器上,所以我向后写了地址,因为它的小端序

c 堆栈 缓冲区溢出

评论

2赞 Mike Nakis 10/26/2023
您尝试执行的不是堆栈溢出。它是(堆栈)缓冲区溢出或缓冲区溢出,但不是堆栈溢出。
1赞 teapot418 10/26/2023
为什么选择NOP?您是否希望 CPU 会跳入其中?
0赞 Roee Toledano 10/26/2023
是的,我尝试制作一个 NOP 雪橇,然后无论返回地址实际存储在哪里,如果返回地址被覆盖,CPU 都会继续跳跃,直到它到达我输入的地址
1赞 Eric Postpischil 10/26/2023
NOP 雪橇在这里不起作用。NOP 滑夹用于您知道 CPU 可能执行指令的大致位置,因此您将 NOP 从可以执行指令的第一个位置放置到(至少)在最后一个位置之前,然后是您想要执行的指令。堆栈用于数据,而不是指令。(堆栈区域通常被标记为不可执行,因此即使您尝试将程序控制转移到堆栈中,处理器也不会执行堆栈中的指令。...
1赞 Eric Postpischil 10/26/2023
...要通过修改返回地址来利用缓冲区溢出,您必须创建一个字符串,该字符串将所需的返回地址准确地放在函数返回地址在堆栈上的位置。为此,您需要知道被调用进程堆栈帧的格式,或者至少知道从缓冲区到返回地址的距离。

答: 暂无答案