可执行文件名如何影响其内存地址偏移?
可执行文件名对栈帧基址偏移的影响解析
要搞懂这个问题,得从进程栈的初始化逻辑说起:
- 当程序被内核加载启动时,栈空间会被预先初始化,内核会把一系列数据压入栈的高地址区域(栈是从高地址向低地址生长的),这些数据包括:环境变量列表、命令行参数列表,以及
argc、argv指针数组。 argv[0]对应的就是你执行的可执行文件的名称(或完整路径),它的长度直接影响栈上初始数据的总占用空间——文件名越长,对应的字符串占用的栈字节数越多,连带整个参数区的总大小都会变化。
在禁用ASLR的前提下,进程的代码段、全局数据段地址是固定的,但栈的初始基址(%rbp/%ebp的初始值)并非固定,它的计算逻辑是:
初始栈基址 = 内核预设的栈起始高地址 - 栈初始数据总大小 - 栈对齐预留空间
也就是说,栈上初始数据的总大小变化,会直接导致初始栈基址的位置偏移——数据越大,栈基址会向更低的地址移动。
回到你的实验场景:
- 实验要求两个可执行文件名称长度相同,本质是为了保证
argv[0]的长度一致,进而让两个进程启动时栈上的初始数据总大小完全相同(假设环境变量也一致)。 - 这样一来,两个进程的初始栈基址位置就会完全相同,而局部变量
j相对于栈基址的偏移是由编译器固定生成的(比如%rbp-0x4这样的偏移),所以Dumb中j的地址和Dumber中j的地址之间的偏移是固定的,Dumber才能通过读取文件中的地址正确操作对应内存。 - 如果文件名长度不同,
argv[0]的长度差异会导致栈初始数据总大小变化,两个进程的初始栈基址就会产生偏移,局部变量的实际地址也就不一样了,Dumber读取的地址自然无法对应到自己进程中j的位置。
总结一下:文件名长度通过影响栈初始化时的初始数据总大小,间接改变了栈基址的初始位置,最终导致局部变量的逻辑内存地址偏移发生变化。
内容的提问来源于stack exchange,提问作者Dean Haklai
相关产品推荐
相关产品推荐

