WorkBuddy信封中的AES-256-GCM

· 2026-11-09 14:05 · 1 阅读

原创 沈沉舟 2026-11-09 14:05 北京

我这篇,没有A里A气的。

创建: 2026-11-09 13:06
链接: https://scz.617.cn/misc/202611091306.txt

以Windows版WorkBuddy为例

%LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth\workbuddy-desktop.info

此文件以json格式存放WB登录态信息,某些字段加密存放,降低直接暴露的风险。比如WB登录时用的手机号,经AES-256-GCM加密存放。

{
  "account"
: {
    "uid"
: "...",
    "phoneNumber"
: {
      "$wbEncrypted"
: 1,
      "envelope"
: "eyJzdWl0ZSI6MSwia2V5SWQiOiIyMjIyMjIyMjIyMjIyMjIyIiwibm9uY2UiOiJFUkVSRVJFUkVSRVJFUkVSIiwiYXV0aFRhZyI6ImljU0tDU1cyNk9Jbko1NGpqUWgzWWc9PSIsImNpcGhlcnRleHQiOiJsVHdKMk8ydEFtUDNrL1k9In0="
    }
,

envelope字段并不直接对应密文,对之BASE64解码并美化后,形如

{
  "suite"
: 1,
  "keyId"
: "2222222222222222",
  "nonce"
: "ERERERERERERERER",
  "authTag"
: "icSKCSW26OInJ54jjQh3Yg==",
  "ciphertext"
: "lTwJ2O2tAmP3k/Y="
}

suite、keyId用于组装参与加解密运算的Additional Authenticated Data (AAD)。AAD的结构形如

"WB-AAD\0" | 0x01 | LP("WBEV1") | LP("sym-v1") | suite | LP(keyId) | framingCode | 0x00 | 0x00

在当前上下文中,framingCode恒为2,表示AAD绑定登录态文件的单个字段。于是AAD只受suite、keyId影响,它们是已知的。从前述envelope组装出AAD

57422d41414400010000000557424556310000000673796d2d7631000000010000001032323232323232323232323232323232020000

00000000  57 42 2d 41 41 44 00 01 00 00 00 05 57 42 45 56  |WB-AAD......WBEV|
00000010  31 00 00 00 06 73 79 6d 2d 76 31 00 00 00 01 00  |1....sym-v1.....|
00000020  00 00 10 32 32 32 32 32 32 32 32 32 32 32 32 32  |...2222222222222|
00000030  32 32 32 02 00 00                                |222...|

nonce对应AES-256-GCM的IV,envelope中nonce是HEX的BASE64形式。

AES-256-GCM加密时需要

protectorKey    0000000000000000000000000000000000000000000000000000000000000000
nonce           111111111111111111111111
suite           1
keyId           2222222222222222
AAD             57422d41414400010000000557424556310000000673796d2d7631000000010000001032323232323232323232323232323232020000
plaintext       13800000000

WorkBuddy.exe内嵌经混淆存放的atRestSecretKey,PE自己知道怎么还原它,社区有现成方案。

对atRestSecretKey求SHA-256,得到protectorKey。不要对atRestSecretKey进行BASE64解码,要直接求SHA-256。

上例只是演示说明,所以用了全0的protectorKey。加密后得到两个值

ciphertext      953c09d8edad0263f793f6
authTag         89c48a0925b6e8e227279e238d087762

将nonce、ciphertext、authTag从HEX转成BASE64

nonce           ERERERERERERERER
ciphertext      lTwJ2O2tAmP3k/Y=
authTag         icSKCSW26OInJ54jjQh3Yg==

即envelope中的形式

AES-256-GCM解密时需要

protectorKey    0000000000000000000000000000000000000000000000000000000000000000
nonce           ERERERERERERERER
AAD             57422d41414400010000000557424556310000000673796d2d7631000000010000001032323232323232323232323232323232020000
authTag         icSKCSW26OInJ54jjQh3Yg==
ciphertext      lTwJ2O2tAmP3k/Y=

解密时会新算一份authTag,与解密前提供的authTag相比较,不匹配则不交付明文,解密失败。

用CyberChef测试

From Base64
  lTwJ2O2tAmP3k/Y=              // ciphertext
AES Decrypt
  Key (HEX)
    0000000000000000000000000000000000000000000000000000000000000000
                                // protectorKey
  IV (BASE64)
    ERERERERERERERER            // nonce
  Mode
    GCM
  Input
    Raw
  Output
    Raw
  GCM Tag (BASE64)
    icSKCSW26OInJ54jjQh3Yg==    // authTag
  Additional Authenticated Data (HEX)
                                // AAD
    57422d41414400010000000557424556310000000673796d2d7631000000010000001032323232323232323232323232323232020000
  IV from input
    Off

输出

13800000000

从解密过程看,envelope解码后所有字段都派上用场,suite、keyId用于组装AAD,并非无用。

尽管CyberChef解密时要求提供authTag,但此字段对我们这种上下文没啥必要性。因为已知protectorKey、nonce、AAD、ciphertext的情况下,可计算出authTag。不过CyberChef并未提供针对这种情形的菜谱。

这年头,在公众号上还能读到人写的技术文章,不容易吧。我这篇,没有A里A气的。

阅读原文

跳转微信打开

本文转载自微信公众号「青衣十三楼飞花堂」,查看原文。版权归原作者所有,如有侵权请联系删除。