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

从无调试符号Swift二进制提取CryptoKit.SymmetricKey的技术问询

问题背景

我要演示在二进制中存储/生成CryptoKit.SymmetricKey并不安全,为此编写了测试脚本:

import Foundation
import CryptoKit

let key = SymmetricKey(data: Data([0x18, 0xd3, 0x31, 0xd0, 0xb4, 0x42, 0x55, 0x71, 0xb5, 0xaa, 0xa9, 0xcd, 0xd3, 0x1b, 0xb4, 0xd1, 0xac, 0xd9, 0x29, 0xd6, 0x18, 0x88, 0xbc, 0xee, 0x3f, 0xdf, 0x5e, 0x62, 0x2d, 0xa4, 0x6c, 0x10]))
let encryptedData = Data([0xa8, 0xf8, 0xf5, 0x79, 0x63, 0xb7, 0xb2, 0x7b, 0x00, 0xbe, 0x39, 0xf8, 0x2a, 0xb2, 0xeb, 0x4f, 0x6d, 0x77, 0x00, 0xe1, 0xd3, 0x7c, 0x15, 0x43, 0xa3, 0xb9, 0x50, 0xf1, 0x6d, 0x47, 0x3b, 0x79, 0xbc, 0x83, 0xee, 0xfe, 0x5e, 0xf1, 0xe5, 0x59, 0x85])

let sealedBox = try! ChaChaPoly.SealedBox(combined: encryptedData)
let decryptedData = try! ChaChaPoly.open(sealedBox, using: key)
let decryptedString = String(decoding: decryptedData, as: UTF8.self)

print(decryptedString)

该脚本由以下代码生成:

import Foundation
import CryptoKit

let message = "Hello, world!"

let nonce = ChaChaPoly.Nonce()
let key = SymmetricKey(size: .bits256)

let keyData = key.withUnsafeBytes { Data(Array($0)) }
print("Key: \(keyData.map { String(format: "%02hhx", $0) }.joined())")

let sealedBox = try! ChaChaPoly.seal(message.data(using: .utf8)!, using: key, nonce: nonce)
print("Combined: \(sealedBox.combined.map { String(format: "%02hhx", $0) }.joined())")

我的目标是避免直接从二进制中提取密钥数组,而是通过内存转储或拦截CryptoKit调用的方式获取密钥,以此证明即使密钥经过混淆或来自其他来源,仍可被提取。具体要求是在无调试符号的任意Swift二进制中,至少获取十六进制格式的密钥,同时尽可能获取密文或明文。


已尝试的方案及问题

LLDB

我尝试在LLDB中为CryptoKit.SymmetricKey.init<A where A: Foundation.ContiguousBytes>(data: A) -> CryptoKit.SymmetricKey和CryptoKit.ChaChaPoly.open(_: CryptoKit.ChaChaPoly.SealedBox, using: CryptoKit.SymmetricKey) throws -> Foundation.Data设置断点,但遇到以下问题:

获取内存地址

带调试符号编译(swiftc -g)时,能用frame var -L key拿到密钥地址,但无调试符号时,无法通过寄存器和反汇编确定密钥的内存地址。

获取密钥数据

即使通过调试符号拿到地址,手动强制转换结构体时也失败:

(lldb) expr -l Swift -- import CryptoKit
(lldb) expr -l Swift -- import Foundation
(lldb) frame var -L key
0x0000000100008028: (CryptoKit.SymmetricKey) key = {
0x0000000100008028:   sb = {
0x0000000100008028:     offset = 4296052176
  }
}
(lldb) expr -l Swift -- let $foo = unsafeBitCast(0x0000000100008028, to: SymmetricKey.self)
(lldb) expr -l Swift -- $foo.withUnsafeBytes { Data(Array($0)) }.map { String(format: "%02hhx", $0) }.joined()
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0xfffffffffffffff8).
The process has been returned to the state before expression evaluation.

不过直接调用expr -l Swift -- key.withUnsafeBytes { Data(Array($0)) }.map { String(format: "%02hhx", $0) }.joined()是有效的。

Frida

我编写了Frida脚本,但陷入瓶颈,不知道如何继续推进:

{
  const getFunc = (name) => {
    if (name.includes("open_")) {
      return "open"
    } else if (name.includes("seal_")) {
      return "seal"
    } else {
      throw new Error("Unknown function")
    }
  }

  const module = Process.enumerateModules().find((module) => module.name === "CryptoKit")

  if (!module) {
    throw new Error("CryptoKit module not found")
  }

  for (const exp of module.enumerateExports()) {
    if (exp.name.includes("Symmetric") || exp.name.includes("Cha")) {
      Interceptor.attach(exp.address, {
        onEnter: (args) => {
          const func = getFunc(exp.name)
          switch (func) {
            case "open":
              // SealedBox, SymmetricKey
              console.log("Open called")
              break
            case "seal":
              console.log("Seal called")
              break
          }
        },
        onLeave: (retval) => {},
      })
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 20:58:20