在漫长的春招过程中,身为一个大三找实习的弱鸡,免不了被面试官捶打。
昨天被问到一个dll注入的问题,当时心想,正中我的下怀,唉,我就叽里呱啦把远程线程注入的实现过程讲了一下:
当然这是第一层,我知道面试肯定没有这么简单,我在第二层等着面试官。
果不其然,面试官问道:“唉,那么问题来了,你在不同的进程调用loadlibrary(),是怎么调用的?”
我以为到第二层就已经结束了。
没想到面试官非常兴奋地问道:“那么问题又来了,为什么dll在每个进程中默认加载机制一样?”
心里一惊 Σ(っ °Д °;)っ
硬着头皮回答道:“Windows默认系统dll在所有进程的加载基址不变,是因为所有进程公用一个内核空间,在内核空间对这里做了规定,所以加载基址一样。”
当然回答的时候,我知道这应该是不对的,所以一直用疑问的语气尝试让面试官给出结果。
这时候,我才意识到,原来面试官是在第5层。
然后我陷入了思考…
首先下面这句话,无疑是正确的。
Windows默认的是同一个系统中dll的文件加载位置是固定的。
然后下面这段话,无疑也是正确的。
那么当它们俩撞在了一起,就让我想起了矛盾相争的故事。“啊,我的茅牛逼,没有扎不破的盾,我的盾也牛逼,没有茅能扎破它”。
”每次加载基址变化的话,那么就绪要重定位,但是重定位的位置在每个进程中,不一定一样啊。”
面试官:“嗯,对,那你再想想,他是在什么时候进行处理的呢?”
我当时想的是,每次系统开启之后就不变了,那么我就赌一手:“每次系统开启的过程中,会进行重定位的处理,之后就不变了。”
面试官:“嗯嗯好,那下一个问题”。
我:疑惑脸,不知道自己回答的对不对,还是面试结束后再去看一下吧。
没想到这个问题老千层饼了。
下面进入正题。
ASLR机制:
这里有一篇是对为什么系统DLL加载基址不变的解释:
http://www.nynaeve.net/?p=198
简单概括:
似乎好像和我回答的有点相像。但这只是规定,我们就去看一下到底是不是这么一回事。
下面是用windbg查找kernel32.dll的基址(这里只是以kernel32为例)
通过查阅MSDN,知道,这个Flink指向的具体的数据结构类型是:_LDR_DATA_TABLE_ENTRY
但是至于这样子ASLR不改变进程中系统dll的基址的原因,我们还需要继续探究。
小弟才疏学浅,还得继续研究,留待搞清楚之后补齐。