sorry-ransomware-reverse-analysis

40次阅读
没有评论

Sorry (Vijay) 勒索软件 — Linux Go 样本逆向分析

分析日期:2026-08-15
分析工具:IDA Pro (ida-pro-mcp)
样本:Linux 64 位 ELF,Go 语言,garble 混淆
分类:勒索软件(Ransomware)/ 混合密码学
风险等级:高(不可恢复加密,密钥外泄)


1. 样本指纹

属性 值
SHA-256 2fc0a056fd4eff5d31d06c103af3298d711f33dbcd5d122cae30b571ac511e5a
格式 64 位 ELF,静态链接
语言 Go(garble 混淆)
大小 ≈ 5.6 MB
基址 0x400000
函数数 5208
调用约定 Go ABIInternal(参数经 RAX/RBX/RCX/RDX/RDI/RSI 传递)

反汇编备注:garble 混淆随机化了 pclntab magic,导致标准 Go 解析器失效。函数无法按 pclntab 恢复语义,导航依赖字符串 xrefs 与汇编级寄存器追踪。


2. 家族识别

样本属于 "Sorry" / Vijay 勒索软件家族。

  • 扩展名:.sorry
  • 标记文件:.sorry_exist
  • 受害者 ID 文件:sorry_id
  • 联系渠道:qTox
  • TOX ID:
    3D7889AEC00F2325E1A3FBC0ACA4E521670497F11E47FDE13EADE8FED3144B5EB56D6B198724

勒索信模板(@0x6a2f4e):

Please contact us through the qtox tool

Download qtox https://github.com/qTox/qTox/blob/master/README.md#qtox

If you can't contact us, please contact some data recovery company(suggest taobao.com), may they can contact to us.

Add our TOX ID and send an encrypted file and 'Sorry-ID' for testing decryption.

Our TOX ID: %v

3. 运行行为总览

  1. 初始化:加载硬编码的攻击者 RSA 公钥(PEM,@0x6a3098),初始化 crypto/rand。
  2. 密钥对生成:每次运行生成受害者自己的 RSA-2048 密钥对(rsa.GenerateKey),PEM 私钥保留在内存。
  3. 受害者识别:采集机器信息(用户名、hostname、机器 ID、IP),生成随机前缀 ID。
  4. 私钥外泄:将「机器信息 + 受害者 PEM 私钥」拼接后,用攻击者公钥 RSA 加密,base64 编码,写入 ~/sorry_id_{时间戳}{32位hex}。
  5. C2 信标:向硬编码 C2 发送 HTTP 请求(伪装 google.com/favicon.ico),上报 init / repeat / time_finished 状态。
  6. 文件加密:遍历目标目录,对每个文件生成随机 AES-256 密钥,AES-CBC 加密内容,文件头写入 RSA 加密的密钥块,扩展名改 .sorry。
  7. 勒索信:落盘勒索说明,含 TOX ID。
  8. 双模式:二进制内置 enc / dec 两种模式(dec or enc dirs, split by ,),攻击者可用 dec 模式解密。

4. C2 通信

属性 值
C2 地址 68.183.190.253:80(DigitalOcean)
协议 HTTP GET,伪装 google.com/favicon.ico
UA 伪装 Chrome
超时 15 秒
上报动作 repeat / init / time_finished:%v

4.1 实测信标(运行抓包)

GET /favicon.ico HTTP/1.1
Host: google.com
Connection: close
User-Agent: Chrome-init|root|localhost|2|linux|/ce69Fih/01896FBB58E8EDEFC5A8392E467C2260|100.64.1.28

4.2 信标逐字段解析

字段 值 含义
Chrome- — UA 伪装前缀
init — 上报动作标签
root — 当前用户名
localhost — hostname
2 — 数字字段(来源待定)
linux — 硬编码 OS 标识
/ce69Fih/01896FBB58E8EDEFC5A8392E467C2260 — 机器 ID(hex)+ 随机前缀
100.64.1.28 — CGNAT 段本地 IP(非公网)

注意:信标是受害者识别标识,不是解密密钥。信标中所有字母数字字段均为 hex/base64 编码的 ID,与文件解密密钥无关。


5. 加密架构(核心)

混合密码学:RSA-2048(PKCS#1 v1.5)+ AES-256-CBC。

5.1 文件加密格式

┌──────────────┬────────────────────────────────────┬──────────────┬─────────────────┐
│ 4B 版本(大端) │ RSA-2048 加密块                     │ 4B 原始大小   │ AES-256-CBC 密文 │
│ = 4          │ AES-256 密钥(32B) + 扩展名(≤20B)    │ (大端)       │                 │
└──────────────┴────────────────────────────────────┴──────────────┴─────────────────┘
  • 版本:4 字节大端,固定为 4。
  • RSA 加密块:每文件随机 AES-256 密钥 + 原扩展名(≤20 字节),用 RSA 公钥加密 → 256 字节密文块。
  • 原始大小:4 字节大端,解密后用于恢复文件长度。
  • 密文:AES-256-CBC。

5.2 RSA 分块加密(sub_5C2500)

  • 明文数据被拆分为 (keysize − 11) 字节的块(RSA-2048 → 245 字节/块)。
  • 每块调用 sub_520000(rsa.EncryptPKCS1v15)加密后拼接。
  • sub_520320 = 大数模幂(modpow)运算。
  • PKCS#1 v1.5 类型 2 填充(公钥加密),填充字节 0x02。

5.3 确认的加密函数

函数 地址 作用
sub_520000 0x520000 rsa.EncryptPKCS1v15(FIPS 字符串佐证)
sub_520320 0x520320 大数模幂
sub_5C2500 0x5C2500 RSA 分块加密循环
sub_5BFBE0 0x5BFBE0 文件头生成(RSA 加密 AES key + 扩展名)
sub_5BE980 0x5BE980 文件流加密(AES)
sub_5BF400 0x5BF400 文件加密主循环
sub_520880 0x520880 rsa.GenerateKey

6. 密钥体系

6.1 每文件 AES 密钥

  • 长度:256 位 = 32 字节(sub_5BE8C0 中 makeslice(0x20))。
  • 内容:crypto/rand.Read 生成的原始二进制随机字节(0x00–0xFF),非字符。
  • 落地形式:不以明文文本形式出现,直接 RSA 加密进文件头。
  • 错误串:gen aes fail: %w(@0x691f75)。

6.2 受害者 RSA 密钥对(每次运行生成)

  • sub_5C3300(INIT 流程)→ rsa.GenerateKey(sub_520880)。
  • PEM 私钥保存在内存,从不以明文落盘。
  • 私钥用于:
    • 拼接进 sorry_id 加密内容(外泄给攻击者);
    • SSH 配置构建(sub_5DC8C0,curve25519-sha256@libssh.org,@0x6975ce)——疑似私钥外泄 / 解密通道。

6.3 攻击者 RSA 公钥(硬编码)

  • 硬编码 PEM @ 0x6a3098,由 sub_5C0140 解析。
  • 存入 config[0x78] 对象偏移 +8。
  • 用于加密 sorry_id 内容与文件头 AES 密钥。

6.4 crypto/rand 全局(关键全局)

全局 地址 作用
qword_9152A0 0x9152a0 crypto/rand.Reader 接口 type 部分(静态 itab &off_6F06E0)
qword_9152A8 0x9152a8 crypto/rand.Reader 接口 data 部分(newobject(unk_654F20) 实例)
  • 两者共同构成 io.Reader 接口值 = crypto/rand.Reader。
  • off_6F06E0(@0x6f06e0)为 itab 结构:{inter, type, hash, fun[0]=sub_50D5E0, ...}。
  • sub_50D5E0 = crypto/rand 懒初始化;sub_50D6A0 = crypto/rand.Read 包装器(字符串 crypto/rand: failed to read random data (see https://go.dev/issue/66821): 佐证)。

6.5 sorry_id 外泄机制(核心)

每次运行的受害者 RSA 私钥,加密后交给攻击者。

concatstring5(机器信息 + PEM私钥)
        │
        ▼
RSA_EncryptPKCS1v15( random=crypto/rand.Reader,
                     pub   =攻击者公钥(config[0x78] 对象[1]),
                     msg   =拼接数据 )
        │
        ▼
base64.EncodeToString  (sub_55FF40)
        │
        ▼
写入 ~/sorry_id_{时间戳}{32位hex}  (mode 0644)
  • 文件名格式字符串:sorry_id_%v%v(@0x690c91)。
  • 随机 ID:sub_5C3160 生成 16 字节随机 → hex 编码为 32 个字符(0123456789abcdef,@0x691f45)。
  • 攻击者持有攻击者私钥 → 解开 sorry_id → 获得受害者 RSA 私钥 → 具备完整解密能力。

7. 解密机制(不上传内容,如何解密)

结论:加密内容永不上传,解密完全基于密钥,而密钥在加密时已交付攻击者。

  1. 文件内容在本地 AES-256-CBC 加密,密文留在本机,改 .sorry 扩展名。
  2. 解密依赖钥匙而非内容:每个文件的 AES 密钥被 RSA 加密在文件头。
  3. 每次运行生成受害者 RSA 密钥对,受害者私钥用攻击者公钥 RSA 加密后写入 sorry_id 文件(随 C2/人工渠道交到攻击者手里)。
  4. 攻击者解密流程:
    • 用攻击者私钥解开 sorry_id → 获得受害者 RSA 私钥;
    • 用私钥解每个文件头 → 获得 32 字节 AES 密钥;
    • 二进制内置 dec 模式(flag dec or enc dirs, split by ,,@0x69695f)逐文件解密,恢复扩展名与原始大小。
  5. 勒索信「发送一个加密文件 + Sorry-ID 测试解密」成立,因攻击者已持有解密钥匙,无需上传完整内容。

8. 关键函数清单

函数 地址 大小 作用
sub_6142A0 0x6142a0 — main(解析攻击者 PEM → config[0x78]+8;分派 enc/dec)
sub_5C3300 0x5c3300 0x626 INIT:生成受害者密钥对 + 构造 sorry_id
sub_5C0140 0x5c0140 — 解析攻击者 RSA 公钥 PEM
sub_5C2500 0x5c2500 — RSA 分块加密
sub_520000 0x520000 — rsa.EncryptPKCS1v15
sub_520320 0x520320 — 大数模幂(modpow)
sub_520880 0x520880 — rsa.GenerateKey
sub_5BFBE0 0x5bfbe0 — 文件头生成(RSA 加密 AES key + 扩展名)
sub_5BE980 0x5be980 — 文件流加密(AES)
sub_5BF400 0x5bf400 0x68d 文件加密主循环
sub_5BE8C0 0x5be8c0 — AES 密钥生成(crypto/rand.Read 包装,32 字节)
sub_5C3160 0x5c3160 — 随机 hex ID(32 字符)
sub_5C2D60 0x5c2d60 — 机器信息收集
sub_55FF40 0x55ff40 — base64.EncodeToString 包装器
sub_50D6A0 0x50d6a0 — crypto/rand.Read 包装器
sub_50D5E0 0x50d5e0 — crypto/rand 懒初始化
sub_5DC8C0 0x5dc8c0 — SSH 配置构建(curve25519-sha256@libssh.org)
sub_47E060 0x47e060 — 通用(流/缓冲相关)
sub_486980 0x486980 — crypto/rand.Read 底层
sub_4F0A80 0x4f0a80 — 错误处理 / panic 包装
sub_4E22C0 0x4e22c0 — 空函数(rand 初始化辅助)

9. 关键全局变量

全局 地址 作用
qword_9152A0 0x9152a0 crypto/rand.Reader type(静态 itab &off_6F06E0)
qword_9152A8 0x9152a8 crypto/rand.Reader data(newobject 实例)
qword_915220 / qword_915228 0x915220 / 0x915228 机器 ID 缓存
qword_914E58 0x914e58 logger
dword_936C80 0x936c80 debug flag
byte_93684A 0x93684a crypto branch flag
dword_9368D8 0x9368d8 rand init lock
byte_93684C 0x93684c rand test-failure flag
byte_936849 0x936849 FIPS flag
unk_634D60 0x634d60 log format
qword_914FD0 0x914fd0 global
qword_936820 0x936820 global(concat 缓冲相关)
off_6F03C0 / off_6F03E0 0x6f03c0 / 0x6f03e0 方法表(文件处理)
off_6F06E0 0x6f06e0 crypto/rand.Reader itab
off_904AD0 / off_904AB0 / off_904AF0 — SSH 算法全局
off_903300 — ifaceeq 全局
unk_654F20 0x654f20 newobject 类型(reader 对象)

10. 关键字符串

地址 字符串 意义
0x6a3098 (攻击者 RSA 公钥 PEM) 硬编码公钥
0x6a2f4e 勒索信模板 qTox 联系 + TOX ID
0x69695f dec or enc dirs, split by , enc/dec 双模式 flag
0x690c91 sorry_id_%v%v sorry_id 文件名格式
0x691f45 0123456789abcdef hex 编码表
0x691f75 gen aes fail: %w AES key 生成错误
0x691f65 rsa enc fail: %w RSA 加密错误
0x693394 write head fail: %w 文件头写入错误
0x693afa write head1 fail: %w 文件头块写入错误
0x693381 stream enc fail: %w 流加密错误
0x6975ce curve25519-sha256@libssh.org SSH 密钥交换算法
— crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in FIPS 140-only mode 识别 rsa.EncryptPKCS1v15
— crypto/rand: failed to read random data (see https://go.dev/issue/66821): 识别 crypto/rand
0x696192 testing simulated failure rand 故障注入测试

11. 混淆与反分析

  • garble 混淆:Go 编译期混淆,随机化 pclntab magic、符号名、字符串。
  • Go ABI:寄存器传参,反编译器常丢失参数语义,需汇编级追踪寄存器(RAX/RBX/RCX/RDX/RDI/RSI)。
  • 随机化:pclntab magic 破坏 → 标准 Go 解析器(GoReSym 等)失效;导航依赖字符串 xrefs。
  • FIPS 分支:存在 FIPS 模式 flag(byte_936849),非 FIPS 环境走 PKCS#1 v1.5。

12. 危害评估与取证要点

  • 不可恢复性:无攻击者私钥则无法解密;受害者私钥已外泄,赎金支付由攻击者主导。
  • 取证关键物:
    • ~/sorry_id_* 文件(含 RSA 加密的受害者私钥 + 机器信息);
    • .sorry 扩展名的加密文件(文件头含 RSA 加密的 AES 密钥);
    • .sorry_exist 标记文件;
    • 网络流量中的 init 信标(机器 ID、IP);
    • 勒索信文本(TOX ID 关联攻击者身份)。
  • IOC:
    • C2:68.183.190.253:80
    • TOX ID:3D7889AEC00F2325E1A3FBC0ACA4E521670497F11E47FDE13EADE8FED3144B5EB56D6B198724
    • 文件特征:.sorry / .sorry_exist / sorry_id_*
正文完
 0