共计 1322 个字符,预计需要花费 4 分钟才能阅读完成。
背景与痛点
Android 恶意软件检测面临的核心挑战是 动态行为隐藏 和代码混淆。传统特征匹配(如哈希值比对)容易被绕过,而动态分析又存在执行路径覆盖不全的问题。函数调用图(FCG)通过静态分析构建应用的全景行为模型,能有效揭示以下恶意特征:

- 隐蔽 API 调用(如偷偷发送短信的
sendTextMessage) - 敏感数据流 (从
getDeviceId到网络传输函数的调用链) - 异常控制流(如反射调用动态加载的恶意代码)
FCG 构建原理
1. 静态分析基础
FCG 的节点是函数(Method),边表示调用关系。构建过程分为两步:
- 方法体解析 :通过反编译 DEX 文件获取每个方法的字节码,识别其调用的其他方法(如
invoke-virtual指令) - 跨过程分析:解决以下难点:
- 虚方法分发(Virtual Method Dispatch)
- 反射调用(需结合字符串常量池分析)
- 动态加载(通过
ClassLoader追踪)
2. 关键算法
- 控制流分析:构建每个方法的 CFG(Control Flow Graph),确定执行路径
- 数据流分析:追踪 Intent、字符串参数等,识别跨组件的隐式调用
技术实现(Python 示例)
使用 androguard 库解析 DEX 文件生成 FCG:
from androguard.misc import AnalyzeAPK
def generate_fcg(apk_path):
# 加载 APK 并解析
a, d, dx = AnalyzeAPK(apk_path)
fcg = {}
# 遍历所有类方法
for method in dx.get_methods():
caller = method.get_full_name()
fcg[caller] = []
# 提取该方法的调用指令
for _, call, _ in method.get_xref_to():
callee = call.get_full_name()
fcg[caller].append(callee)
return fcg
恶意行为识别
图算法应用
- 社区检测:
- 使用 Louvain 算法发现密集子图(如加密挖矿代码簇)
-
示例特征:大量调用
MessageDigest但无 UI 相关调用 -
关键路径分析:
- 查找从敏感源(
getSubscriberId)到汇聚点(HttpClient.execute)的路径 - 使用 DFS 或 Yen’s K 最短路径算法
性能优化
- 图压缩:合并相同调用模式的节点(如模板代码)
- 增量分析:仅重新分析修改过的 DEX 文件
- 并行处理:
from multiprocessing import Pool def analyze_method(method): # 并行处理方法分析 pass with Pool(4) as p: p.map(analyze_method, dx.get_methods())
避坑指南
- 误报处理:
- 排除广告 SDK 等合法敏感调用
- 设置权重阈值(如至少 3 层敏感调用链)
- 混淆对抗:
- 识别常见混淆模式(
a.a.a.a类名) - 通过调用上下文还原语义(如
Runtime.exec无论被重命名为何都可识别)
总结与展望
当前 FCG 技术的局限性在于无法处理 Native 代码(JNI 调用)和动态生成的类(如热修复)。未来方向包括:
- 结合动态分析验证可疑路径
- 引入图神经网络(GNN)进行自动化模式学习
- 开发轻量级运行时 FCG 监控工具
正文完
