从 XZ 后门学奇技淫巧

💡 原文中文,约25400字,阅读约需61分钟。
📝

内容提要

该文章分析了CVE-2024-3094漏洞中后门隐藏的技巧,包括GLIBC的IFUNC特性、Radix Tree算法隐藏字符的方法和利用dl_audit机制进行函数hook的流程。文章总结了XZ后门的复杂性,并提供了一些参考链接。

🔎

延伸解读

IFUNC 特性:加载阶段执行代码的隐蔽入口

文章通过示例展示了 GLIBC 的 IFUNC 特性:在程序加载阶段,动态链接器会调用 resolver 函数来确定函数地址,且该调用发生在构造函数之前。这意味着攻击者可以利用 IFUNC 在依赖库被加载时自动执行代码,而无需依赖常规的入口点。XZ 后门正是利用了这一机制,在 liblzma.so 加载时触发后门逻辑。需要注意的是,IFUNC 需要 glibc 2.11.1 以上、GCC 4.6 以上及 Binutils 2.20.1 以上才支持。

Radix Tree 隐藏字符串:规避静态检测

XZ 后门使用 Radix Tree 算法存储关键字符串,避免在二进制中直接出现如“sshd”等敏感字符串。文章解释了其数据结构:每个节点用两个 64 位整数表示 128 个字符的存在性,并通过指针链接子节点。这种压缩存储方式使得字符串信息分散在内存表中,增加了逆向分析的难度。但文章也指出,该算法本质上是可逆的,通过爆破可以还原出所有字符串。

获取依赖库信息:基于 ld 基址的符号解析

后门通过 __tls_get_addr 函数地址爆破出 ld 的基地址,进而解析 ELF 结构获取任意符号地址。文章详细描述了如何利用 __libc_stack_end 获取参数和环境变量,以及通过 _r_debug 和 link_map 遍历所有加载的库,最终定位到 sshd 和 libcrypto 等目标。这一过程完全自定义实现,不依赖库函数,体现了后门的高度复杂性。

dl_audit 机制:函数 hook 的实现与条件

XZ 后门利用 glibc 的 dl_audit 机制进行函数 hook。文章分析了 _dl_audit_symbind 的调用条件:需要 dl_naudit > 0 且相关 link_map 的 l_audit_any_plt 标志置位。后门通过修改 ld 中的全局变量和 audit 结构体,将 symbind64 指向自定义函数,从而在符号绑定时拦截并替换目标函数(如 RSA_public_decrypt)。文章还提供了简化 demo 演示了 hook AES_set_encrypt_key 的过程。

❓

Q&A

CVE-2024-3094漏洞的主要特点是什么?

CVE-2024-3094漏洞涉及后门隐藏的技巧,利用GLIBC的IFUNC特性和Radix Tree算法来隐藏字符信息。

GLIBC的IFUNC特性是如何工作的?

GLIBC的IFUNC特性允许在程序加载阶段自动运行特定函数,通过环境变量决定调用哪个函数。

XZ后门是如何利用Radix Tree算法隐藏字符的?

XZ后门使用Radix Tree算法来隐藏字符串信息,避免直接暴露关键字符,增强隐蔽性。

如何通过dl_audit机制进行函数hook?

XZ后门通过设置dl_audit结构体的symbind函数指针来实现对特定函数的hook,从而拦截调用。

获取依赖库信息的步骤是什么?

通过__tls_get_addr函数获取ld的基地址,然后匹配ELF头信息以获取依赖库的地址。

XZ后门的实现复杂性如何?

XZ后门的实现复杂,几乎不依赖外部库函数,完全自定义实现,增加了逆向分析的难度。

🏷️

标签

➡️

继续阅读