WAL 文件时间旅行攻击

摘要 SQLite 的 WAL 模式通过将写操作先追加到 Write-Ahead Log,再通过 Checkpoint 批量合并至主数据库,实现了读写并发的性能飞跃。然而,这一架构也引入了时间维度上的信息残余:已删除的记录在 WAL 文件中保留至下一次 Checkpoint 执行,且应用程序通常依赖 SQLite 的自动 Checkpoint 策略(1000 页阈值或连接关闭时触发),这为攻击者提供了充裕的窗口。攻击者可通过延迟 Checkpoint、强制持有读锁阻止 WAL 清理,使 WAL 文件中的“已删除”数据保留数小时甚至数天;随后仅需解析 WAL 的帧格式,即可从 $WAL 文件中提取已被主数据库删除的敏感记录,实现对“历史状态”的时间旅行攻击。 WAL 模式的并发模型与锁定机制 WAL模式设计初衷 在传统的 SQLite Rollback Journal 模式下,写操作需要持有独占的数据库级锁,导致读写无法并发。WAL 模式通过将新的写入追加到独立的 WAL 文件末尾,使读操作可以直接访问主数据库文件中的未修改页面,同时在 WAL 文件中查找更新后的版本。 ┌─────────────────────────────────────────────────────────────┐ │ 系统内存 (共享内存) │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 共享内存索引文件 (-shm) │…

ClientHello 扩展排列的差分隐私与 JA4 指纹伪造

摘要 TLS 握手的第一步——ClientHello 消息——在明文传输中承载了客户端支持的加密套件、TLS 版本和数十个扩展字段,其精确组合构成了每个 TLS 实现的独特指纹。JA3 及其继任者 JA4 将这些字段哈希化,为网络防御者提供了一柄识别恶意软件与异常流量的利器。然而,指纹的稳定性本身就是一把双刃剑:Go 的 crypto/tls 与浏览器的 BoringSSL 在扩展排列、GREASE 扩展生成和 ALPN 排序上的细微差异,形成了不可伪造的指纹裂隙。攻击者利用 utls 等库精心伪造 ClientHello,却仍在 JA4 指纹空间中留下暴露真实客户端的二阶痕迹。 ClientHello 指纹的构建原理 从 JA3 到 JA4 JA3 指纹由 Salesforce 在 2017 年提出,通过对 ClientHello 中的 TLS 版本、密码套件、扩展列表和椭圆曲线参数进行 MD5 哈希,生成一个 32 字符的指纹字符串。其核心假设是:同一 TLS 实现的 ClientHello 在这些字段上保持稳定,从而可作为识别特定客户端软件(如 Chrome、Python requests、Go 程序)的强标识。 然而,JA3 存在两个根本性局限: 对 QUIC 无效:JA3 基于 TLS over TCP,对…

Git LFS 指针文件的竞态条件与 Smudge Filter 的隐蔽持久化

摘要 Git Large File Storage 用轻量指针文件替代大文件,再通过 Smudge Filter 在 checkout 时透明下载真实内容。这套机制原本是为了解决版本控制中的大文件管理问题,却在不经意间开辟了一条隐蔽的持久化通道:指针文件仅通过格式校验即可被认定为合法,而 Smudge Filter 在 checkout 时执行的命令完全由仓库内的 .gitattributes 控制。攻击者可以在指针文件通过验证后、实际下载内容完成前的微秒级窗口内,利用竞态条件将恶意载荷替换为“真实”文件,或直接注册一个伪装成 LFS Filter 的恶意 Smudge Filter,在 git clone 的瞬间执行任意命令。 Git LFS信任机制 LFS 指针文件的静态格式 Git LFS 的核心设计理念是“用指针文件替代大文件”。在 Git 仓库中,一个被 LFS 管理的大文件(如 video.mp4)会被替换为如下结构的指针文件: version https://git-lfs.github.com/spec/v1 oid sha256:4d7a214614ab2935c943f9e0ff69d22eadbb8f32b1258daaa5e2ca24d17e2393 size 341283 这个文件仅包含三行文本:版本声明、对象 OID(SHA-256 哈希)、文件原始大小。Git 对 LFS 指针的合法性校验仅基于两点: 第一行匹配version https://git-lfs.github.com/spec/v1。 第二行以oid sha256: 开头,后跟 64 个十六进制字符。 只要满足这两个格式条件,Git 就认为该文件是一个有效的 LFS 指针,并在后续操作中触发…

Nim 的 C-FFI 隐身衣

摘要 Nim 语言凭借其接近 C 的性能与 Python 般简洁的语法,正逐渐成为恶意软件开发者的新宠。其独特的编译期代码执行能力,使得恶意代码可以在编译时读取系统信息、生成仅在特定目标环境中激活的分支,并直接绑定 Win32 API——不依赖 LoadLibrary/GetProcAddress 的动态解析,也不在导入表中暴露敏感函数名。与 Go 的 cgo 和 Rust 的 cc crate 不同,Nim 生成的 C 中间产物在最终二进制中几乎不留痕迹,逆向工程师面对的是一张高度定制的“C-FFI 隐身衣”。 Nim编译管道与C-FFI绑定 Nim 编译器的工作流程 Nim 编译器(nim)并非直接生成机器码,而是默认通过 C 后端生成 C 源代码,再调用系统的 C 编译器(GCC、Clang 或 MSVC)完成最终编译。这一设计的核心优势在于:Nim 程序天然具备与 C 语言相同级别的底层访问能力,同时保留了高级语言的类型安全和元编程能力。 编译流程分为四个阶段: Nim 源码解析与语义分析:编译器将 .nim 文件解析为 AST,进行类型推导和宏展开。 中间表示生成:经过语义检查的 AST 被转换为 Nim 虚拟机指令或直接进入代码生成阶段。 C 代码生成:代码生成器遍历中间表示,输出对应的 C 代码。Windows 下通常输出 .nim.c 文件,包含所有函数的 C 实现和 Nim 运行时支持代码。 C…

iBoot SMMU 绕过与 Kernelcache 结构体伪造

摘要 Apple Silicon 的安全启动链从 Boot ROM 到 iBoot 再到 Kernelcache,层层验证,构筑了封闭生态中最坚固的信任根基。然而,iBoot 阶段的系统内存管理单元初始化和设备树解析,依赖一套早于 XNU 内核建立的内存映射机制。攻击者若能在 iBoot 执行阶段污染设备树中的 DART 节点,便可在 SMMU 页表创建之前植入虚假的 IOMMU 映射,使内核在不知情的情况下使用被篡改的 DMA 保护配置。 Apple Silicon 的启动链与信任模型 从 Boot ROM 到 Kernelcache 的信任传递 Apple Silicon Mac 的启动过程分为四个严格校验的阶段: Boot ROM:芯片出厂固化代码,不可修改。验证下一阶段的签名(iBoot),仅在 DFU 模式下可通过外部刷新进行恢复。这是信任的物理根基,也是 checkm8 等永久性漏洞的所在层。 iBoot:Apple 的第二阶段引导加载器,负责初始化硬件(包括 SMMU、内存控制器、PCIe 根复合体),解析设备树并选择启动内核。iBoot 本身由 Boot ROM 验证签名。 Kernelcache:XNU 内核及其扩展的预链接映像,由 iBoot 验证签名后解压加载。内核启动后依赖 iBoot…

通过 AER 滥用和 ECRC 劫持实现 DMA 重定向

摘要 PCI Express 链路上传输的每一条 DMA 读写请求都被封装为 TLP(事务层数据包),携带设备标识符和目标物理地址。IOMMU 通过 BDF 编号和地址转换表对这些请求进行合法性检查,阻止未经授权的内存访问。然而,TLP 层存在一个容易被忽视的攻击面:高级错误报告(AER)允许设备向根复合体报告各类错误,而端到端 CRC(ECRC)本用于检测传输过程中的比特翻转,却可能被恶意设备主动操纵,迫使接收端进入错误恢复流程。在错误恢复的重传机制中,如果攻击者能够制造 TLP 的“合法重放”,并将其中的物理地址字段替换为攻击目标,便能在 IOMMU 检查之前完成 DMA 重定向。 PCIe TLP 与 DMA 的权限模型 TLP 的结构与路由 PCIe 采用分层协议,事务层负责在设备与主机之间传输数据。 每个 TLP 包含: TLP 前缀(可选):用于扩展头信息。 TLP 头:包含格式(Fmt)和类型(Type)字段,决定 TLP 是存储器读写、配置读写、消息还是完成包。对于存储器写 TLP,头中还有地址字段(32 位或 64 位物理地址)。 数据载荷:实际传输的有效数据。 TLP 摘要:可选字段,包含 32 位的 ECRC,用于检测端到端的比特错误。 在 DMA 操作中,设备主动向主机内存发起读写请求。主机芯片组中的根复合体(Root Complex)根据 TLP 头中的 Requester ID(Bus/Device/Function,BDF)和地址进行路由,并由 IOMMU…