作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++、嵌入式、Linux。
目录
别人的经验,我们的阶梯!
昨天,因产品需求,需要在Windows
操作系统下写一个小工具。
这个小工具中调用一个比较重要的DLL
动态库文件,来完成一些重要的功能。
一般来说,最直接的做法就是调用Win32 API
函数,来动态的加载、获取函数地址、释放:
LoadLibrary(...); GetProcAddress(...); FreeLibrary(...);
但是,由于这个动态库比较重要,如果直接把DLL
文件放在文件目录中,就增加了文件被反编译的风险。
也就是说为了提高DLL
文件的安全性,最好不要让用户看到/拿到文件;
即使拿到了文件,也不要让用户很容易的破解文件。
关于分析过程就不多说了,这里直接给出目前的处理方式:
使用了AES
对称加密算法,主要是为了管理秘钥简单。
加密后的文件liba_enc.png
与可执行文件放在一起。
此时,如果用户获取到了这个动态库,由于没有秘钥,理论上是无法解开这个文件的。
不过,道高一尺魔高一丈。。。
这个动态库最终肯定是要被加载到应用程序的内存空间中被使用的,因此在被加载之前,需要被使用者(也就是应用程序)解密。
那么,应该解密到哪里呢?
用来加载动态库的API
函数LoadLibrary()
,需要的参数是文件的路径。
也就是说:必须要把一个动态库文件的路径传递给该函数,才可以被正确的加载到内存中。
假如是在Linux
系统中,可以解压到/tmp
临时文件系统中。
在动态库使用期间文件一直存在;一旦使用结束就立刻删除掉。
但是在Windows
系统中没有临时文件系统之说。
即使存在类似的临时文件空间,即使该DLL
文件的使用周期非常短,仍然存在暴露给用户的可能性。
只要用户有机会能够看到这个解密后的文件,就有方法把它dump
出来,然后进行反编译...
目前,能想到的最好的方法就是:先把加密的DLL
文件解压到一块空闲的内存缓冲区中(比如:从堆空间中malloc
出来的一块空间),然后再按照动态库的加载流程从这块缓冲区中读取字节流,加载到动态库所属的代码空间中。
刚才说过,LoadLibrary(...)
函数只能接受文件路径作为参数,我们不能把缓冲区的首地址传给它,因此需要使用其它方式来加载。
刚好,在github
上看到这样一个开源C
代码:
图中描述的功能正是我所需要的,简直是量身定做:
只需要一个头文件MemoryModule.h
和一个C
文件:MemoryModule.c
,提供的函数也足够简单:
HMEMORYMODULE MemoryLoadLibrary(const void *, size_t);
FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR);
void MemoryFreeLibrary(HMEMORYMODULE);
与Win32
提供的3
个函数在语义上是对应的,唯一的区别是加载函数传入的参数是:缓冲区的地址和长度。
经过测试证明:这个方法工作的很好,很完美的解决了我的问题!
因为目前我只在Windows
平台上有这个需求,这个方法相当于重写了一套动态库加载函数。
那么,在Linux
系统上如果也存在类似的需求,是否也有类似的:从内存缓冲区加载动态库的实现?
我目前还没有发现类似的代码,如果您知道的话,不妨在留言中分享一下?灰常感谢!
------ End ------
github 项目地址:https://github.com/fancycode/MemoryModule
,感谢作者!
既然看到这里了,如果觉得不错,请您随手点个【赞】和【在看】吧!
如果转载本文,文末务必注明:“转自微信公众号:IOT物联网小镇”。