APK 后门检测实战
背景
手上有一个可疑的 APK 文件,疑似携带后门程序。本文将使用之前介绍的四款工具,对该 APK 进行全面的安全分析。
注意:本文以
target.apk代指待分析的 APK 文件,实际操作时替换为真实文件名。
分析流程概览
第一阶段:快速预览(APK Analyzer)
↓
第二阶段:解包分析(APKTool)
↓
第三阶段:源码反编译(JADX)
↓
第四阶段:深度分析(dex2jar + JD-GUI)
↓
第五阶段:综合评估第一阶段:APK Analyzer 快速预览
操作步骤
- 打开 Android Studio →
Build→Analyze APK... - 选择
target.apk
检查重点
① 原生库(.so 文件)
查看 lib/ 目录下是否存在原生库文件。后门程序常常将核心恶意逻辑藏在 .so 文件中,因为相比 Java 代码,原生代码的反编译难度更大。
重点关注:
- 是否存在不应出现在该类型应用中的
.so文件 - 文件名是否可疑(如随机字符串、与包名无关等)
- 是否有异常大的
.so文件
② DEX 文件
查看 DEX 文件的大小和类数量:
- 异常大的
classes.dex可能意味着存在大量隐藏代码 - 多个 DEX 文件(
classes2.dex、classes3.dex)也需要留意
③ AndroidManifest.xml
APK Analyzer 可以解析 AndroidManifest.xml,直接查看:
- 申请了哪些权限
- 注册了哪些四大组件(Activity、Service、BroadcastReceiver、ContentProvider)
- 应用的包名和版本信息
危险权限清单
| 权限 | 风险说明 |
|---|---|
INTERNET | 联网发送数据 |
READ_SMS | 读取短信(验证码拦截) |
RECEIVE_SMS | 接收短信 |
READ_CONTACTS | 读取通讯录 |
RECORD_AUDIO | 录音 |
CAMERA | 拍照 |
ACCESS_FINE_LOCATION | 精确定位 |
SYSTEM_ALERT_WINDOW | 悬浮窗(钓鱼攻击) |
BIND_ACCESSIBILITY_SERVICE | 无障碍服务(高危) |
REQUEST_INSTALL_PACKAGES | 静默安装 |
RECEIVE_BOOT_COMPLETED | 开机自启 |
⚠️ 如果 APK 申请了大量与其功能无关的敏感权限,这是后门的重要信号。
第二阶段:APKTool 解包分析
解包命令
apktool d target.apk -o target_extractedAndroidManifest.xml 分析
解包后的 AndroidManifest.xml 是明文 XML,仔细检查:
<!-- 检查是否有可疑的静态广播接收器 -->
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- 检查是否有可疑的服务 -->
<service android:name=".HiddenService" android:exported="true" />
<!-- 检查是否有可疑的 ContentProvider(数据泄露渠道) -->
<provider android:name=".DataProvider" android:authorities="com.example.provider" />检查重点
① 启动项
搜索 BOOT_COMPLETED,检测是否有开机自启的组件。
② 加密/混淆的字符串
搜索 AndroidManifest.xml 中是否有可疑的 Base64 编码字符串或乱码。
③ 检查 res/values/strings.xml
应用可能将恶意 URL、IP 地址、C2 服务器地址隐藏在字符串资源中。
查看 smali 代码
APKTool 解出的 smali 代码位于 smali/ 和 smali_classes2/ 等目录。可以使用文本搜索工具(如 Grep)搜索可疑关键字:
# 搜索 IP 地址
grep -rnE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" smali/
# 搜索 URL
grep -rn "https\?://" smali/
# 搜索 Base64 编码的字符串
grep -rn "const-string.*[A-Za-z0-9+/]{40,}=*" smali/
# 搜索关键方法调用
grep -rn "Ljava/net/HttpURLConnection" smali/
grep -rn "Ljavax/crypto" smali/
grep -rn "Ljava/lang/Runtime;->exec" smali/第三阶段:JADX 源码反编译(核心环节)
操作步骤
# 直接打开 GUI
jadx-gui.bat
# 或者命令行反编译后浏览
jadx target.apk -d target_source搜索策略
这是整个检测流程中最关键的环节。按以下优先级逐项排查:
1. 搜索网络请求(寻找 C2 服务器)
在 JADX GUI 中使用 Ctrl+Shift+F 全文搜索:
| 搜索关键词 | 查找目标 |
|---|---|
http:// | HTTP 明文请求 |
https:// | HTTPS 请求 |
HttpURLConnection | Java 原生 HTTP 请求 |
OkHttpClient | OkHttp 网络请求 |
HttpClient | Apache HttpClient |
URL | URL 连接 |
Socket | TCP/UDP Socket 连接 |
InetAddress | DNS 解析 |
getInputStream | 获取输入流(接收数据) |
getOutputStream | 获取输出流(发送数据) |
2. 搜索敏感 API 调用
| 搜索关键词 | 查找目标 |
|---|---|
Runtime.getRuntime().exec | 执行系统命令(高危) |
ProcessBuilder | 启动进程 |
Process | 进程操作 |
DexClassLoader | 动态加载 DEX(代码动态加载) |
PathClassLoader | 类加载器 |
System.loadLibrary | 加载原生库 |
Cipher | 加解密操作 |
SecretKeySpec | 密钥生成 |
Base64 | Base64 编解码 |
getDeviceId | 获取设备 ID(信息窃取) |
getSubscriberId | 获取 IMSI |
getSimSerialNumber | 获取 SIM 卡序列号 |
getInstalledApplications | 获取已安装应用列表 |
queryContentProviders | 查询 ContentProvider |
ContentResolver | 内容解析器(数据访问) |
3. 搜索可疑字符串
| 搜索关键词 | 查找目标 |
|---|---|
.apk | 下载/安装 APK |
application/vnd.android | APK 下载类型 |
cmd / sh | shell 命令 |
chmod | 修改文件权限 |
/data/data/ | 数据目录访问 |
/sdcard/ | 外部存储 |
encrypt | 加密操作 |
decrypt | 解密操作 |
AES / DES / RSA | 加密算法 |
4. 查看 Application 类
APK 的 Application 类是代码的入口,恶意应用经常在 Application 的 onCreate() 中初始化后门逻辑。
// 可疑的 Application 示例
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
// 可疑:启动隐藏服务
startService(new Intent(this, HiddenService.class));
// 可疑:初始化网络连接
new Thread(new Runnable() {
@Override
public void run() {
// 连接到远程服务器
connectToC2();
}
}).start();
}
}5. 分析混淆代码
如果代码经过混淆(类名如 a.a.a、b.b.b),重点关注:
- 与网络通信相关的类
- 与文件 IO 相关的类
- 与加密相关的类
- 入口点(Application、MainActivity)
JADX 支持导出为 Gradle 项目,可以导入 IDE 中使用反混淆插件辅助分析。
第四阶段:dex2jar + JD-GUI 深度分析
操作步骤
# 转换
d2j-dex2jar.bat target.apk -o target.jar
# 用 JD-GUI 打开
jd-gui.exe target.jar用途
当 JADX 的反编译结果不理想时(如出现大量无法识别的方法调用),使用 dex2jar + JD-GUI 作为补充:
- JD-GUI 支持将源码批量导出为
.java文件 - 导出的源码可以用文本工具进行批量搜索
- 可以配合 CFR 或 Procyon 获得不同的反编译结果
小技巧:JD-GUI 导出源码后,使用
grep -r或findstr在导出的文件中批量搜索,效率比逐个查看更高。
第五阶段:完整性检测与签名校验
1. 签名信息检查
使用 jarsigner 查看 APK 签名信息:
jarsigner -verify -verbose -certs target.apk检查要点:
- 签名是否使用
jarsigner可验证 - 签名证书是否为开发者自有证书(自签名证书不一定有问题,但需要留意)
- 签名时间是否异常
2. 使用 keytool 查看签名证书
# 提取证书信息
keytool -printcert -jarfile target.apk3. 完整性检查
计算 APK 的 MD5 / SHA256,与官方版本对比:
certutil -hashfile target.apk MD5
certutil -hashfile target.apk SHA2564. 检测是否被二次打包
对比以下特征判断 APK 是否被修改过:
- 签名证书与官方版本不一致
- 添加了额外的文件或资源
- AndroidManifest 中添加了异常权限或组件
后门行为判断决策树
APK 是否申请了过多敏感权限?
├── 是 → 进一步检查
└── 否 → 风险较低
是否有开机自启组件?
├── 是 → 后门可能性较高
└── 否 → 继续排查
是否含有网络通信代码?
├── 是 → 检查通信目标地址
│ ├── 连接到可疑 IP/域名 → 高度可疑
│ └── 连接到正常服务 → 继续分析
└── 否 → 后门可能性降低
是否包含加密/解密代码?
├── 是 → 可能有数据加密回传
└── 否 → 继续分析
是否有动态加载 DEX 或执行系统命令的代码?
├── 是 → 高度危险,确认是后门
└── 否 → 继续分析
是否包含隐藏的 Service 或 BroadcastReceiver?
├── 是 → 后门可能性较高
└── 否 → 风险降低检测报告模板
完成分析后,建议按以下格式记录结果:
# APK 安全检测报告
## 基本信息
- 文件名:target.apk
- 包名:com.example.app
- 大小:XX MB
- MD5:XXXXXXXXXXXX
## 权限分析
- 高危权限:[列表]
- 可疑权限:[列表]
## 组件分析
- Activity:[数量]
- Service:[数量],可疑服务:[列表]
- BroadcastReceiver:[数量],可疑接收器:[列表]
- ContentProvider:[数量]
## 网络分析
- 发现的网络请求目标:[列表]
- 可疑目标:[列表]
## 恶意代码分析
- 系统命令执行:[有/无]
- 动态加载:[有/无]
- 加密操作:[有/无]
- 信息窃取:[有/无]
## 签名信息
- 签名状态:[有效/无效/自签名]
- 签名证书:[信息]
## 结论
- [安全/可疑/确认后门]
- 风险等级:[低/中/高/严重]
- 建议:[处理建议]常见后门特征总结
| 特征 | 危险等级 | 说明 |
|---|---|---|
| 开机自启 + 联网 | 🔴 高危 | 典型的远控木马行为 |
| 静默接收短信 | 🔴 高危 | 拦截验证码 |
| 执行 shell 命令 | 🔴 高危 | 获得系统控制权 |
| 动态加载 DEX | 🟡 中危 | 隐藏恶意代码 |
| 加密通信 | 🟡 中危 | 隐藏数据传输内容 |
| 频繁获取设备信息 | 🟡 中危 | 信息窃取 |
| 请求悬浮窗权限 | 🟠 低危 | 可能用于钓鱼 |
| 申请无障碍服务 | 🔴 高危 | 可以模拟用户操作 |
总结
APK 后门检测是一个系统性的过程,单一工具无法完成全部工作。推荐工作流如下:
- APK Analyzer — 快速了解 APK 结构,定位可疑文件
- APKTool — 解包获取 AndroidManifest 和资源文件
- JADX — 核心工具,反编译为 Java 源码进行关键字搜索
- dex2jar + JD-GUI — 辅助验证,批量导出分析
安全提醒:分析可疑 APK 时,建议在隔离环境(如虚拟机、沙箱)中操作,避免恶意代码在分析过程中执行。
分析了一个apk
以下是AI对apk反编译后的代码的分析结果:
一、基本信息
| 项目 | 内容 |
|---|---|
| 包名 | xchrpnbpq.jhwohjuaxg.ouxujaofffl(随机字符串,典型恶意软件特征) |
| Application类 | aomvl.hfghxzriv.yxswd.okd.GkjDli(随机包名) |
| SO库名 | liboh13bCwNjkXvzuS.so、libAEjZdKClmEOqtfz.so(随机字符串命名) |
二、后门架构——多层加载机制
该程序采用"加固壳"的方式隐藏真正的恶意代码:
GkjDli (Application入口)
│
├── 1. 加载 libAEjZdKClmEOqtfz.so (ShellNativeMethod2)
│
├── 2. 从 assets/nmtlfie/configs.bin 读取配置 (JSON)
│ ├── sha1 (签名校验)
│ ├── canResign (是否可以重签名)
│ ├── debuggable (调试开关)
│ ├── assets (是否复制额外assets)
│ ├── encryptNative (是否加密native)
│ └── arouter (ARouter路由配置)
│
├── 3. 从APK中提取 SO库 到 payload_lib/ 目录
│
├── 4. 从 assets/nmtlfie/tswqij 读取加密的DEX
│ └── 调用 AESUtil.decrypt() (JNI native) 解密
│
├── 5. 动态加载解密后的DEX
│ ├── Android 10+: InMemoryDexClassLoader (内存加载,无文件痕迹)
│ └── 低版本: DexClassLoader
│
├── 6. 通过反射偷梁换柱
│ ├── 替换 ActivityThread 中的 mApplication
│ └── 替换 ClassLoader
│
├── 7. 复制 assets/illadiu 到 files/ 目录
│ └── 通过 addAssetPath 注入资源
│
└── 8. 注册 ActivityLifecycleCallbacks 监听Activity生命周期三、权限列表(大量高危权限)
从 [AndroidManifest.xml](file:///d:/workspace/apktool/p0/vir001/AndroidManifest.xml) 中提取的关键权限:
| 权限 | 用途 |
|---|---|
| INTERNET | 网络通信 |
| READ_PHONE_STATE | 读取通话状态、设备信息 |
| PROCESS_OUTGOING_CALLS | 监控去电 |
| MODIFY_PHONE_STATE | 修改通话状态 |
| RECORD_AUDIO | 录音 |
| CAMERA | 拍照 |
| ACCESS_FINE/COARSE_LOCATION | 定位 |
| READ_EXTERNAL_STORAGE | 读取文件 |
| WRITE_EXTERNAL_STORAGE | 写入文件 |
| SYSTEM_ALERT_WINDOW | 悬浮窗 |
| REQUEST_INSTALL_PACKAGES | 静默安装APK |
| CALL_PHONE | 拨打电话 |
| MANAGE_OWN_CALLS | 管理通话 |
四、反检测机制
| 技术 | 位置 | 说明 |
|---|---|---|
| 反调试 | [b/c.java#k()](file:///d:/workspace/apktool/p0/vir.jar.src/b/c.java#L185-L214) | 读取 /proc/[pid]/status 检查 TracerPid,!=0 表示被调试 |
| 签名校验 | [GkjDli.java#attachBaseContext](file:///d:/workspace/apktool/p0/vir.jar.src/aomvl/hfghxzriv/yxswd/okd/GkjDli.java#L46) | 计算自身SHA-1签名,与配置中的sha1对比,不一致则弹Toast并2秒后退出 |
| SO库检测 | [b/c.java#f()](file:///d:/workspace/apktool/p0/vir.jar.src/b/c.java#L114-L148) | 读取 /proc/[pid]/maps 检查/data/data下的SO库 |
| 随机命名 | 包名、SO库名、资源路径 | 全部使用随机字符串,规避静态检测 |
五、真正的恶意载荷
从 [AndroidManifest.xml#L82-L89](file:///d:/workspace/apktool/p0/vir001/AndroidManifest.xml#L82-L89) 可以看到 真正的恶意代码在加密DEX中,包含:
im.ujpskfvwlu.tel.IncomingCallReceiver— 电话状态广播接收器- 监听
android.intent.action.PHONE_STATE来电状态变化 - 以独立进程
.call运行
- 监听
im.ujpskfvwlu.tel.CallApiAbove29Dialer— 拨号Activity(Android 10+)- 响应
android.intent.action.DIAL拨号意图
- 响应
这些类不在当前源代码中,说明真正的后门功能代码在加密的 assets/nmtlfie/tswqij 文件中,需要在运行时通过AES解密后动态加载到内存中执行。
六、关键后门行为总结
| 行为 | 说明 |
|---|---|
| 📞 电话监控 | IncomingCallReceiver 监听来电状态 |
| 📍 定位追踪 | 具备精确/粗略定位权限 |
| 🎤 录音 | RECORD_AUDIO 权限 |
| 📷 拍照 | CAMERA 权限 |
| 🌐 网络通信 | INTERNET 权限 + 可加载远程配置 |
| 📦 静默安装 | REQUEST_INSTALL_PACKAGES 权限 |
| 🛡️ 反调试 | TracerPid 检测 |
| 🔄 动态加载 | 解密DEX并在内存中执行,无文件痕迹 |
真正的后门逻辑(电话监控、数据窃取、远程控制等)被加密存储在 assets/nmtlfie/tswqij 文件中,需要运行时密钥通过JNI解密后才能看到完整代码。