PAC 绕过新维度

摘要 ARM64 的指针认证通过 PACIA/PACIB 指令为返回地址和函数指针附加密码学签名,阻断了传统 ROP/JOP 攻击。然而,PAC 的密钥分域——指令地址用 A-key,数据地址用 B-key——留下了裂隙。攻击者可以在 JavaScript JIT 编译过程中喷射精心构造的 shellcode,利用 JIT 引擎生成混合了返回指令序列的代码,在指令域签名却在数据域校验,从而绕过 PAC 验证。 ARM64 PAC密钥分域与签名 PAC 指令与密钥 ARMv8.3-A 引入了指针认证(PAC),使用基于 QARMA 的轻量级 MAC 算法为 64 位指针生成认证码,嵌入指针的高位。核心指令: PACIA Xd, Xn:使用指令 A-key 对 Xn 生成签名,存储到 Xd。 PACIB Xd, Xn:使用指令 B-key 对 Xn 签名。 AUTIA Xd, Xn:验证 A-key 签名,若失败则将 Xd 设为无效指针。 AUTIB Xd, Xn:验证 B-key 签名。 A-key 用于指令地址(如返回地址、函数指针),B-key…

Mojo IPC 的序列化陷阱

摘要 Chromium 的多进程架构将高风险渲染器囚禁于受限沙箱,所有特权操作必须通过 Mojo IPC 向浏览器进程发起请求。Mojo 接口定义语言(.mojom)自动生成序列化代码,以 C++ 模板的 StructTraits 和 UnionTraits 实现高效编解码。然而,正是这种自动生成的序列化逻辑隐藏了一类致命的陷阱——接口参数校验与调用者能力假设之间的裂缝。攻击者在获得渲染器代码执行权限后,可构造跨越沙箱边界的畸形 Mojo 消息:向 FileSystemManager 接口注入路径遍历序列,利用 Blob 存储系统绕过站点隔离,或通过 WindowOpen 等接口制造幽灵窗口。 Chromium 沙箱架构与 Mojo IPC 基础 站点隔离与进程模型 Chromium 采用 Site Isolation 策略,每个源(origin)被分配到独立的渲染器进程。渲染器运行在受限沙箱中,无法直接访问文件系统、网络或系统调用。任何此类操作必须通过 Mojo 接口向浏览器进程(Browser Process)发出请求,浏览器进程进行权限验证后代理执行。 Mojo 是 Chromium 自研的 IPC 框架,替代了早期的 Legacy IPC 和 ChannelProxy。它提供跨进程的消息传递、接口定义、自动生成绑定代码以及版本控制。Mojo 的核心抽象是 Message Pipe(消息管道),两端由 mojo::Remote 和 mojo::Receiver 持有,分别用于发送和接收接口方法的调用。 Mojo 接口定义与代码生成 Mojo 接口使用 .mojom IDL 定义,例如: // FileSystemManager.mojom (简化) interface FileSystemManager { OpenFile(string path, OpenFlags flags) => (file.File file);…

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…