64-bit Linux stack smashing tutorial: Part 1使用Get environment variable address gist获取环境变量地址。先决条件是首先通过echo 0 > proc/sys/kernel/randomize_va_space
禁用ASLR。
要点的内容是:
/*
* I'm not the author of this code, and I'm not sure who is.
* There are several variants floating around on the Internet,
* but this is the one I use.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *ptr;
if(argc < 3) {
printf("Usage: %s <environment variable> <target program name>\n", argv[0]);
exit(0);
}
ptr = getenv(argv[1]); /* get env var location */
ptr += (strlen(argv[0]) - strlen(argv[2]))*2; /* adjust for program name */
printf("%s will be at %p\n", argv[1], ptr);
}
为什么*2
用于调整程序名称?
我的猜测是程序名称在堆栈上方保存两次。
https://lwn.net/Articles/631631/中的以下图表提供了更多详细信息:
------------------------------------------------------------- 0x7fff6c845000
0x7fff6c844ff8: 0x0000000000000000
_ 4fec: './stackdump\0' <------+
env / 4fe2: 'ENVVAR2=2\0' | <----+
\_ 4fd8: 'ENVVAR1=1\0' | <---+ |
/ 4fd4: 'two\0' | | | <----+
args | 4fd0: 'one\0' | | | <---+ |
\_ 4fcb: 'zero\0' | | | <--+ | |
3020: random gap padded to 16B boundary | | | | | |
在此图中,./stackdump
用于执行程序。所以我可以看到程序名./stackdump
一旦保存在环境字符串之上。如果从Bash shell启动./stackdump
,Bashell会将其保存在包含密钥_
的环境字符串中:
_
(下划线。)在shell启动时,设置为用于调用正在执行的shell或shell脚本的绝对路径名。 环境或参数列表。随后,扩展到最后 扩展后的上一个命令的参数。也设置为 用于调用执行并放入的每个命令的完整路径名 环境导出到该命令。检查邮件时,这个 参数保存邮件文件的名称。
环境字符串位于堆栈之上。因此程序名称会在堆栈上方另一次保存。
答案 0 :(得分:1)
如果有人还在想为什么。这是因为除了在所有环境变量之前推送到堆栈之外,程序名称也存储在环境变量名称“_”中。
您可以通过将gdb附加到进程来检查这一点,并检查最后一个环境变量下面的堆栈内容。假设0x7fffffffabcd是最后一个环境变量的地址:
$ gdb -p <pid>
(gdb) x/20s 0x7fffffffabcd
存储在argv[0]
中的程序名称不会影响环境变量的地址,因为它位于堆栈上最后一个环境变量的顶部。
答案 1 :(得分:0)
将以下代码保存为stackdump.c
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/auxv.h>
int main(int argc, char *argv[]) {
char *ptr;
int i;
for (i = 0; i < argc; i++) {
printf(" argv[%d]: %p, %p, %s\n", i, argv + i, argv[i], argv[i]);
}
char * program = (char *)getauxval(AT_EXECFN);
printf("AT_EXECFN: , %p, %s\n", program, program);
char* path = getenv("PATH");
printf(" PATH: , %p, %s\n", path, path);
char* underscore = getenv("_");
printf(" _: , %p, %s\n", underscore, underscore);
}
首先,运行gcc -o stackdump stackdump.c
来编译代码。其次,执行echo 0 > proc/sys/kernel/randomize_va_space
。第三,运行./stackdump zero one two
给予:
argv[0]: 0x7fffffffe4a8, 0x7fffffffe6e5, ./stackdump
argv[1]: 0x7fffffffe4b0, 0x7fffffffe6f1, zero
argv[2]: 0x7fffffffe4b8, 0x7fffffffe6f6, one
argv[3]: 0x7fffffffe4c0, 0x7fffffffe6fa, two
AT_EXECFN: , 0x7fffffffefec, ./stackdump
PATH: , 0x7fffffffee89, /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/cloud-user/.local/bin:/home/cloud-user/bin
_: , 0x7fffffffefe0, ./stackdump
./stackdump
的三个副本位于程序的地址空间中,如上所示。其中两个地址的地址高于PATH,如下所示:
AT_EXECFN: 0x7fffffffefec, ./stackdump
_: 0x7fffffffefe0, ./stackdump
PATH: 0x7fffffffee89, /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/cloud-user/.local/bin:/home/cloud-user/bin
因此*2
的原因是_
环境变量和AT_EXECFN
auxiliary vector value。