Dll 劫持初探
前言
前几周做了一个小工具 HijackGen,反响还不错,今天就来简单介绍一下 dll 劫持的原理和实现,具体的实践大家也可以参考文档。
基本概念
Dll 劫持 (dll hijack) 是一种常见的攻击手段,通过劫持系统 dll 或自定义 dll 实现恶意代码的注入。
原理
劫持系统 dll
当程序加载系统 dll 时,若未指定 dll 的完整路径 (这种情况相当常见),Windows 会大致按照以下顺序搜索 dll (随 Windows 版本不同可能会有差异):
- 当前目录
- 系统目录
- Windows 目录
- 环境变量 PATH 中指定的目录
可以看到,当前目录优先级最高,因此可以将恶意 dll 重命名为程序需要的系统 dll 并放置在当前目录,从而实现劫持。
注意:在注册表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
中列出的 dll 不会被劫持。
当然,被掉包的 dll 应该实现原 dll 的所有导出函数,否则可能会导致程序崩溃。
实现方式见下文。
劫持自定义 dll
这一部分就很简单了,我们通过创建一个新的 dll,重命名为原 dll 的名称,并在其中实现原 dll 的所有导出函数。这样,当程序加载这个新的 dll 时,实际上是加载了我们自己实现的代码。
这个方法也叫做 “dll 代理”(dll proxy)。
实现
劫持系统 dll
在代码中,我们需要找到目标 dll 的路径,通过 LoadLibrary
加载该 dll,之后通过 GetProcAddress
获取真正的函数地址。随后,我们需要导出获取到的真正函数,并且导出的名称必须与原 dll 对应函数一致。
关键代码如下:(以 version.dll
的 GetFileVersionInfoA
函数为例)
1 |
|
最后在 dll 的 DllMain
函数中调用 InitHijack
函数即可。
劫持自定义 dll
劫持自定义 dll 时利用转发函数的方式实现,将调用转发到原 dll 的对应函数。
如果使用 .h 头文件,那么我们需要使用类似 #pragma comment(linker, "/EXPORT:...")
的语句来导出函数。
1 |
|
如果使用 .def 文件,那么我们需要在 .def 文件中添加 EXPORTS
语句。这种方式仅限 gcc/g++,msvc 不支持。
1 |
|