Ubuntu10.04,C,gcc,x86 Intel proc:
当试图使用printf打印环境变量的地址时,打印的地址在这个玩具程序中是不正确的(这是一个有意识的反向版本,在这个版本中,我试图通过将地址值保存在堆中来隔离问题的来源,而不是在读取时直接使用指针来覆盖它,并使用直接生成相同问题的指针):
#include <stdio.h>
#include <stdlib.h>
int main(){
const char* d = getenv("TEST");
unsigned i = (unsigned*) malloc(sizeof(unsigned));
i = (unsigned*) d;
printf("%s at location 0x%8d.\n", "TEST", i);
}编辑:与此(原件)版本相同的问题)
int main(){
const char* d = getenv("TEST");
printf("%s at location %p.\n", "TEST", d);
return 0;
}这个问题与如何打印指针无关。请继续读。
如果我将程序更改为不打印测试地址,而是将测试更改为字符串(其值),则没有问题。
但是,返回的地址不是环境变量在输入打印子例程之前实际位于的地址;通过上述设置,应该打印该地址。在eax寄存器中使用main的反汇编和测试地址,我被引用到测试变量的正确位置,这比main在我的系统上大约0 0xbffffiii的堆栈帧(i任意十六进制值)要低一些。打印的地址值为0xbfeiiii。
我不明白。这是否是一种安全防范措施,以防止环境变量被覆盖(例如,粉碎堆栈)?如果是,编译器是否真的像我上面那样跟踪地址的传输,并悄悄地调整它的值?
还是我漏掉了什么?(可能)
非常感谢。
P.S.:为了消除可想象的问题来源,我首先编译时没有任何选项,然后是: gcc -O0 -static -fno-stack- -g程序。
发布于 2011-08-23 14:44:41
我想出来了,在R.的评论之后。他把我引向ASLR的方向。
我不熟悉ASLR堆栈保护。我描述的原因是ASLR对内存地址空间进行了加扰,以防止预测相对于它的变量的位置。一直以来,在LINUX内核中,ASLR都是默认打开的。
为了了解我的意思,获取su特权,然后输入(发送的确切整数可能会根据发行版的不同而变化;在我的发行版上,它是0,默认是2。还最好通过第一次查看文件来确认文件中只有一个整数,就像在我的系统上一样):
cd /proc/sys/kernel
export OLD=$(less randomize_va_space) // save old value to restore after
echo 0 > randomize_va_space // 0 == turn off ASLR然后再运行我的小程序:它将报告我期望的地址(大约0 0xbffffiii)。之后,显然,恢复旧的保护使用
echo $OLD > randomize_va_space非常感谢每一个花了一些时间来帮助你的人。
发布于 2011-08-22 21:44:35
这不是打印地址的正确方法。只需使用%p格式打印(void*)d。
printf("%s at location 0x%p.\n", "TEST", (void*)d);发布于 2011-08-22 21:47:17
将char*指针存储在unsigned变量中可能在某些系统上工作,但不是可移植的。例如,在我的64位Ubuntu框sizeof(char*)==8和sizeof(unsigned)==4上。在整数变量中存储指针的可移植方式是使用intptr_t类型。
或者,简单地打印地址,请使用%p,如下所示:
#include <stdio.h>
#include <stdlib.h>
int main() {
const char* d = getenv("TEST");
printf("%s at location %p.\n", "TEST", d);
}在我的Ubuntu盒子上,这个打印出来
TEST at location (nil).或
TEST at location 0x7fff8cf34628.取决于是否设置了$TEST ( couse的地址可能有所不同)。
https://stackoverflow.com/questions/7153946
复制相似问题