能稳定识别框架、插件、Manifest、权限、原生桥、assets、部分接口/文案/路由字符串;但 Dart AOT 的核心 widget tree、状态机和算法默认不是可读源码,需要 Flutter AOT 专用工具或动态运行补证。
结论先行
它是 React Native / Expo / Hermes:index.android.bundle 是 Hermes bytecode v96,app.config 暴露 Expo SDK 53、expo-router、expo-media-library。产品逻辑比 Flutter 更容易通过字符串和 Expo 配置推断。
先用“存储焦虑”拿权限和首次扫描结果,再用重复/相似照片分组制造可见价值,删除前确认,关键动作/恢复/高级清理接订阅,购买后走服务端校验和归因分析。
Flutter 逆向边界
| 层级 | 静态能看到 | 难点 / 补法 |
|---|---|---|
| Native 壳 | Activity、Service、Receiver、Provider、权限、deep link、SDK、Billing、广告、推送、文件 provider。 | 高置信。Manifest + apktool/jadx 足够。 |
| Flutter assets | flutter_assets、图片、lottie、locale JSON、AssetManifest、插件痕迹,能反推产品模块和页面素材。 | 中高置信。界面视觉能推断,但无法还原完整 widget tree。 |
| Dart AOT / libapp.so | 部分字符串、接口域名、错误文案、埋点名、模型/功能名。 | 核心逻辑默认编成 AOT,不能直接得到 Dart 源码;需要 blutter / Doldrums / reFlutter、符号恢复、或动态 hook。 |
| 接口和远端配置 | base URL、path 片段、SDK endpoint、证书/加密库痕迹。 | 真实请求体、签名、remote config、paywall SKU 要靠抓包、Frida、logcat、真机流程。 |
本批 Flutter 样本里,AI Art Magic / AI Photo Lab 都能从 assets 和插件层看出 AI 图片、广告、分享、邮件/素材模块;但真正的生成 API、模板状态机和 paywall 触发逻辑需要动态补证。
APK 身份和技术栈
com.cleanerguru.app1.0.08cleanerassets/index.android.bundle · 2807432 bytes9653.0.0已有 iOS 机会报告锁到 Apple bundle gen.universe.app.cleaner;这次 Android APK 为 com.cleanerguru.app,bundle 内还出现 Play 链接 package 字符串。后续多版本采集必须用 package/bundle 锁定,避免同名 App 混淆。
Expo plugins
| Plugin | Config |
|---|---|
expo-router | |
expo-build-properties | {"android": {"kotlinVersion": "2.0.21"}} |
expo-splash-screen | {"image": "./assets/images/splash-icon.png", "imageWidth": 200, "resizeMode": "contain", "backgroundColor": "#ffffff"} |
expo-media-library | {"photosPermission": "Allow $(PRODUCT_NAME) to access your photos to find and remove duplicates.", "savePhotosPermission": "Allow $(PRODUCT_NAME) to save photos to your library.", "isAccessMediaLocationEnabled": false} |
expo-av | {"microphonePermission": ""} |
Manifest 证据
android.permission.ACCESS_MEDIA_LOCATIONandroid.permission.INTERNETandroid.permission.MODIFY_AUDIO_SETTINGSandroid.permission.READ_EXTERNAL_STORAGEandroid.permission.READ_MEDIA_IMAGESandroid.permission.RECORD_AUDIOandroid.permission.VIBRATEandroid.permission.WRITE_EXTERNAL_STORAGEcom.android.vending.BILLINGcom.google.android.gms.permission.AD_IDandroid.permission.READ_MEDIA_VIDEOandroid.permission.READ_MEDIA_AUDIOandroid.permission.READ_MEDIA_VISUAL_USER_SELECTEDcom.android.vending.CHECK_LICENSE
com.android.vending.BILLINGandroid.permission.READ_EXTERNAL_STORAGEandroid.permission.READ_MEDIA_IMAGESandroid.permission.WRITE_EXTERNAL_STORAGEandroid.permission.RECORD_AUDIOandroid.permission.MODIFY_AUDIO_SETTINGS
android.permission.READ_MEDIA_AUDIOandroid.permission.READ_MEDIA_VIDEOandroid.permission.RECORD_AUDIO
Manifest 合并后仍有部分 blocked 权限痕迹,需安装后看实际运行时弹窗。
Activities
| Name | Exported | Authorities | Intent filters |
|---|---|---|---|
com.cleanerguru.app.MainActivity | true | {"actions": ["android.intent.action.MAIN"], "categories": ["android.intent.category.LAUNCHER"], "data": []}; {"actions": ["android.intent.action.VIEW"], "categories": ["android.intent.category.DEFAULT", "android.intent.category.BROWSABLE"], "data": [{"scheme": "cleaner"}, {"scheme": "exp+cleaner"}]} | |
com.android.billingclient.api.ProxyBillingActivity | false | | |
com.android.billingclient.api.ProxyBillingActivityV2 | false | | |
com.google.android.gms.common.api.GoogleApiActivity | false | | |
com.google.android.play.core.common.PlayCoreDialogWrapperActivity | false | | |
com.pairip.licensecheck.LicenseActivity | false | |
Providers
| Name | Exported | Authorities | Intent filters |
|---|---|---|---|
com.reactnativecommunity.webview.RNCWebViewFileProvider | false | com.cleanerguru.app.fileprovider | |
expo.modules.filesystem.FileSystemFileProvider | false | com.cleanerguru.app.FileSystemFileProvider | |
androidx.startup.InitializationProvider | false | com.cleanerguru.app.androidx-startup | |
com.pairip.licensecheck.LicenseContentProvider | false | com.cleanerguru.app.com.pairip.licensecheck.LicenseContentProvider | |
产品流程推断
单 Activity 进入 RN/Expo,bundle 中有 onboarding status、trackOnboarding、hasCompletedOnboarding 等痕迹。
expo-media-library 权限文案直指“访问照片以查找并删除重复项”。
可见 getAssetsAsync、loadAndAnalyzeInRealTime、scanForDuplicates、扫描完成/智能更新状态。
可见 total photos、similar/duplicate、best result、clean up 等 UI/文案资产线索。
可见单张/多选删除确认,底层有 deleteAssetsAsync 一类能力,删除不可逆是核心风险点。
Free trial、weekly auto-renewable、purchase/restore/acknowledge/check status 等 token 完整。
可见 xscan API、uuid 登录、Play 订阅校验、restore subscription 路径。
AppsFlyer / Amplitude / Facebook / Firebase / RevenueCat 信号,用于广告归因、购买和漏斗事件。
Hermes Bundle 证据
这里保留 byte token 存在性做短证据;offset 用于本地复核,不代表源码行号。后续一节补充 Hermes 反编译后的 pseudo-code 结论。
media_scan_delete
| Token | Status | Byte offset |
|---|---|---|
getAssetsAsync | found | 507747 |
deleteAssetsAsync | found | 539334 |
Failed to find duplicates | found | 427078 |
scanForDuplicates | found | 502733 |
loadAndAnalyzeInRealTime | found | 420395 |
Photo access denied | found | 418788 |
scan completed | found | 381013 |
smart updating | found | 381029 |
total photos | found | 415692 |
Are you sure you want to delete this photo | found | 392184 |
Are you sure you want to delete selected photos | found | 476281 |
subscription_paywall
| Token | Status | Byte offset |
|---|---|---|
premium_subscription | found | 377950 |
subscription_product_id | found | 596500 |
purchaseProduct | found | 827354 |
purchaseSubscription | found | 827389 |
validateReceiptAndroid | found | 830316 |
validateSubscription | found | 830352 |
acknowledgePurchaseAndroid | found | 416587 |
checkSubscriptionStatus | found | 424323 |
restorePurchases | found | 545707 |
Free for 3 days | found | 418514 |
1 Week, auto-renewable | found | 422480 |
Welcome to Cleaner Guru Premium | found | 542564 |
auth_backend
| Token | Status | Byte offset |
|---|---|---|
https://api.xscan.app/ | found | 594372 |
https://api-dev.xscan.app/ | found | 594308 |
/app/signin/uuidv4 | found | 471308 |
/app/playstore/validateAndCheckExpiry | found | 471259 |
/api/subscriptions/restore | found | 471195 |
Checking token validity | found | 418185 |
Creating new account | found | 418271 |
Validate tokens on server | found | 417270 |
New tokens received | found | 418475 |
analytics_attribution
| Token | Status | Byte offset |
|---|---|---|
AppsFlyer | found | 426995 |
Amplitude | found | 420313 |
logPurchaseEvent | found | 824053 |
trackSubscription | found | 503455 |
trackOnboardingScreenView | found | 539408 |
trackAppLaunch | found | 527888 |
https://api2.amplitude.com/2/httpapi | found | 591454 |
https://api.eu.amplitude.com/ | found | 596549 |
https://sr-client-cfg.eu.amplitude.com/config | found | 391103 |
legal_store_links
| Token | Status | Byte offset |
|---|---|---|
https://universeapps.limited/cleaner/privacy.html | found | 518431 |
https://universeapps.limited/cleaner/tos.html | found | 768750 |
https://universeapps.limited/cleaner/billing.html | found | 510730 |
https://play.google.com/store/apps/details?id=com.cleanerguru.cleaner | found | 768631 |
Hermes 反编译后的扫描逻辑
这轮已把 hermes-dec 安装到项目 .venv 并成功跑完 hbc-file-parser、hbc-disassembler、hbc-decompiler。完整反编译输出保留在 ignored 的 data/extracted/package_forensics/runs/20260610-002429/cleaner-guru-cleaning-app/deep-tools,不提交原始 JS/hasm。
| 问题 | 静态还原结论 | 产品含义 |
|---|---|---|
| 照片怎么加载 | 先用 getAssetsAsync({mediaType: photo, first: 1, sortBy: creationTime}) 拿 totalCount,再按 after/endCursor 分页读取;其中一个实时路径批量值为 25,另一个全量缓存路径批量值为 500。 | 这是典型“先快速拿总量,再分批显示进度”的 onboarding/扫描体验。 |
| 每张照片取哪些字段 | 映射出 id、uri、timestamp、fileName、width、height;遇到 ph:// URI 会尝试 getAssetInfoAsync 拿 localUri。 | 这解释了它能做总量、进度、预览和删除,但不必一开始读取完整图片像素。 |
| 重复/相似怎么判断 | 反编译出的 findDuplicates 先按 timestamp 排序,用 Set 避免重复处理;内层只比较时间接近的候选,出现 5000ms 时间窗。arePhotosSimilar 当前只检查时间差是否小于等于 60000ms。 | 这个版本更像“按拍摄时间近似聚类 burst/连拍照片”,不是 pHash/AI 视觉相似。实现成本低,但误分组和漏识别风险都更高。 |
| 分组 key 怎么生成 | generateGroupKey 按年-月-日-小时:分钟生成 key。 | UI 上容易包装成“相似照片组”,但技术上更偏分钟桶。 |
| 扫描状态 | 可见 REQUESTING_PERMISSION、LOADING_PHOTOS、ANALYZING_DUPLICATES、COMPLETED、ERROR 等状态,并通过 callback 回传 totalPhotos/processedPhotos。 | 产品上能做实时进度、扫描完成、智能更新这些感知价值。 |
置信度:中高。证据来自 Hermes pseudo-code,还需要用受控测试相册动态验证实际分组结果,以及确认远端配置或其他版本是否替换了更强的视觉算法。
Activity / Flutter AOT / Ghidra 分流结论
| 问题 | 当前结论 | 下一步 |
|---|---|---|
| Activity 好不好深挖 | Cleaner Guru 只有 6 个 Activity,first-party 只有 1 个 launcher/home 容器;其余主要是 billing、Facebook/custom tab 和未知 SDK 壳。Activity 对它不是核心逻辑入口。 | Activity triage 已生成:research/app-package-forensics/cleaner-guru-cleaning-app/apk-pure-latest/activity-triage.html。本包继续以 Hermes bundle 为主线。 |
| Ghidra 对 Cleaner Guru 有没有价值 | 价值中等偏低。它是 RN/Expo 包,核心业务在 Hermes bytecode;native `.so` 多数是 RN/Hermes/Expo/图片管线库,Ghidra 更适合确认 native image/transcoder 是否有自研算法,而不是还原扫描状态机。 | native-ghidra lane 已跑通;本机安装在 tools/vendor/ghidra,JDK 21 由 runner 自动注入。优先跑可疑 first-party/native media `.so`,不要全量跑 SDK 库。 |
| Flutter AOT 怎么办 | 本批 Flutter 样本只有 armeabi-v7a/libapp.so 和 libflutter.so;blutter 官方路径主要面向 Android arm64,所以当前样本无法直接用 blutter。 | 后续抓带 arm64-v8a split 的 XAPK/APK,再跑 flutter-aot lane;若只有 32-bit,先退回 asset/string/endpoint/动态证据。 |
| 哪些 App 更适合 Activity + Ghidra | Refoto 和 PDF Reader 更适合。Refoto 有 104 个 Activity,其中 35 个 first-party,`HighDefinition`、`PeopleRemove`、`TemplateGenerate`、`TextBrush` 链路很清晰;还包含 libXYAI_CL.so、libXYAIBridge.so、librxffmpeg-core.so 等 native 学习候选。 | Refoto/PDF Reader 优先走 Activity triage + jadx,再对 AI/FFmpeg/PDF native `.so` 用 Ghidra 补函数和伪 C。 |
界面 / 素材线索
APK 内部素材名显示它至少准备了扫描/销售页/删除/结果类视觉:assets_salescreenanimation.mp4、assets_card1.mp4、assets_images_bestresult.png、assets_images_deletebuttonicon.png、src_assets_images_ph.png、src_assets_images_cl.png、src_assets_images_offericon.png。
| Asset | Bytes |
|---|---|
unknown/res/drawable-mdpi-v4/assets_images_bestresult.png | 264 |
unknown/res/drawable-mdpi-v4/assets_images_deletebuttonicon.png | 216 |
unknown/res/drawable-mdpi-v4/node_modules_exporouter_assets_arrow_down.png | 202 |
unknown/res/drawable-mdpi-v4/node_modules_exporouter_assets_error.png | 469 |
unknown/res/drawable-mdpi-v4/node_modules_exporouter_assets_file.png | 138 |
unknown/res/drawable-mdpi-v4/node_modules_exporouter_assets_forward.png | 188 |
unknown/res/drawable-mdpi-v4/node_modules_exporouter_assets_pkg.png | 364 |
unknown/res/drawable-mdpi-v4/node_modules_exporouter_assets_sitemap.png | 428 |
unknown/res/drawable-mdpi-v4/node_modules_exporouter_assets_unmatched.png | 4715 |
unknown/res/drawable-mdpi-v4/node_modules_reactnavigation_elements_lib_module_assets_backiconmask.png | 653 |
unknown/res/drawable-mdpi-v4/src_assets_images_chevronright.png | 118 |
unknown/res/drawable-mdpi-v4/src_assets_images_cl.png | 8408 |
unknown/res/drawable-mdpi-v4/src_assets_images_offericon.png | 180 |
unknown/res/drawable-mdpi-v4/src_assets_images_ph.png | 12641 |
unknown/res/drawable-nodpi-v4/cleaner_ic_foreground.png | 25373 |
unknown/res/raw/assets_card1.mp4 | 144650 |
unknown/res/raw/assets_fonts_spacemonoregular.ttf | 93252 |
unknown/res/raw/assets_salescreenanimation.mp4 | 731273 |
unknown/res/raw/assets_splashdark.mp4 | 173730 |
商店截图 OCR 模块
下面是已有公开商店截图采集的 OCR 摘要,帮助理解 Cleaner Guru 品类的产品包装;它反映 iOS 商店素材,不等同于这个 Android APK 全部功能。
STORAGEUSSTORAGE
CLEAN UPUSCLEAN UP DUPLICATE PHOTOS
DUPLICATE CONTACTSUSDUPLICATE CONTACTS Merged Version
PHOTO SWIPEUSPHOTO SWIPE TO SORT OUT
VIDEOSUSVIDEOS
CHARGING ANIMATIONUSCHARGING ANIMATION
PRIVATE PHOTOSUSPRIVATE PHOTOS Secret Storage
实现拆解:我们能学什么
| 模块 | Cleaner Guru 证据 | 可复用实现思路 | 风险边界 |
|---|---|---|---|
| 首次价值 | 扫描完成、total photos、similar/duplicate、best result。 | 先做只读 inventory + 本地分组预览,让用户先看到可清理空间和重复组。 | 不要先收费后看结果;否则评论风险会很高。 |
| 照片/视频清理 | expo-media-library、getAssetsAsync、deleteAssetsAsync、scanForDuplicates。 | iOS 用 PhotoKit,Android 用 MediaStore/ContentResolver;相似图用 pHash/dHash/embedding,重活放原生模块或后端 worker。 | 删除必须二次确认、可预览、尽量提供撤销或最近删除说明。 |
| Paywall | free trial、weekly subscription、purchase/restore/check status/acknowledge。 | 免费扫描 + 高级操作/批量删除/自动清理/压缩接订阅;后端做 receipt 校验和 entitlement。 | trial、自动续订、取消路径必须透明,不复制误导免费素材。 |
| 后端 | xscan API、uuid 登录、Play 校验、subscription restore。 | 匿名 UUID 账户 + entitlement API + receipt validation + remote config;本地不保存敏感媒体内容。 | 接口签名、证书 pinning、风控要动态确认;隐私政策要和实际上传行为一致。 |
| 增长归因 | AppsFlyer、Amplitude、Facebook/Firebase、RevenueCat 信号。 | 埋点覆盖 install、permission、scan_start、scan_result、delete_attempt、paywall_show、purchase、refund/support。 | 广告 ID、跨站追踪、ATT/Google Data Safety 要同步披露。 |
下一步动态分析计划
| 优先级 | 动作 | 要验证的问题 | 产物 |
|---|---|---|---|
| P0 | 安装到测试 Android,跑 first launch + permission + scan,不登录真实个人账号。 | 真实请求哪些权限;scan 前/后 paywall 位置;是否上传照片/缩略图/统计。 | logcat 摘要、屏幕路径、权限弹窗截图 manifest。 |
| P0 | Reqable/mitmproxy 抓包,必要时 Frida 绕过 pinning。 | api.xscan.app 的登录、订阅、配置接口和请求体 shape。 | 脱敏 HAR manifest、endpoint 表、request schema。 |
| P1 | 补 Hermes 反汇编工具链。 | 路由文件名、函数名、feature flag、paywall 状态机能否恢复更多。 | bundle symbol map / route map / 事件字典。 |
| P1 | 找更早 Android 版本。 | 1.0.0 是否初始功能;早期是否只做照片重复清理,后面才扩 contacts/videos/private/charging。 | 版本 diff HTML + 初始功能树。 |