利用DelayLoad来优化应用程序的性能及拦截API
对dll的调用,直到你的exe结束。它打印出dll被调用的情况的汇总,包括多少个dll被调用,每个dll有多少个函数被引入。
我在这里强调:DelayLoadProfile只是针对exe有效,当它涵盖你的程序所关联的所有dll的时候,有时会造成一点点复杂。DelayLoadProfile只给你哪个dll可以用DelayLoad开关的暗示,你最好在不确定的时候,使用原来的处理方法。 DelayLoadProfile:详细描述 其实DelayLoadProfile的原理很简单:重定向 exe中,IAT的函数的指针到一段根区。根区简单的标志一下,引入的函数被调用了。然后,跳入原来的Win32加载提供的IAT地址。只是,难的是如何实现。 第一,你必须决定,要在哪里运行你的代码,实现对exe的IAT入口的更改,把他们指定到那段根区去。这些都是在进程外完成。这样可以避免你的代码牵涉到目的exe进程中。这个可以用遍历所有的数据结构,定位和修改IAT结构的方法。我在这里利用了很多ReadProcessMemory调用。 接着的艰苦工作是要在和目的exe相同的进程空间里完成。几乎是很琐碎的工作:遍历所有的数据结构,建立根区,从定向IAT入口,然后在完成的时候,汇总结果。然而,为了完成进程空间的工作,在exe进程运行的时候,一些 DelayLoadProfile代码必须被加载到目的exe的进程空间。这个是我要做的。 当确认到需要在目的进程中,加载我的代码的时候,下个问题就是如何把我的代码加入到目的进程中。其中一个选择就是,要求用户连接我的DelayLoadProfile库,这个会造成用户的很大量的对他们源代码工程,或者Makefile的更改,所以,我不能采用,现在需要一个完全自动化的方法。 在这点上,我想到了加载程序,然后,插入我的DelayLoadProfiledll进去,一个技术就是用CreateRemoteThread,在目标进程,创建一个LoadLibrary的线程。我放弃了这个,因为,win9x中,不提供CreateRemoteThread. 很久以前的MSJ读者可能记得我5年前写的一个叫APISPY32的程序。它加载一个进程,插入一个dll来记录API的调用。那个有点像我今天的DelayLoadProfile工作。然而,我在Win200中,调用那个dll失败。有一点点问题。我觉得现在是时候要重读那段代码,并且改正那个错误了。 继续深入: 重新温习一下,DelayLoadProfile包含2部分,一,是进程加载功能,它会注射一个dll到你的进程的地址空间。然后,那个dll扫描你的所有的exe IAT,重新定向他们到dll创建的根区中。当你的程序完成后,注射的dll会扫描所有的根区,统计出多少dll和函数它调用的。如果你曾经用过APIMON的相关部件,你将认出类似的技术细节。 完成所有的工作,包括 监视 一个程序的引入的dll,叫DelayLoadProfileDLL.(看Figure 1).它用到DLL_PROCESS_ATTACH和DLL_PROCESS_DETACH来初始化2个主要的工作。 当DllMain获得DLL_PROCESS_ATTACH的消息的时候,DelayLoadProfileDLL调用PrepareToProfile(),在PrepareToProfile中,代码加载目的EXE的IAT,对于每个它发现的引用的DLL,代码还检测是否安全的重定向IAT。通过IsModuleOKToHook函数来检测,大多数情况下,是安全的,因此,PrepareToProfile包括了RedirectIAT函数。 RedirectIAT是比较复杂的函数。如果你理解了 winini.h中的引入相关数据结构,你将得到很大的帮助。首先,函数定位IAT和相关的引入名字表,然后,计算有多少个IAT入口,扫描所有的IAT,查找NULL的指针。得到了数目后,程序将创建一个DLPD_IAT_STUB根区,每个根区对应一个IAT入口。 最后,代码重新扫描IAT,获取每个IAT入口的地址,用根区的一个包含JMP指令的地址,替换IAT入口。它还扫描下一个IATDLPD_IAT_STUB根区。我在后面将还会继续解析。 在重定向IAT入口的根区中,有2个值得提起:1,IAT常常被放到EXE的只读段,通常,尝试改写只读段,会引起访问违规,幸运 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |