【问题标题】:Writing to memory beginning by null bytes以空字节开始写入内存
【发布时间】:2016-05-22 08:24:01
【问题描述】:

假设这段代码:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    int main(int argc, char** argv){
    char fonction[50] = "/usr/bin/passwd ";
    char messageAccueil[100] = "changement du mot de passe de  : ";
    if(argc == 1){
        printf("vous devez passer un username en parametre \n");
        return 1;
    }
    printf(messageAccueil);
    printf(argv[1]); //<-- format string vulnerability here !!
    if(strcmp(argv[1], "root")==0){
        printf("vous ne pensiez quand meme pas pouvoir changer le mot de passe de root si facilement ?\n");
        return 1;
    }
    printf("\n");
    strncat(fonction,argv[1],38);
    system(fonction);
    return 0;
}

我想利用格式字符串漏洞来执行shell, 所以,我想用我存储在环境变量中的shellcode的地址来重写GOT中的strcmp函数地址。

gdb 给了我:

(gdb) info functions
0x0000000000400570  strcmp@plt
(gdb) disas 0x400570
Dump of assembler code for function strcmp@plt:
0x0000000000400570 <+0>:    jmp    QWORD PTR [rip+0x20070a]#0x600c80 <strcmp@got.plt>
0x0000000000400576 <+6>:    push   0x6
0x000000000040057b <+11>:   jmp    0x400500
End of assembler dump.

所以我想把我的shellcode地址写到0x00600c80

如何将 nullbyte 传递给我的 ./changepasswd 文件?

我实际上正在尝试这个漏洞:

/changepasswd $(echo -e '\x80\x0c\x60\x00____\x84\x0c\x60\x00')%65527d%136\$x%59017d%137\$x

给我地址600c845f

\x00 一样没有影响,也不会存储到堆栈中。

我发现地址以 00 开头的事实可能是 ascii armouring 问题,但我的系统中完全没有 exec-shield 选项。

所以我正在寻找一种方法将 00 写入我的堆栈让我的 GOT 地址由 00 以外的其他东西开始..

【问题讨论】:

  • 当然是一票接近。

标签: c security format-string


【解决方案1】:

这里有两个问题。或者,更好地说,有两种可能性。

首先,有一个 shell 问题:如何将包含 NUL 的字符串作为命令行参数传递给实用程序。

Shell 变量不能包含NULs,因此无法构造参数字符串并将其作为参数传递。 [注 1] 但是,您可以构造一个包含 NUL 的流并将其通过管道传输到某个实用程序的 stdin 中。剩下的只是找到一个实用程序,将其输入转换为其他实用程序的命令行参数;那将是xargs。因此,您可以尝试以下方法:

printf '\0This is an argument' | xargs -I{} ./victim {}

但是,由于第二个问题,这是行不通的(xargs 的大多数实现甚至不会让您尝试它 [注 2]):mainargv 参数是一个数组NUL-terminated 个字符串,因此每个命令行参数都由第一个 NUL 终止。因此,即使您设法找到将所有字节传递到 argv 数组的方法,该实用程序也会将 NUL 视为终止参数,而不是作为参数的一部分。 (例如,printf(argv[1]) 将打印第一个参数中的字节,直到它到达 NULNUL 表示格式字符串的结束。)

但是您不会找到这样做的方法,因为exec* 系统库函数(其中一个是将参数传递到另一个可执行文件所必需的)也会将NUL 视为终止相应的参数。由于exec* 函数需要将参数复制到新的可执行映像的地址空间中,并且当到达参数末尾时复制将终止,NUL 后面的任何字节都会不要复制。


注意事项:

  1. Shell 有不同的方法来处理使用命令替换插入NULs 的尝试。例如,Bash 只会删除 NULs,但其他 shell 可能会在第一个 NUL 处终止替换。

  2. 作为记录,xargs 的 Gnu 实现将产生以下有用的消息:

    xargs:警告:输入中出现 NUL 字符。它不能在参数列表中传递。您的意思是使用 --null 选项吗?

【讨论】:

  • 那么为什么我的 \x00 字符没有结束我的论点?通过传递$(echo -e '\x80\x0c\x60\x00____\x84\x0c\x60\x00')%65527d%136\$x%59017d%137\$x,所有字符串都作为参数传递,但只有 \x00 被忽略并且不存储在堆栈中
  • @gfrancqu:因为 bash 在执行 $(...) 替换时会删除 NUL 字符。并非所有的 shell 都这样。有些会在第一个 NUL 处终止参数。我想我本可以提到这一点。
  • 这仍然是 python、perl 或任何其他语言的问题吗?
  • @gfrancqu:执行可执行文件的唯一方法是使用exec*。请再次阅读我的答案,然后阅读一些手册页。 (如果你想写漏洞利用,你需要做一些研究:))
猜你喜欢
  • 2013-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-17
  • 2016-02-12
  • 2015-10-03
  • 2019-10-09
相关资源
最近更新 更多