c - 修改存在缓冲区溢出漏洞的C函数的返回地址

标签 c linux

我正在尝试修改以下 C 程序,以便 main 函数将跳过 printf("x is 1") 行,只打印“x is 0”。

 void func(char *str) {
         char buffer[24];
         int *ret;

         ret = buffer + 28; // Supposed to set ret to the return address of func
         (*ret) += 32; // Add the offset needed so that func will skip over printf("x is 1")
         strcpy(buffer, str);
 }

 int main(int argc, char **argv) {
         int x;
         x = 0;
         func(argv[1]);
         x = 1;
         printf("x is 1");
         printf("x is 0");
         getchar();
 }

正如注释所暗示的,ret 指针需要首先设置为函数的返回地址。然后我需要添加一个偏移量,将其推到我想跳过的线上。我在配备 2 个 Intel(R) Xeon(TM) CPU 3.20GHz 的 Linux 系统上运行此代码。我正在使用 gcc 版本 4.7.2 (Debian 4.7.2-5) 进行编译。我还尝试使用此 ( http://insecure.org/stf/smashstack.html) 链接中的 example3.c 作为引用。下面是使用 gdb 对 main 函数的反汇编:

 Dump of assembler code for function main:
    0x0000000000400641 <+0>:     push   %rbp
    0x0000000000400642 <+1>:     mov    %rsp,%rbp
    0x0000000000400645 <+4>:     sub    $0x20,%rsp
    0x0000000000400649 <+8>:     mov    %edi,-0x14(%rbp)
    0x000000000040064c <+11>:    mov    %rsi,-0x20(%rbp)
    0x0000000000400650 <+15>:    movl   $0x0,-0x4(%rbp)
    0x0000000000400657 <+22>:    mov    -0x20(%rbp),%rax
    0x000000000040065b <+26>:    add    $0x8,%rax
    0x000000000040065f <+30>:    mov    (%rax),%rax
    0x0000000000400662 <+33>:    mov    %rax,%rdi
    0x0000000000400665 <+36>:    callq  0x4005ac <func>
    0x000000000040066a <+41>:    movl   $0x1,-0x4(%rbp)
    0x0000000000400671 <+48>:    mov    $0x40075b,%edi
    0x0000000000400676 <+53>:    mov    $0x0,%eax
    0x000000000040067b <+58>:    callq  0x400470 <printf@plt>
    0x0000000000400680 <+63>:    mov    $0x400762,%edi
    0x0000000000400685 <+68>:    mov    $0x0,%eax
    0x000000000040068a <+73>:    callq  0x400470 <printf@plt>
    0x000000000040068f <+78>:    callq  0x400490 <getchar@plt>
    0x0000000000400694 <+83>:    leaveq
    0x0000000000400695 <+84>:    retq
 End of assembler dump.

使用我从示例中读到的内容,我的缓冲区长 24 个字节,我应该为 SFP 大小额外添加 4 个字节。这意味着我要添加 28 个字节才能到达 <+41> 的返回地址。然后看起来我想跳转到 <+73> 处的最后一个 printf 调用。这应该是 32 的偏移量。但是,当我执行代码时,仍然打印“x is 1”。我似乎无法找出原因。我的数学或假设有问题吗?

最佳答案

这看起来是获得 gdb 经验并验证您对堆栈和函数返回地址位置的期望是否正确的理想时机!

不过,我会建议您修改后的返回地址应该是 <+63>,而不是 <+73>,因为您需要运行函数设置代码(以传递参数等)。

关于c - 修改存在缓冲区溢出漏洞的C函数的返回地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29711974/

相关文章:

c - 在编译时初始化数组

C:在函数内部声明的数组

c++ - 在许多情况下,使用 XOR 运算符查找数组中的重复元素会失败

php - 在我的情况下将 jenkins 服务器放在哪里

c - 如何将多个值作为参数传递给 C 中的线程?

c - 为什么我的 C 代码没有生成我设置范围内的随机数?

linux - 如何在 Linux 上断开任意 TCP/IP 连接?

c - linux 字符驱动程序中的接口(interface)

c - pthread_create 不工作。传递参数 3 警告

java - 如何将 .java 或 .jar 文件转换为 Linux 可执行文件(没有 .jar 扩展名,这意味着它不是 .jar 文件)