一种保护应用程序的方法 模拟Windows PE 加载器,从内存资源中加载DLL 1、前言 目前很多敏感和重要的DLL(Dynamic-link library) 都没有提供静态版本供编译器进行静态连接(.lib 文件),即使提供了静态版本也因为兼容性问题导致无法使用,而只提供 DLL 版本,并且很多专业软件的授权部分的API,都是单独提供一个 DLL 来完成,而主模块通过调用DLL 中的接口来完成授权功能。虽然这些软件一般都采用了加壳和反调试等保护,但是一旦这些功能失去作用,比如脱壳,反反调试,HOOK API 或者干脆写一个仿真的授权 DLL(模拟授权 DLL 的所有导出函数接口),然后仿真的DLL 再调用授权 DLL,这样所有的输入首先被仿真 DLL 截获再传递给授权 DLL,而授权 DLL 的输出也首先传递给仿真 DLL 再传递给主程序,这样就可以轻易的监视二者之间的输入输出之间的关系,从而轻易的截获 DLL 中的授权信息进行修改再返回给主程序。 2、目前隐式调用敏感 DLL 中可能存在的安全隐患 以下通过两个软件的授权 DLL 来说明这种问题的严重性。如下是两个软件中授权 DLL 的部分信息,如下图所示: (图1) 通过工具 OllyICE 可以轻易的看出 IoMonitor.exe 调用授权 DLL(XKeyAPI.DLL),这样就很容易在调用这些 API 的地方设置断点,然后判断输入输出的关系,从而达到破解的目的。 (图2) 通过工具OllyICE 可以轻易的看出sfeng.DLL 中导出了很多函数,其中含义也很明显。GetHDID 获取硬盘的ID,GetCpuId 获取 cpu 的ID,WinAntiDebug 反调试接口。而这些都是主程序需要调用的,比如:主程序通过GetHDID来获取硬盘编码,以这个硬盘 ID 的伪码来生成授权码,破解者很容易修改这些接口的输出值或者干脆写一个sfeng.DLL 来导出跟目标 sfeng.DLL 一模一样的导出函数,而主程序却完全不知晓。只要用户有一套授权码就可以让 GetHDID 不管什么机器都返回一样的值,从而达到任何机器都可以使用同一套授权码。 (图3) 如上图所示,直接修改 DLL 中函数GetHDID(RVA 地址:0093FF3C 开始)的实现,让它直接返回固定的硬盘 ID 就可以达到一个授权到处使用的目的。其中:‖WD-Z=AM9N086529ksaiy‖为需要返回的已经授权的硬盘 ID,我们直接返回这个值即可。把原来 0093FF3C 部分的代码用 nop 替换掉,添加 Call 008FFF60,后面添加字符串‖WD-Z=AM9N086529ksaiy‖,Call 008FFF60 之后,ESP=Call 后的返回地址(Cal...