You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CGO加载库前调用SetDefaultDllDirectories防范DLL劫持?

问题描述

我需要保护Go应用免受DLL劫持威胁。当前应用存在漏洞:部分加载的DLL会优先从本地路径(./)查找系统DLL(如winmm.dll)。为解决该问题,我在main()函数开头调用了以下代码:

windows.SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32)

该调用对后续通过完整本地路径加载的DLL有效,但对CGO导入的库无效。通过Process Explorer观察到winmm.dll仍会从本地路径查找,推测CGO在main()执行前已完成该库的导入与加载。我通过以下方式在CGO中加载库:

#cgo LDFLAGS: -L . -lmylib
#include <string.h>
#include <stdlib.h>
#include <mylib.h>

请问是否有办法让main()中的SetDefaultDllDirectories()调用对CGO加载的库生效?

解决方案

由于CGO依赖的库会在Go的main()函数执行前完成加载,因此main()中设置的DLL搜索路径无法覆盖这一阶段的加载行为。你需要在任何DLL加载之前设置默认搜索路径,以下是两种可行方案:

方案1:使用C构造函数提前设置路径

在CGO代码中添加一个带有__attribute__((constructor))标记的C函数,该函数会在程序启动初期(早于CGO依赖库加载、早于Go的main()执行)自动执行,从而提前设置DLL搜索路径:

#cgo LDFLAGS: -L . -lmylib
#include <string.h>
#include <stdlib.h>
#include <mylib.h>
#include <windows.h>

#ifdef _WIN32
__attribute__((constructor))
void init_dll_search_path() {
    // 设置默认仅从System32目录查找系统DLL
    SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32);
}
#endif

这个构造函数会优先于所有依赖库的加载逻辑执行,确保winmm.dll这类系统DLL只会从系统目录加载,避免本地路径劫持。

方案2:延迟加载CGO依赖库(仅适用于动态链接库)

如果mylib是动态链接库(.dll文件),可以通过延迟加载的方式,让其在main()设置完路径后再加载:

  1. 修改CGO的链接选项,添加延迟加载标记:
#cgo LDFLAGS: -L . -lmylib -delayload:mylib.dll
  1. 在Go的main()函数开头先设置DLL搜索路径,再手动触发mylib的加载:
import "syscall"
import "unsafe"

/*
#cgo LDFLAGS: -L . -lmylib -delayload:mylib.dll
#include <mylib.h>
void trigger_load() {}
*/
import "C"

func main() {
    windows.SetDefaultDllDirectories(windows.LOAD_LIBRARY_SEARCH_SYSTEM32)
    // 触发mylib的加载
    C.trigger_load()
    // 后续业务逻辑
}

这种方式通过延迟加载机制,让DLL搜索路径设置生效后再加载依赖库,从而避免劫持风险。


内容的提问来源于stack exchange,提问作者Volker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:01:30