通过 argv 输入零字节到 C 程序
Input zero bytes to C program via argv
这是简单的 C 程序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int hex;
memcpy(&hex, argv[1], 4);
printf("hex %x\n", hex);
return 0;
}
我做了如下实验
./main `python -c 'print "\x01\x01\x02\x01"'`
输出是可预测的:hex 1020101
接下来我尝试在我的输入中放入一些零字节
./main `python -c 'print "\x01\x00\x02\x01"'`
结果让我大吃一惊
hex 10201
然后我检查了 python 到底输出到主输入:
python -c 'print "\x01\x00\x02\x01"' > test
hexdump -C test
00000000 01 00 02 01 0a |.....|
00000005
而且似乎 python 老老实实地把 \x01\x00\x02\x01 放到文件中并打印行尾符号。
我的理解是 argv[1] 应该是指向字节模式 01000201 所在内存的指针。在这种情况下,输出应该是 1020001 而不是 10201。
问题 - 零字节在哪里?
零字节是字符串终止符,因此在使用反引号时它永远不会被 shell 传递。我很确定内核也不会在第一个零之后传递任何字节,因为它应该如何知道要复制的参数的实际长度?
您可以通过
轻松验证这一点
echo `python -c 'print "\x01\x00\x02\x01"'` | hd
在您的程序中,您访问未初始化的内存是因为所有定义的第一个参数在第一个 '[=11=]'
之后结束。结果可能是确定性的,但本质上是未定义的。
这是简单的 C 程序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int hex;
memcpy(&hex, argv[1], 4);
printf("hex %x\n", hex);
return 0;
}
我做了如下实验
./main `python -c 'print "\x01\x01\x02\x01"'`
输出是可预测的:hex 1020101
接下来我尝试在我的输入中放入一些零字节
./main `python -c 'print "\x01\x00\x02\x01"'`
结果让我大吃一惊
hex 10201
然后我检查了 python 到底输出到主输入:
python -c 'print "\x01\x00\x02\x01"' > test
hexdump -C test
00000000 01 00 02 01 0a |.....|
00000005
而且似乎 python 老老实实地把 \x01\x00\x02\x01 放到文件中并打印行尾符号。 我的理解是 argv[1] 应该是指向字节模式 01000201 所在内存的指针。在这种情况下,输出应该是 1020001 而不是 10201。
问题 - 零字节在哪里?
零字节是字符串终止符,因此在使用反引号时它永远不会被 shell 传递。我很确定内核也不会在第一个零之后传递任何字节,因为它应该如何知道要复制的参数的实际长度?
您可以通过
轻松验证这一点echo `python -c 'print "\x01\x00\x02\x01"'` | hd
在您的程序中,您访问未初始化的内存是因为所有定义的第一个参数在第一个 '[=11=]'
之后结束。结果可能是确定性的,但本质上是未定义的。