Drozer能发现所有隐藏组件吗?
Android App渗透测试--Drozer(实战篇)
对于许多初入移动安全渗透测试领域的研究者而言,Drozer无疑是一把锋利且功能集中的瑞士军刀。当它在设备上列出那些导出的Activity、Content Provider和Service时,那种“尽在掌握”的感觉往往令人振奋。然而,一个不容回避的尖锐问题随之浮现:Drozer真能发现所有隐藏组件吗?答案,可能会让过于乐观的你感到一丝寒意。

Drozer的探测机制:基于“静态”的审计
要理解Drozer的能力边界,首先得看它的工作原理。Drozer通过与安装在目标设备上的Agent代理进行交互,其核心探测逻辑依赖于分析应用的AndroidManifest.xml文件。简单说,它主要识别那些显式或隐式标记为exported=true的组件,或者虽未导出但被定义了Intent Filter的组件。这是一种典型的、基于清单文件声明的静态分析。说白了,Drozer是在读取应用“自己说出口”的接口清单。
“隐藏”组件的几种狡猾形态
那么,有哪些组件是Drozer的“盲区”呢?真正危险的漏洞,往往藏在这里。
- 动态注册的组件:这是Drozer最大的软肋之一。一个Activity或Broadcast Receiver如果仅在代码运行时通过
registerReceiver()或registerActivity()动态注册,那么它在清单文件中是“隐身”的。Drozer的静态扫描对此完全无效。攻击者需要结合逆向工程,分析代码逻辑,才能找到这些运行时才暴露的入口点。 - 权限保护下的非导出组件:如果一个组件设置了
exported=false,但同时通过android:permission指定了自定义权限,且该权限的保护级别(protectionLevel)是normal或dangerous,那么在拥有该权限的应用(如同签名应用、系统应用)看来,它实际上是“准导出”的。Drozer的常规扫描(如app.package.attacksurface)通常会将其视为非导出而忽略。识别这类组件需要更精细的权限与组件交叉分析,而这往往超出了自动化工具的默认范畴。 - 深度链接(Deep Link)与App Links中的复杂路径:虽然Drozer的
scanner.activity.browsable模块能发现一些可通过浏览器调用的活动,但对于那些需要特定数据格式、复杂URI结构或依赖服务器端验证的深度链接,简单的枚举可能无法触发或发现所有有效路径。这需要手动构造和模糊测试。 - 通过JNI/NDK调用的本地代码组件:Drozer的
scanner.misc.native可以找到包内的本地库,但识别这些库中哪些函数可以被外部不当调用,以及如何构造复杂的参数触发漏洞(如本地代码的内存破坏),则完全依赖于深入的人工逆向分析与动态调试。
一个被忽略的案例:隐形的广播接收器
想象这样一个场景:一款金融应用为了接收来自自家推送服务器的加密消息,在代码的onCreate()方法中动态注册了一个广播接收器,其Intent Filter动作是com.example.internal.PUSH_ACTION。这个接收器负责处理敏感的交易确认通知。
使用Drozer的app.broadcast.info扫描该应用,结果可能一片空白——因为清单文件中没有它。攻击者如果只依赖Drozer,就会与这个潜在的高危入口失之交臂。只有通过反编译,追踪代码执行流,才能发现这个“幽灵”接收器。如果该接收器在处理Intent时未充分验证来源,就可能成为伪造通知、实施钓鱼攻击的跳板。
工具是延伸,而非替代
因此,将Drozer视为“组件发现终结者”是一种危险的误解。它的真正价值在于高效地完成第一轮“表面清扫”,快速定位那些显而易见的攻击面,为测试者节省大量基础工作的时间。但安全测试的深度,从来不由自动化工具的上限决定,而由测试者对手动分析、代码审计和逻辑推理的投入程度决定。
一个成熟的移动安全研究员,会这样使用Drozer:先用它跑一遍,记下结果;然后毫不犹豫地打开反编译工具(如JADX、Ghidra),开始阅读代码,寻找那些没有写在“门牌”上的“后门”和“暗室”。Drozer给出了地图上标明的道路,而真正的挑战,往往在地图之外的迷雾里。

参与讨论
Drozer的快速表面扫出来的东西确实挺有用的。
感觉还能再细化点。
动态注册的Receiver到底要怎么手动抓到?有没有推荐的脚本?
我之前逆向一个金融App,发现一个隐藏的广播接收器,真是让人捏把汗。
除了Drozer,还可以用adb的dumppermissions配合手工检查权限交叉。
这玩意儿盲区太多,靠它直接上报告怕被打回。
看到有人只用Drozer报告说没有风险,结果后面被客户追问才发现暗藏的深度链接。
那如果应用在运行时才通过ClassLoader加载某个Service,Drozer根本看不见,这种情况有没有通用的检测思路?比如结合Frida实时hook?
对,先Drozer扫一遍再手工分析,省事多了 😊
说Drozer只能发现导出的组件有点片面,实际上它的scanner.activity.browsable还能抓到部分未导出的browsable activity,只是需要额外参数。
有人发帖说只要跑一次Drozer就能找全所有入口,结果被实测后全是漏网之鱼,真是笑死我了。