Linux ASLR的一些实验 (1)
最近在调试一个漏洞,在利用信息泄露的洞的时候发现了一个比较好玩或者说和我预期不太一样的现象,即在Android或者Linux中,即使程序开启ASLR,DSO(Dynamic Shared Objects)的相对偏移却是固定的。即任意两个DSO加载位置的delta永远是固定值。除非中间有其他什么模块的干扰。
这就导致了一个问题:假如一个程序能够泄露某个模块的加载地址,那么就能够推算出其他所有模块的地址。而我的预期则稍稍有点不一样,我最开始是以为所有模块的加载都是随机的。
首先是标记为DT_NEEDED的模块,用ldd看可以发现,vDSO先不管,以libdl.so.2为基准,libc.so.6永远在它-0x39f000的地方,而ld-linux-x86-64.so.2则永远在它的+0x407000的地方。当然,这个只是我随便写的一个printf的程序,可能这几个库除了ld就是libc看起来比较“特殊”,但是对于其他程序而言,情况也是这样的。
对于dlopen的加载也没什么区别,可以看到永远libcalculate.so都是在前一个模块的+0x39D000处。不管是LAZY还是RTLD_NOW,都是一样。
对它们进行检测,可以发现PIE都处于Enabled的状态。
所以比较迷茫的情况下看了下glibc的源代码(对,这一块是ld做的,ld的源代码事实上绝大部分情况下都在glibc,[或者其他什么库里面,如果开发者愿意修改的话]),似乎从中发现了一些线索。