DLL劫持算是一个很古老的技术了,早在XP时代就有臭名昭著的lpk.dll劫持,病毒通过伪装系统lpk.dll达到注入目标进程,为什么会被劫持呢?因为在程序执行的时候会在当前目录搜索lpk.dll文件,如果文件存在就会被加载到进程地址空间。
DLL劫持原理: DLL劫持技术当一个可执行文件运行时,Windows加载器将可执行模块映射到进程的地址空间中,加载器分析可执行模块的输入表,并设法找出任何需要的DLL,并将它们映射到进程的地址空间中。
由于输入表中只包含DLL名而没有它的路径名,因此加载程序必须在磁盘上搜索DLL文件。首先会尝试从当前程序所在的目录加载DLL,如果没找到,则在Windows系统目录中查找,最后是在环境变量中列出的各个目录下查找。利用这个特点,先伪造一个系统同名的DLL,提供同样的输出表,每个输出函数转向真正的系统DLL。程序调用系统DLL时会先调用当前目录下伪造的DLL,完成相关功能后,再跳到系统DLL同名函数里执行。这个过程用个形象的词来描述就是系统DLL被劫持(hijack)了。
伪造的dll制作好后,放到程序当前目录下,这样当原程序调用原函数时就调用了伪造的dll的同名函数,进入劫持DLL的代码,处理完毕后,再调用原DLL此函数。
这种补丁技术,对加壳保护的软件很有效,选择挂接的函数最好是在壳中没有被调用的,当挂接函数被执行时,相关的代码已被解压,可以直接补丁了。在有些情况下,必须用计数器统计挂接的函数的调用次数来接近OEP。此方法巧妙地绕过了壳的复杂检测,很适合加壳程序的补丁制作。
一些木马或病毒也会利用DLL劫持技术搞破坏,因此当在应用程序目录下发现系统一些DLL文件存在时,如lpk.dll ,应引起注意。
思路: 我们拿winmm.dll劫持做演示,通常的劫持技术是导出和winmm.dll同样的函数并提供相同的参数,当程序运行后加载winmm.dll会事先在当前目录查找,此时如果你编写的伪装winmm.dll在当前目录就会被加载到进程空间,如果程序还调用了里面的函数就会调用你编写的函数你必须保证可以正常运行你得调回原winmm.dll中的函数。 这样来回调用大大降低了效率,而且易语言导出的函数的特殊性大大降低了效率甚至部分程序还不能正常的回调。 那有没有办法解决这个问题呢? 于是我想到了能不能调用函数的时候直接跳转到原函数呢 这样大大降低了劫持影响的效率 比如 程序a.exe调用 a.dll 里面的 test函数 劫持后 程序a.exe调用a.dll里面的test的时候 会先调用我们劫持的dll里面的test然后跳转到a.dll里面的test 这样就相当于调用一个函数变成了调用两个函数 我们完全可以这样 调用我们的test的时候 直接跳转到原函数 而且我们的导出函数不需要提供任何参数跟返回值 这简直太棒了!! DLL公开的子程序就是只用作导出函数请不要加任何代码没有意义。
例程:
补充: 如果想自己回调某个函数拦截修改功能,请把pszProcName数组变量对应的成员名称给删除 然后自己修改对应的导出函数 提供原函数同样的参数跟返回值
|