技术上没问题。八卦上出了问题。这次烦请不要再对号入座了,谢谢。
这个DirectShow的,大概是属于mov byte ptr [EXX+EAX+0xXX], 0这样的,其中,EAX可以控制,利用的就是找一个可以跳转的,写一个字节的0,让它跳到其他地方去,打个比方,我的quartz.dll加载到0x7Dxxxxxx,那么exp可以迫使其跳到0x7d00xxxx,当然你也可以让它跳转到0x7dxxxx00什么的,但这个九成九没有意义。
这里顺便说一句,如果不是写一个0,而是写一些可控的字符,第一个想法肯定是写到返回地址最高位上,然后加载dll或者heap spray都会比较稳定。此外,写栈上保留的ebp数据也是一个不错的方法,这种方法今年早些时候肯定大家都见过实战的exp。但在这里只写一个0的情况,后面这个方法并不适用。再多说一句,这里是byte,msjet里面有一个写WORD的情况,在这个世纪最开始的时候就有N(N>2)个人Fuzzing出来过,不过因为两字节对齐的问题,到现在都没有很好的利用方法,不然国内不知道多少asp+mdb的网站要遭殃。
知道了这一点,我们来还原一下作者的思路,当然要是我来写,不会这样写的,所以这里只能是猜测一下。
首先quartz.dll加载的地方不尽相同,我测试两台机器加载位置不一样,可能作者也发现了这个问题,而且非常巧的是,有时候0x7d00xxxx这一块并不是空闲的,所以最好的办法是把quartz.dll挤开,让最后执行到的地方避开不可控的位置。这里是高位,最好的办法是弄个.net的dll把它给占了,这就是exp里面看到最后(?)那个dll干的事情,这里必须在创建那个wmp(?)对象之前,也就是quartz.dll加载之前做。
然后可以确定的是,quartz.dll很委屈地跑到其他地方去了,一些比较可能的地方有0x10000000等,这个位置也不好。这里插一句,quartz.dll其实挺大的,要找个容身的地方并不容易,可能的情况是在低位找到这么大块位置也就将就了。不管在什么地方,作者可以先假定最后必然跳转到0xXX00XXXX,而且如果是低位,刨开0x04000000下面的和0x10000000以上的,把每个0xXX00XXXXX都占据就可以保证跳到自己的代码上了。这个通过.net dll也可以做到,exp里面好像是把0x05000000、0x06000000、0x07000000、0x08000000、0x09000000、0x0a000000、0x0b000000、0x0c000000都给占了。
最后,正主该登场了。如果quartz.dll被加载到0x05000000~0x0c000000之间的任意个位置,理论上最后必然会执行到.net dll占据的位置中。这里有几个条件,首先,必须要有足够的空闲空间给quartz.dll占据,如果用heap spray把所有的空闲都占了,quartz.dll只能朝更高的地方去落脚,这时候,理论如果刚好你heap spray的翻过了0x0X000000这个坎,且quartz.dll比较老实地加载到后面,那会成功,但是数学上计算一下,这个同你不用.net占据那几个位置成功的机率是一样的。其次,你要保证你确实占据了0x0X000000(X在5和c之间)这几个位置,这个比较难,因为不太清楚在你的.net dll加载前这些位置是否已经有人了,exp里面是从0x0c000000开始倒着加载的。按照先来后到的原则,顺序加载效果应该也一样,除非每个.dll有区别(事实上这几个.dll貌似没有什么区别),可能作者也有其他的想法,或者只是个习惯。