Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
DllShimmer — 轻松武器化 DLL 劫持。为任意 DLL 中的任意函数植入后门。 | Kitploit
工具/GitHubGitHub/print3m/dllshimmer
持久化机制渗透测试红队Payload 开发对抗性攻击
GitHubprint3m/dllshimmer

DllShimmer

轻松武器化 DLL 劫持。为任意 DLL 中的任意函数植入后门。

查看仓库
7508511个月前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

DllShimmer

轻松武器化 DLL 劫持。在不影响正常进程操作的情况下,向任意 DLL 中的任意函数植入后门。

DllShimmer 流程图

工作原理

DllShimmer 会解析原始 DLL 并提取导出函数的信息(名称、序号和转发器信息)。基于这些信息,DllShimmer 会生成一个 C++ 样板文件(.cpp)。生成的文件允许你向原始 DLL 导出的每个函数添加自己的代码,而不会干扰程序的正常运行。 无需逆向工程或插桩,因为 DllShimmer 不依赖函数签名(详见“局限性”)。

生成的第二个文件是 .def 文件,它确保代理 DLL 编译后导出的所有 DLL 与原始 DLL 具有相同的名称和序号。

编译后,代理 DLL 中的 EAT 与原始 DLL 中的 EAT 完全相同。所有导出函数的名称和序号均匹配,转发函数也会照常转发。 DllShimmer 不会像大多数工具那样显式转发所有函数,从而形成一种全新的、可疑的 EAT 结构。

安装

编译 Go 源代码,或下载已编译的二进制文件。

依赖:

  • x86_64-w64-mingw32-g++
  • x86_64-w64-mingw32-dlltool

使用方法

示例:

root@kitploit:~
# Backdoor version.dll (proxy to absolute path)
./DllShimmer -i version.dll -o project/ -x "C:/Windows/System32/version.dll" -m

# Backdoor random chat.dll (proxy to relative path)
./DllShimmer -i chat.dll -o project/ -x "lib/chat2.dll" -m

# Backdoor random app.dll (static linking to the original DLL)
./DllShimmer -i app.dll -o project/ -x "app2.dll" -m --static

参数:

-i / --input <path> [必需]

你想要植入后门的原始 DLL。

-o / --output <path> [必需]

DllShimmer 保存所有生成文件的目录路径。

-x / --original <path> [必需]

对于动态链接(默认),请提供代理 DLL 在目标系统上查找原始 DLL 的路径。

对于静态链接(--static),只需指定原始 DLL 的名称。系统将按照 Windows 上的默认加载顺序进行搜索。

-m / --mutex [可选]

启用此选项会向源文件添加互斥体,防止你的后门在单次程序运行期间被多次执行。所有原始函数仍将正常工作。

--static [可选]

启用代理 DLL(IAT)与原始 DLL(EAT)之间的静态链接。这会在输出目录中生成一个额外的 .lib 文件,作为静态编译时的原始 DLL。

与动态链接相比,该技术存在一些严重的局限性:

  • 你无法定义原始 DLL 的完整路径或相对路径。系统加载器仅使用代理 IAT 中的 DLL 名称,并在默认路径中搜索。
  • 调试信息有限。如果原始 DLL 加载失败,程序通常会直接崩溃,且无额外信息。

然而,在某些场景下,静态链接可能更隐蔽、更自然。

默认情况下:DllShimmer 始终使用 LoadLibraryA() 和 GetProcAddress() 函数进行动态链接。

--debug-file <path> [可选]

将调试日志保存到文件。程序运行期间,日志会持续写入文件。如果选择此选项,日志将不会打印到 STDOUT。

默认情况下:DllShimmer 始终将调试日志写入 STDOUT。

调试输出示例:

调试输出示例

局限性

  • 仅支持 x86-64 / AMD64 架构。
  • 通用代理代码很可能无法用于带浮点参数的函数,因为它们使用的寄存器与 DllShimmer 所用的整数寄存器不同。如果你知道函数签名,可以在生成的文件中手动调整。
  • 超过 12 个参数的函数无法使用,因为该数字已硬编码到 DllShimmer 模板中。
  • 有些大型混淆 DLL 带有奇怪的名称修饰、调用约定和技巧(例如已编译的 Qt 框架 DLL)。我不建议将它们用作代理 DLL。在这种情况下,DllShimmer 很可能会生成一些垃圾代码。

故障排查

开始故障排查之前:

  1. 阅读“局限性”。
  2. 确保你没有使用静态链接(--static)。使用动态链接(默认)更容易调试。
  3. 将调试输出保存到文件(--debug-file)。

在生成的 .cpp 文件中,我看不到原始 DLL 的所有导出函数。

原始 DLL 中被定义为“转发”的函数不会包含在 .cpp 文件中。但是,它们会出现在 .def 文件中。编译后它们也会被导出,与原始 DLL 完全一致。

加载原始 DLL 时出现奇怪的加载器错误 (126)

有时,即使你在 -x 参数中理论上指定了正确的相对路径,代理 DLL 在加载原始 DLL 时仍会显示错误,错误代码为 126。为什么不生效?!?

系统会在 当前目录 中搜索 DLL。在 98% 的情况下,该目录就是主 EXE 文件所在的位置,但有些程序(大多是旧版遗留程序)会使用例如 SetCurrentDirectoryW() 随意更改 当前目录。主程序知道这一更改,因此它能正确加载你的代理 DLL,而你却对此毫不知情,并尝试相对加载原始 DLL,而程序会在更改后的 当前目录 中搜索它。

此规则同时适用于原始 DLL 的静态和动态加载。遗憾的是,使用静态链接时,此问题更难发现,因为我们没有调试信息。系统加载器只会失败,然后就此结束。这就是为什么我始终建议优先使用默认的动态链接。

在动态链接的情况下,我们有两种选择:

  1. 根据新的 当前目录 情况调整 -x 参数中的路径。
  2. 动态更改 当前目录,以便在我们想要的位置搜索 DLL。

在静态链接的情况下,我们实际上只有一种选择:

  1. 将原始 DLL 移动到 当前目录。

TODO

  • 支持 C++ 修饰函数名
下载工具