Skip to content

Go 主机安全面试:Windows DLL 侧载与搜索顺序劫持检测

Windows 主机被入侵后,攻击者常把恶意 DLL 放到可信程序的同目录,借助 DLL 搜索顺序加载,或者替换程序会先找的依赖文件,让合法进程帮自己执行代码。面试官通常会追问:这类行为为什么难靠文件名发现?Go Agent 应该采哪些事件?怎样减少把正常安装程序、驱动更新和第三方软件误报成攻击?

岗位场景

text
Windows 主机
  -> 采集进程创建、模块加载、文件创建、签名信息和哈希
  -> 识别可信进程加载异常路径 DLL、同名依赖覆盖、临时目录落地和后续外联
  -> 关联父子进程、安装包、解压目录、启动目录和告警抑制规则
  -> 输出可解释证据,支持客户排障、误报治理和攻击链还原

这类题考的是 Windows 加载器原理、进程/模块证据、规则设计、白名单边界和 Go 侧的事件标准化能力。

高频面试题

1. 什么是 DLL 侧载,为什么它常见?

简洁答案:DLL 侧载就是让一个可信程序加载到攻击者控制的 DLL,程序本身可能是正常的,但它被放在了会优先搜索的目录里,于是恶意代码借壳执行。

关键知识点:

  • Windows 加载 DLL 时会按搜索顺序找目标模块。
  • 同目录、当前工作目录、系统目录和 PATH 都可能参与解析。
  • 攻击者喜欢利用“程序合法、路径异常”这个落差。

Go 落地思路:

  • 事件里同时保留 imageloaded_modulemodule_pathsignaturehash
  • 规则不要只看 dll 文件名,要看加载它的进程和所在目录。
  • 告警解释里说明“哪个可信程序从哪里加载了什么 DLL”,比只报一个文件名更有用。

2. 只看 DLL 文件名为什么不够?

简洁答案:同名 DLL 可能是正常组件,也可能是攻击者伪造的;真正关键的是加载路径、父进程、签名和文件来源。

关键知识点:

  • 很多软件会带自己的私有 DLL,文件名可能很普通。
  • 同名文件放在不同目录,安全含义完全不同。
  • 侧载攻击常见于安装包目录、解压目录、用户写入目录和应用目录。

Go 落地思路:

  • 把“名称 + 路径 + 签名”作为最小判断单元。
  • 对可信软件维护路径基线,而不是维护一个巨大的文件名黑名单。
  • 规则优先匹配“可信进程 + 非预期目录 + 弱签名或无签名”。

3. Windows 上哪些证据最适合发现侧载?

简洁答案:进程创建、模块加载、文件创建、签名校验和网络连接放在一起,才容易把侧载和正常依赖加载区分开。

常见证据:

证据来源关注字段检测价值
进程创建imagecmdlineparent_imageuser找到可信宿主和启动来源
模块加载module_pathsignedpublisher找到异常 DLL 路径
文件事件pathcreate_timehash发现 DLL 落地和覆盖
网络事件dest_ipdest_domainproc发现侧载后的外联
签名信息signature_statussubject辅助区分官方组件和伪装文件

Go 落地思路:

  • 采集层统一输出结构化字段,别把 ETW、Sysmon 或其他来源的细节直接暴露给规则层。
  • 文件事件和模块事件要按同一 host + pid + time window 关联。
  • 对高频系统组件做基线缓存,减少重复计算。

4. 搜索顺序劫持和普通 DLL 依赖加载有什么区别?

简洁答案:普通依赖加载是程序设计的一部分,搜索顺序劫持则是攻击者利用加载器会先找某些目录的行为,把恶意 DLL 放进优先目录。

关键知识点:

  • 依赖加载通常是显式依赖,路径和签名更稳定。
  • 搜索顺序劫持更依赖目录位置,例如当前目录、可写目录或解压目录。
  • 攻击者经常把文件放进和程序同目录的位置。

Go 落地思路:

  • 规则判断时分开“显式私有依赖”和“通过搜索顺序找到的模块”。
  • 对安装目录、临时目录、下载目录、用户可写目录做风险分层。
  • 报警输出要注明“这是路径风险,不是单纯的文件名风险”。

5. 如何减少正常安装器、解压器和自动更新的误报?

简洁答案:看进程角色和上下文。安装器、更新器和解压器确实会写入 DLL,但它们通常有固定签名、固定父进程和固定工作目录。

关键知识点:

  • 正常安装通常伴随可信签名、固定产品名和已知安装路径。
  • 攻击链常见父进程是浏览器、Office、脚本宿主、Web 服务或用户临时会话。
  • 单次命中不够,要看连续行为是否形成落地、执行和外联链路。

Go 落地思路:

  • 白名单优先按 publisher + path + hash + expiry 设计,不要只按文件名。
  • 对压缩包解压、软件升级和补丁安装做时间窗口压制。
  • 保留被压制事件的样本,方便后续回溯误报原因。
go
type ModuleEvent struct {
    HostID       string
    PID          int
    ProcessImage string
    ModulePath   string
    Signed       bool
    Publisher    string
    SHA256       string
}

6. Go Agent 怎么做 DLL 侧载检测才不重?

简洁答案:先做轻量标准化和风险分层,再在规则层做少量高价值判断,不要在采集层写一堆硬编码黑名单。

关键知识点:

  • 采集层只负责把模块加载、文件落地、签名和路径统一起来。
  • 规则层负责判断路径是否异常、签名是否可信、是否命中已知宿主基线。
  • 告警层再做去重、聚合和攻击链合并。

Go 落地思路:

  • 用稳定键聚合:host + pid + module_path + minute_bucket
  • 先过滤系统正常噪声,再对可疑路径做深一点的规则判断。
  • 避免每个事件都重复做昂贵的签名查询和哈希计算。

7. 如果攻击者把恶意 DLL 伪装成系统文件名怎么办?

简洁答案:不能只看名字,要看路径、签名、哈希、父进程和加载时间。系统文件名放到用户可写目录里,通常比名字本身更值得怀疑。

关键知识点:

  • 伪装名只是表象,路径才是关键。
  • 可信系统文件一般在固定系统目录并有稳定签名。
  • 同名不同签名、同名不同路径、同名不同发布时间都值得比较。

Go 落地思路:

  • 先建立“可信目录 + 可信签名”的双条件。
  • 对系统目录外出现的高仿文件名提高权重,但不要直接一票否决。
  • 记录 hash 变化和首次出现时间,便于排查持久化侧载。

学习要点

  • Windows DLL 搜索顺序和加载器行为。
  • 进程创建、模块加载、文件创建、签名和网络事件的关联方式。
  • 白名单、路径基线和时间窗口在降噪里的作用。
  • Go Agent 的事件标准化、聚合、缓存和规则解释设计。

小练习

  1. 观察一台 Windows 机器上某个常用软件启动时加载了哪些 DLL,区分系统目录和应用目录。
  2. 设计一个最小规则:只在 trusted_process + user_writable_path + unsigned_module 时报警。
  3. 想一想:如果安装器和攻击样本都写入同名 DLL,你还会用什么字段区分它们?

复盘题

  1. 为什么 DLL 侧载比“查一个黑名单文件名”更适合做成行为检测?
  2. 你会把哪些字段放进 Go 的模块事件结构体,为什么?
  3. 如果客户现场把某个告警判成误报,你会先看哪三个证据?
最近更新