我使用的是 Ubuntu (22.04.3) x86_64 系统。
我知道虚拟内存和页面一般是如何工作的,我也知道系统可以使用 ASLR。
不过我想知道在这个特定场景下 Ubuntu 系统到底会发生什么。
我在名为 test.c 的文件中有这个小程序:
#include <stdio.h>
int main(){
int a = 10;
a++;
printf("%p\n",(void*)&main);
}
我用“gcc test.c -o test”编译了这个文件。然后我运行命令“objdump -d test”,我得到了这个:
0000000000001149 <main>:
1149: f3 0f 1e fa endbr64
114d: 55 push %rbp
114e: 48 89 e5 mov %rsp,%rbp
1151: 48 83 ec 10 sub $0x10,%rsp
1155: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
115c: 83 45 fc 01 addl $0x1,-0x4(%rbp)
1160: 48 8d 05 e2 ff ff ff lea -0x1e(%rip),%rax # 1149 <main>
1167: 48 89 c6 mov %rax,%rsi
116a: 48 8d 05 93 0e 00 00 lea 0xe93(%rip),%rax # 2004 <_IO_stdin_used+0x4>
1171: 48 89 c7 mov %rax,%rdi
1174: b8 00 00 00 00 mov $0x0,%eax
1179: e8 d2 fe ff ff call 1050 <printf@plt>
117e: b8 00 00 00 00 mov $0x0,%eax
1183: c9 leave
1184: c3 ret
正如你所看到的,主地址是0x1149。
当我运行程序时,main的地址是不同的,并且每次运行它时都是不同的。我已经做了三次,得到了三种不同的结果:
0x55b032770149
0x5615f1082149
0x557829668149
我可以推断这与 ASLR 有关。这是我的问题:
-
我们如何从 0x1149 到例如 0x55b032770149 ?幕后发生的整个过程是什么?
-
C 程序中打印的地址(如 0x55b032770149)是我们程序的实际且确定的虚拟地址吗?
-
RIP 寄存器是否包含虚拟地址(例如 0x55b032770149)作为下一条要执行的指令的地址?