嗨,我正在使用Ubuntu,只是关闭了我的ASLR来检查2个文件(dumb.c和dumber.c)
哑巴正在创建文件并输入变量地址
dumber正在阅读并进行打印我有一个问题要弄清楚为什么在某些计算机上它可以打印16而其他计算机32767
哑巴
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int i = 7;
int j = 12;
int k = 15;
int *p = &j;
FILE *fp;
if(0 == (fp = fopen("dumb.txt", "w")))
{
printf("well, that didn\'t work!\n");
return -1;
}
fprintf(fp, "%p\n", (void*)p);
printf("Address from Dumb: %p, value: %d\n", (void *)p, *p);
if(fclose(fp))
{
printf("oh well.");
return -1;
}
sleep(300);
return EXIT_SUCCESS;
}
dumber.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int i = 8;
int j = 16;
int k = 32;
int *p = &j;
FILE *fp;
if(0 == (fp = fopen("dumb.txt", "r")))
{
printf("well, that didn\'t work!\n");
return -1;
}
fscanf(fp, "%p\n", &p);
if(fclose(fp))
{
printf("oh well.");
return -1;
}
printf("\nDumber Address: %p\n", (void *)p);
printf("p points to: %d\n", *p);
return EXIT_SUCCESS;
}
最佳答案
在dumber.c
中,您有:fscanf(fp, "%p\n", &p); /* getting address dumb process put there */
然后您有:printf("p points to: %d\n", *p); /* reading memory content at that address */
因此,在哑进程中,您将读取哑进程放置在其中的地址,从这一点来看,p
并不指向j
。
现在,通常来说,由于这两个主电源是不同的进程,因此,不管ASLR如何,哑地址所见的内存地址的内容很可能会与哑地址的相同地址处的值不同。
这就是进程的工作方式(我假设这些进程在Linux \ Windows \ Mac中运行),它们被加载到具有不同虚拟和物理地址映射的不同物理地址,并且您也不知道在哑进程中此地址是否指向一个有效地址。
现在,这里发生的是当您使用ASLR运行时,两个进程之间的进程地址空间(进程使用的虚拟地址)肯定不同。
没有ASLR进程的地址空间对于所有进程都是相同的,无论如何,物理地址可能会不同。由于两个进程的堆栈使用情况都相同,因此哑进程将j
的偏移量(虚拟地址)写入文件,而哑进程读取该偏移量,并且由于哑进程的j
与哑进程具有相同的偏移量,您将访问dumber的j
。使用ASLR时,哑巴看到的地址是哑巴进程的有效地址,但很可能不是哑巴的有效地址(可能没有针对该地址的哑巴映射)
您可以通过在其中一个进程中更改j
的位置来验证它,执行此操作,并且在哑进程中将永远不会看到16打印为j
所指向的地址上的值。