Photo Recovery V1.0.3 独立逆向复核报告#
包名:
com.files.photo.recovery.restore.pro
样本:Google Play 测试机实装后通过 ADB 提取
版本:V1.0.3(versionCode 4)
分析日期:2026-08-11
方法:安装元数据核验、完整 APK 提取、SHA-256、JADX 1.5.5 静态反编译、Pixel 6a 有限运行时dumpsys验证
边界:未授予通知监听权限做破坏性测试,未等待完整通知周期,未抓取或解密网络流量,未读取测试机个人通知内容
1. 结论先行#
原《Photo Recovery 逆向分析报告》的核心代码发现,在当前线上 V1.0.3 中大部分仍然成立,而且常驻前台服务、24 分钟 Job、18 分钟 WorkManager 和 8 小时 Alarm 已在测试机运行时被直接观察到。
当前版本仍具备以下组合:
- 本地通知、前台服务通知、FCM 和 NotificationListenerService 四套通知相关能力。
notification.when = 当前时间 + 365 天的通知排序干预代码。- 通知删除 PendingIntent 指向前台服务的恢复路径。
- 前台 Service 在
onDestroy、onTaskRemoved中再次请求启动自身。 - 4–6 秒兜底 Job、约 24 分钟持久 Job、约 8 小时 Alarm、18 分钟 WorkManager、开机/更新广播和 FCM。
- NotificationListenerService 在功能开关开启、用户授予通知使用权后,扫描活动通知并对非允许集合调用
cancelNotification(key)。 - Firebase Remote Config 数据模型及 Offline/Online 两组硬编码兜底配置;Online 组仍包含普通通知 120 秒间隔、99 次上限和广告通知
upper_limit=-1。 - 桌面小组件、添加小组件引导和 24 小时
updatePeriodMillis。 - 冷启动、热启动、扫描完成、恢复成功、删除成功、清理成功、退出等大量广告场景。
因此,最稳妥的定性是:V1.0.3 是一款具有激进通知召回、持续后台调度和高密度广告变现能力的文件恢复/清理工具。“灰产团队”“攻击参数”“一定劫持所有通知”等主观或绝对化表述,仍不能仅靠本次证据直接认定。
2. 样本真实性#
2.1 测试机安装元数据#
| 项目 | 结果 |
|---|---|
| 设备 | Pixel 6a (bluejay) |
| 安装来源 | com.android.vending(Google Play) |
| 包名 | com.files.photo.recovery.restore.pro |
| versionName | V1.0.3 |
| versionCode | 4 |
| minSdk | 24 |
| targetSdk | 35 |
| compileSdk | 35(Manifest 构建元数据) |
| 安装时间 | 2026-08-11 21:23:09 |
2.2 提取文件#
| 文件 | 大小 | SHA-256 |
|---|---|---|
base.apk |
42,150,560 B | 0b1ab515be2d6c195f1e2992d7281dc9799f443f7b4fc50ce0f36a96ed1eaab9 |
split_config.arm64_v8a.apk |
2,143,423 B | f5835760dbec6077787ec92c86d360439f88309dd10f141e9ed9d05fba8779a8 |
split_config.xxhdpi.apk |
327,153 B | 7385fa6a1ce913b16e8266cb6c1fff1d6be0b491f8501dbc10fcc3429e2a121e |
JADX 共处理约 19,531 个类,报告 114 个局部反编译错误。Manifest、资源、常量、类结构和多数明确调用点可用;复杂混淆方法的控制流不能只依赖 Java 伪源码下结论。
3. 权限与关键组件#
Manifest 直接确认的敏感权限包括:
MANAGE_EXTERNAL_STORAGEREAD_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGEREAD_CONTACTS/WRITE_CONTACTSPOST_NOTIFICATIONS(重复声明)RECEIVE_BOOT_COMPLETEDFOREGROUND_SERVICE/FOREGROUND_SERVICE_SPECIAL_USEPACKAGE_USAGE_STATSWAKE_LOCKAD_ID、AdServices、FCM 和 Billing
关键自研组件:
| 组件 | 静态身份 | 关键配置 |
|---|---|---|
iIL0OiOQ.qnfE |
前台 Service | specialUse,subtype=quick entry |
iLiOQl.qnfE |
快速兜底 JobService | BIND_JOB_SERVICE |
Ql1lqlL.qnfE |
约 24 分钟心跳 JobService | persisted,高优先级 |
lefrHZ9.qnfE |
约 8 小时 Alarm Receiver | exported |
Qi0l0QQ.qnfE |
开机/更新 Receiver | BOOT_COMPLETED、MY_PACKAGE_REPLACED |
iqQiiOL.qnfE |
FirebaseMessagingService | FCM token/消息入口 |
MyNotificationListenerService |
通知监听服务 | 需用户授予通知使用权 |
MyWidgetProvider |
桌面小组件 | 24 小时更新周期 |
4. 后台调度与保活#
4.1 静态确认#
p298a.AbstractC4451c 明确实现:
- 4–6 秒兜底 Job:
minimumLatency=3999ms、overrideDeadline=5999ms、persisted。 - 约 24 分钟 Job:
minimumLatency=1,446,000ms、overrideDeadline=1,449,999ms、persisted,Android 13+ priority 400。 - 约 8 小时 Alarm:
ELAPSED_REALTIME_WAKEUP,延迟28,799,365ms。 - FCM topic 订阅与 30 秒至 24 小时指数退避。
- 在条件满足且服务未标记存活时调用
startForegroundService(),失败后转兜底 Job。
iIL0OiOQ.qnfE 明确实现:
onCreate构造并启动前台通知。onStartCommand返回START_STICKY对应值1。onDestroy调用前台服务启动入口。onTaskRemoved清除存活标记并再次调用启动入口。
4.2 Pixel 6a 运行时确认#
App 打开约 5 分钟后,系统实际状态中观察到:
| 运行项 | 实际证据 |
|---|---|
| 常驻前台 Service | iIL0OiOQ.qnfE 正在运行,isForeground=true |
| 前台通知 | id 2084960406,ONGOING_EVENT / NO_CLEAR / FOREGROUND_SERVICE,visibility PUBLIC |
| 24 分钟 Job | Ql1lqlL.qnfE,persisted、priority 400、minimum latency 约 24m06s |
| WorkManager | tag #iLiOQl#,下一次约 18 分钟 |
| 8 小时 Alarm | lefrHZ9.qnfE,ELAPSED_WAKEUP,约 7h55m 后触发,系统给出 1 小时窗口 |
| FCM Service | iqQiiOL.qnfE 已被绑定并存在活动 ServiceRecord |
这证明上述链路不只是“包内具备能力”,至少在首次打开后的当前配置下已经实际注册或运行。
仍未验证:强杀、Force Stop、重启设备、Doze、后台限制、划除任务、划除通知后能否在各 Android/厂商系统稳定恢复。Android 系统限制会影响最终成功率,不能表述为“用户一定关不掉”。
5. 通知系统#
5.1 前台服务通知#
p298a.C4450b 确认:
- 非小米设备的通知时间为
TimeUnit.DAYS.toMillis(365) + System.currentTimeMillis()。 - Notification 设置
deleteIntent。 - 删除 PendingIntent 最终指向前台 Service。
- 通知包含高优先级、公开可见、常驻等设置。
未来时间戳会影响部分系统/ROM 的通知排序,但“必然永久置顶”仍依赖系统排序策略,不能绝对化。
5.2 本地通知远程配置#
V1.0.3 的 p306a9.C4570q 仍内置两组兜底 JSON:
| 配置 | 普通通知上限 | 普通通知间隔 | repetitions | 广告通知上限 |
|---|---|---|---|---|
| Offline_A | 5 | 1,800,000ms(30 分钟) | 1 | -1 |
| Online_B | 99 | 120,000ms(2 分钟) | 3 | -1 |
Online_B 还包含:
continuous_ntf_num=12ntf_cooling_time=120000max_visible_ntf=5- Android 16 相关
os16_max_visible_ntf=1 - 多个 photo、video、document、screenshot、contacts、notification cleaner 等路由素材
这些值确认了“客户端兜底能力”,但不等于所有线上用户当前都使用 Online_B。要认定真实投放频率,需要读取 Remote Config 实际激活值或长时间动态观察。
5.3 NotificationListener#
静态代码确认:
- 服务会读取活动通知列表。
- 当内部通知管理开关为真时,将允许集合与本应用包名合并。
- 对不在集合中的活动通知调用
cancelNotification(key),然后解析为NotificationBean并入库。
重要前提:用户必须在系统设置中手动授予通知使用权,且内部功能开关开启。本次没有授予该权限做破坏性验证,因此结论是“代码路径确认、实际取消效果未验证”。
5.4 FCM#
iqQiiOL.qnfE 会主动取得 FCM token,并检查 google.delivered_priority、google.priority_reduced、google.priority。反编译后的复杂分支存在控制流警告,当前不能仅凭 Java 伪源码精确断言每种优先级对应的最终路径;但 FCM Service、前台服务启动入口和相关事件上报均确认存在。
6. 桌面小组件#
appwidget_info.xml 确认:
minWidth=300dpminHeight=100dpupdatePeriodMillis=86,400,000mswidgetCategory=home_screen
代码确认存在 requestPinAppWidget(),并从主页、启动、设置、退出等多个来源记录添加入口。小组件点击路由清理、恢复、联系人等业务场景。
需要修正旧报告的一点:24 小时更新周期是系统调度请求,不保证每天精确唤醒或准时执行;会受待机、省电和厂商策略影响。
7. 广告与商业化#
包内确认存在 Google Mobile Ads、Meta Audience Network、Pangle、Mintegral/MBridge、InMobi、Vungle、ThinkUp/TopOn 相关代码,以及 Adjust、Firebase 和 Billing。
Online_B 内置广告配置确认的业务场景包括:
- ColdOpen / HotOpen
- GuideCompletionInt
- ScanCompleteInt
- FolderClickInt
- RecoverySuccessInt
- DeleteSuccessInt
- CleanSuccessInt
- ScanResultExitInt
- RecoveredExitInt
- ContactExitInt
- NotificationExitInt
- CleanerExitInt
其中热启动兜底间隔为 5 秒;Folder/Recovered/Contact/Notification/Cleaner Exit 等场景包含 IntervalNum=1、IntervalTime=10000。这是客户端兜底配置,不代表远程线上策略必然一致。
8. 对旧报告的逐项复核#
| 旧报告主张 | V1.0.3 复核 | 说明 |
|---|---|---|
| 包名、SDK、主要权限 | 确认 | 当前 versionCode 已升至 4 |
| 未来 365 天通知时间 | 确认 | C4450b 直接代码证据 |
| deleteIntent 回前台服务 | 确认 | 静态调用链确认 |
| Service 在销毁/划任务后自恢复 | 确认 | onDestroy/onTaskRemoved 直接代码证据 |
| 4–6 秒、24 分钟、8 小时调度 | 确认 | 静态与运行时双重证据 |
| 18 分钟 WorkManager | 确认 | 运行时存在下一次约 18 分钟的 Job |
| Online_B 2 分钟/99 次 | 确认是硬编码兜底 | 未确认当前线上激活值 |
| NotificationListener 取消非允许通知 | 确认代码路径 | 需用户授权;未做实际取消测试 |
| FCM 高优先级一定拉前台服务 | 部分确认 | 相关能力存在,混淆分支需指令级或推送动态验证 |
| Widget 每天至少唤醒一次 | 表述过强 | 只能确认 24 小时更新请求 |
| “用户关不掉 App” | 不成立为确定事实 | Android 限制、Force Stop、厂商策略会影响结果 |
| “灰产团队、规避审核” | 无法直接证明主观意图 | 可描述高风险设计,不宜认定动机 |
9. 风险结论#
已确认的高风险设计#
specialUse/quick entry前台服务与实际持续后台运行之间存在明显用途解释风险。- 通知时间设置为未来 365 天、删除通知触发服务恢复,属于激进通知控制。
- Service、Job、Alarm、WorkManager 和 FCM 形成多路径后台调度。
- Online_B 客户端兜底允许极高通知频率。
- NotificationListener 具备取消其他应用通知并转存的能力。
- All Files Access、联系人和通知监听等权限组合带来较高隐私与审核压力。
尚不能确认#
- 当前线上用户实际采用 Offline_A 还是 Online_B,或其他远程配置。
- 每日真实通知数量与广告展示频率。
- FCM 服务端实际推送策略。
- 通知监听权限是否被强诱导、取消了哪些具体通知。
- 各 Android 版本和厂商 ROM 下的后台恢复成功率。
- “团队主观恶意”“刻意逃避审核”等意图性判断。
10. 推荐的下一步动态测试#
若需要把报告提升为可提交的安全/政策证据,建议在干净测试机上继续:
- 记录 Remote Config 激活结果,但不绕过 TLS 或处理真实用户数据。
- 分别测试 Home、最近任务划除、停止服务、重启、Doze、后台限制和 Force Stop。
- 在专用测试环境授予通知使用权,创建测试通知,验证允许集合和取消逻辑。
- 连续观察 24 小时,记录通知时间、类型、数量、路由和触发来源。
- 用测试 FCM 或合法可控环境验证 high/normal priority 分支。
- 对照片恢复功能放入已知测试文件,验证它是在扫描现存缓存/缩略图,还是具有真实已删除扇区恢复能力。
11. 产物位置#
- 原始 APK:
photo-recovery-v1.0.3/apk/ - JADX 结果:
photo-recovery-v1.0.3/jadx/ - Manifest:
photo-recovery-v1.0.3/jadx/resources/AndroidManifest.xml - 本报告:
Photo_Recovery_V1.0.3_独立复核报告.md