InShot (com.camerasideas.instashot) 逆向分析总报告
分析对象:Google Play 上的
com.camerasideas.instashot—— 原名 "InStaShot - Camera for Instagram",现为 InShot 视频编辑器(Video Editor & Maker),由杭州影笑科技(InShot Inc.)开发。 分析版本:v2.200.1530(versionCode 1530),APK 87.7MB,从 modyolo 镜像站获取(MOD 版:Pro 权益解锁 + 签名校验绕过,核心代码与官方一致)。 分析方法:jadx 1.5.6 全量反编译 → 30,794 个 Java 文件、~291 万行代码 → 4 个子代理并行深挖(视频编辑/图像编辑/商业化/库清单)。
1. 开发者与产品背景
| 项目 | 信息 |
|---|---|
| 开发者 | 杭州影笑科技有限责任公司(InShot Inc.,杭州) |
| 产品演变 | 2014 年发布 "InStaShot - Camera for Instagram"(相机应用,包名沿用至今)→ 转型为全能视频/图片编辑器 InShot |
| 全球用户 | 数亿级,支持 89 个语言目录(30+ 语言) |
| 商业模式 | Freemium:免费 + Pro 订阅(pro.permanent 永久 / vip.monthly / vip.yearly)+ 广告变现 |
| 竞争位置 | Google Play 视频编辑类头部应用(与 CapCut、VN 同级) |
2. 逆向工程过程(方法论可复用)
2.1 APK 获取
网络环境限制(大量 APK 镜像站 TCP 级不可达),最终路径:
- 探测可达主机 → 发现
modyolo.com(MOD 站)可用 - 分析其 WordPress 主题 JS → 找到下载接口
admin-ajax.php?action=k_get_download - 拿到 CDN 直链
files-2.modyolo.com/.../Inshot_v2.200.1530-modyolo.apk(84MB) - 注意:下载 CDN 对非浏览器 TLS 指纹有 WAF 拦截(curl/Node 均 403),但文件本体 CDN 放行
2.2 工具链(网络受限环境的替代方案)
- JDK 17:Corretto(AWS CDN,2MB/s,比 GitHub 快 60 倍)
- jadx 1.5.6:GitHub Release 被墙 → 从 Maven Central 递归解析依赖树组装(
io.github.skylot全模块 +com.android.tools.smali从 Google Maven 补拉),修 SLF4J 冲突、JADX_CONFIG_DIR沙箱重定向后成功反编译 - 反编译统计:27,214 个类全部处理,30,794 个 .java,154 个类失败(可忽略)
2.3 关键判定:这是 MOD 包
- 签名 = Android 默认 debug keystore(CN=Android, SHA1
61:ED:37:7E:85:D3:86:A8:DF:EE:6B:86:4B:D8:5B:0B:FA:A5:AF:81,SHA1withRSA) - 应用基类
B0.b extends bin.mt.signature.KillerApplication—— MT管理器(MOD 工具)的签名校验绕过类,直接实锤重打包 - v1 签名
Created-By: Android Gradle 8.0.2与内部元数据 AGP 8.12.3 矛盾 → 第三方重签 - 影响:代码仍是原版;原版发布签名信息无法取证
3. 应用形态与技术基线
3.1 Manifest 关键信息
versionCode=1530, versionName=2.200.1530, minSdk=24 (Android 7.0), targetSdk=compileSdk=35 (Android 15)- 权限:媒体(READ_MEDIA_*/RECORD_AUDIO)、广告 ID、FCM、Play Billing;无 CAMERA 权限(已转型为纯编辑器)
- 组件:61 Activity / 18 Service / 12 Receiver / 7 Provider
- 双进程架构:
:videoprocess独立进程运行VideoProcessService(前台服务 mediaProcessing|dataSync)→ 导出不阻塞 UI - 自定义 scheme:
inshot://inshotapp.com/deeplink/home+ App Links 深度链接
3.2 构建工具链(从 META-INF 取证)
| 工具 | 版本 | 证据 |
|---|---|---|
| Gradle | 8.14.3 | kotlin-tooling-metadata.json |
| AGP | 8.12.3 | app-metadata.properties + databinding 版本文件 |
| Kotlin | 2.1.0 | kotlin-tooling-metadata.json |
| Java | 11 | 字节码目标 |
| 混淆 | R8 全量模式(full mode)+ 资源收缩 | 代码单字母混淆、无 mapping 残留 |
| 插桩 | Didi Booster(booster-android-instrument) | ShadowAsyncTask/ActivityThreadHooker 等运行时类 + 应用代码调用 |
| 其他 | DataBinding/ViewBinding 开启、6 dex multidex、baseline profiles(assets/dexopt/baseline.prof) | |
| 泄露 | git commit e292e629d43aa300896807def7257c33af4e6a5c;构建窗口 ≈2025-01-29 |
3.3 原生库(47 个 .so × 2 ABI,仅 ARM;无 x86)
自研核心引擎(影笑自研 "is 系列"):
libisffmpeg.so(12.7MB,FFmpeg fork)、libisvideoengine.so、libisplayer.so、libisvideoutil.so—— 视频核心libanim_engine_lib.so(14.4MB,Lottie 系动画引擎 fork)、libskia.so(7MB,Skia 渲染)libImageKit.so(Skia 合成引擎)、libisTurboJpeg.so、libisblur.so、libinpaint.so、libpallet.so、libcaption.so、libglPixelReader.so、libanimated-frame.so- 音频:FMOD 授权中间件 +
libauto_beat.so(自动卡点)+libaudio_silence_dt.so+libsmoothvideo.so(光流平滑)+libvideo_stabilization.so - AI:
libMNN.so(阿里 MNN 推理引擎)+libYXAIEngine.so/libYXAImg.so(自研 AI 封装)+libface_detect.so+libportrait_matting_jni.so+libvid_seg.so+libvid_sot.so - 三方:
libcrashlytics*.so、libapplovin-native-crash-reporter.so、libfmod.so、libmmkv.so/libmarsxlog.so(微信)、libgpuimage-{library,extension}.so、libglide-webp.so、Fresco 系(libimagepipeline/static-webp/native-imagetranscoder/gifimage)、libpl_droidsonroids_gif.so、libdatastore_shared_counter.so、libcer.so(自研反篡改)、libc++_shared.so - AI 模型不在 assets(无 .tflite/.mnn),内嵌 so 或运行时从
inshot.cc/InShot/Model/...下载(md5 校验)
4. 总体架构
4.1 分层全景
┌─────────────────────────────────────────────────────────┐
│ 表现层:MainActivity + 60+ Activity + Fragment 双容器 │
│ (MVP: X3.A BaseMvpActivity → Presenter → IView 契约) │
├─────────────────────────────────────────────────────────┤
│ 业务层:Fragment/Presenter 对(视频/图像/拼图/拼接/设置/商店)│
│ 单例管理器集群:MediaClipManager / GraphicItemManager │
│ / VideoPlayer / UserManager / BackForward(撤销重做) │
├─────────────────────────────────────────────────────────┤
│ 框架层:自研 DI(ViewBinder)+ ButterKnife + EventBus │
│ + 自研启动调度器(AnchorsManager 式 DAG)+ 远程配置门面 │
├─────────────────────────────────────────────────────────┤
│ 渲染层:GPUImage 移植 + Skia(ImageKit)+ 自研 GtrDrawable │
│ + GL 线程渲染器(自研 EGL 循环)+ LUT 滤镜链(乒乓 FBO) │
├─────────────────────────────────────────────────────────┤
│ 引擎层(JNI):isffmpeg/isvideoengine/isplayer + EditablePlayer│
│ + VideoEditorUtil + anim_engine_lib + MNN + YXAIEngine │
├─────────────────────────────────────────────────────────┤
│ 基础设施:ReLinker/NativeLoader、xlog、MMKV、Coroutines、 │
│ OkHttp/Cronet、Gson(@SerializedName 稳定键草稿持久化) │
└─────────────────────────────────────────────────────────┘
4.2 架构决策要点
- 纯 MVP(非 MVVM):
X3.A<V,P>基类模板方法(L3()建 Presenter /N3()布局 /I3()回调),Activity 只当"接线板";跨层事件走 GreenRobot EventBus - 文档模型(Project-as-DTO):整个编辑工程 =
ParamInfo+ 各*ClipInfoGson DTO,字段名用@Jb.c("XX_n")(自打包 SerializedName)稳定契约 → 天然支持草稿持久化/跨页传递/云同步 - 单例管理器集群 + 观察者:MediaClipManager/AudioClipManager/PipClipManager/EffectClipManager 各自维护列表,变更经委托列表广播 → 桥接原生引擎
- 原生引擎是单一事实源:预览与导出共用
EditablePlayer(isplayer),导出仅切 mode=2 + 挂编码器;JNI 回调用@Keep静态方法 + WeakReference + 主线程 Handler;原生可反向回调 Java(selectMediaCodec让 Java 选硬解解码器) - 自研启动调度器:Application 里用 AnchorsManager 式 DAG(
Project.kt)编排InitializeApmTask → Env → Billing → State → Lib → Resource,优先级队列 + 主线程等待,任务间dependOn依赖;用 Didi Booster 插桩优化线程池/AsyncTask - 双进程:视频导出跑
:videoprocess前台服务,导出完成后通知主进程 - 防御性工程:黑屏检测、GL OOM 捕获、第三方 SDK 崩溃白名单静默(CrashHandler)、厂商机型黑名单修复(如 Transsion AIHelper 在 Android 15 的崩溃)、GLES 能力分级降级(低端机关闭高端特效)
4.3 安全/反分析(商业 App 常规操作)
- R8 全量单字母混淆 + 字符串池解密(
Le.n)、\u200b零宽空格包名水印 - 反篡改:
libcer.so原生校验证书 + SHA1 +openssl_pub.key;签名不一致上报pirate_app事件 - Play Integrity(Google + 华为双实现,meta-data 读项目号)+ 盗版检测
- 把应用类塞进
com.google.gson.internal包做全局静态钩子(反混淆陷阱) - AI 算法库(CerChecker)授权校验后才
initNative
5. 技术栈全景(第三方库清单,版本均来自代码常量/BuildConfig/META-INF)
媒体/图像
| 库 | 版本 | 用途 |
|---|---|---|
| ExoPlayer | 2.17.1 | 播放 |
| Glide(InShotModule.java 即其 @GlideModule) | — | 图片加载(89 个应用文件引用) |
| Fresco + SoLoader | — | 图片管线(WebP/GIF/转码原生模块) |
| GPUImage(cyberagent) | 2.x | 滤镜;libgpuimage-*.so + 2 个 GLSL |
| PhotoView / AndroidGifDrawable / Picasso(遗留) | — | 缩放查看 / GIF / 旧图片库 |
| Volley(遗留)、AndroidYouTubePlayer | — | 旧网络 / YouTube 嵌入 |
网络/序列化
OkHttp 4.11.0、Retrofit2 2.9.x(R8 混淆,KotlinExtensions 证明 ≥2.6)、RxJava2 2.2.x、Gson 2.9~2.10.x、protobuf-lite、Cronet(play-services-cronet 18.0.1)
广告(合计 ~6000 类,商业化大头)
- AppLovin MAX 13.3.1 聚合 + 适配器:AdMob 24.5.0 / Unity Ads 4.12.5 / Vungle 7.5.0 / InMobi 10.8.7 / Fyber 8.3.8 / PubMatic 4.8.0
- TradPlus 14.4.0.1、OM SDK(544 类,多网络副本)、Giphy SDK、DigitalTurbine
- 自研 "Shantanu MobileAds" 框架(强混淆)+ 自定义 waterfall JSON(32 步全指 AdMob)+ 设备定向投放(按机型/内存/系统版本)+ 频控 + 10s 激励观看窗口 + house ad 自推
Google/Firebase
Play Billing 7.1.1、App Update 2.1.0、Integrity 1.5.0、Firebase(analytics 22.5.0 / messaging / crashlytics / remoteconfig / appcheck / storage)、GMS 全家桶(7980 类)、UMP 3.2.0
工具/存储
MMKV + mars xlog(微信)、Coroutines 1.10.2、EventBus 3.x、ButterKnife 10.x、Booster、HiddenApiBypass、FMOD、vlayout(阿里)、UltraViewPager、Banner(youth)、KPSwitch、Commons Math3(残留)
明确结论
- 无 Dagger/Hilt(InShotModule 是 Glide 模块;全库零 Dagger)
- 无 AppsFlyer/Adjust(埋点只走 Firebase)
- 无测试框架残留(无 JUnit/Espresso/Robolectric/LeakCanary)
6. 四大模块深挖(详见分报告)
6.1 视频编辑(reports/video_editing.md,349 行)
- 三层 Presenter 链:
Q(BaseVideoPresenter)→C1(MultipleClipEditPresenter)→F6(VideoEditPresenter) - 时间线:
MediaClipManager(主轨)+ Audio/Pip/Effect 管理器;com/camerasideas/track/是时间轴 UI(TimelineDelegate/AudiolineDelegate/FilterlineDelegate/PiplineDelegate),RecyclerView 多行 + 可缩放 TimelineSeekBar + 波形 - 导出:策略模式
IEncoder→ AsyncHWEncoder(MediaCodec 异步+EGL input surface)/ FfmpegEncoder(原生 GLES 拉帧,伪装 MediaCodec.BufferInfo 输出)/ GifEncoder;硬编失败回退软编;自研原生MediaMuxer封装(非 android.media 的);看门狗:40 帧无输出报错 - 关键帧动画 Java 化:
VideoKeyframeAnimator+ Calculator(16 位 float 矩阵按时间戳插值) - 音频:FMOD 商业中间件(
org/fmod用 AudioTrack 当输出设备、MediaCodec 当解码桥);AutoBeatAlgo(libauto_beat)卡点 → AudioRhythmAnimator 驱动贴纸跳动 - 转场/动画:
TransitionInfo+AnimationProperty+ anim_engine_lib(Lottie fork,"org.instory.suit" 整包)
6.2 图像编辑(reports/image_editing.md,564 行)
- 双视图架构:SurfaceView(GL 渲染)+ ItemView(透明覆盖层处理手势),GLGraphicsContext 自研 EGL 线程
- 自研 "GraphicsDrawable" 画布模型(graphicproc 97 类):BaseItem 条目体系(Sticker/Text/Pip/Mosaic/Watermark/Border/Animation)+ GraphicItemManager 单例 + GtrRenderer + Gson 草稿序列化 —— 与 InShot 官方开源 GraphicsDrawable 同构
- 撤销重做 = 命令 + 备忘录:BackForward 四栈 + OpData(EditInfo 深拷贝快照)
- 滤镜:GPUImage 深度改造;
GPUImageEditorFilter= 调整链(GPUFilterChainGroup)+ 特效链;三套 LUT(经典 512² / AES 加密 LUT 资产 / GLES3 3D LUTGPU3DLookupFilter.glsl),乒乓 FBO 流水线 - AI 抠图:本地 MNN(
PortraitMatting,模型运行时下载)+ 云端 PreciseCutout 双引擎;蒙版 → OutlineProperty → MattingLayer shader - 文字:Spannable TextAttributes(30+ span 类型)+ JNI 排版引擎(org.instory.suit.textLayout)+ 115 个内置字体
- 导出:PixelBuffer 离屏 GL 渲染 → 黑屏检测 → 尺寸阶梯降级策略 → MediaStore pending 写入;JPEG 走 TurboJPEG(90 质量,无 EXIF)
- 涂鸦:8 种画笔策略 + 双缓冲 + 命令栈;粒子纯 Canvas+ValueAnimator
6.3 商业化(reports/monetization.md,783 行)
- 三层抽象:Shantanu 自研 SDK(强混淆,
\u200b水印)/ 投放配置层(AdDeploy 设备定向 + 远程 JSON,assets 全量回退)/ 业务接入层(7 个广告位单例 + 订阅判定门面) - 广告:AppLovin MAX 初始化延迟到主线程 idle;订阅用户跳过;插屏频控(存盘次数 + 跨天重置)、激励 10s 窗口 + 失败仍发奖开关
- 订阅:SKU 分组(permanent/vip.monthly/vip.yearly+freetrail/introductory)、4 商店 PurchaseManager(含华为)、Shantanu IAP 服务器验证 + 邮箱账户绑定(跨设备恢复)、
remove.ads去广告开关与广告强耦合 - 分析:统一门面
p348ri.M→ Firebase Analytics/Crashlytics,协程 Channel 队列 +sample_number采样 + 事件过滤 JSON;日志三路(Log/xlog/Crashlytics.log 镜像) - APM:自定义 CrashHandler(第三方 SDK 崩溃白名单静默:AdMob/Vungle/AppLovin/Unity/InMobi/Yandex/Firebase...)、RxJava 错误上报、WebView 多进程锁修复
- 隐私:UMP 同意流 + EU 专用隐私页(inshot.cc/website/.../privacypolicy_eu.html)+ CCPA Do-Not-Sell
6.4 SDK/构建清单(reports/sdk_inventory.md)
见第 3、5 节;另:META-INF 87 个版本文件精确还原 AndroidX 版本(core 1.15.0、appcompat 1.7.1、material 1.12.0、lifecycle 2.9.2、room 2.2.5(旧)、datastore 1.1.3...)
7. 学习要点:开发者是怎么做这个 App 的
7.1 可借鉴的工程实践
- 核心能力自研、通用能力采购:FFmpeg/Skia/Lottie 深度 fork 改造成自研引擎(isffmpeg/anim_engine_lib/org.instory),MediaCodec/MediaMuxer 只当底层原语;AI 用 MNN(开源)做推理底座 + 自研 YX 系列封装
- 文档模型编辑架构:整个工程可序列化(Gson + 稳定字段名),草稿系统、跨页传递、进程迁移、云备份全链路打通 —— 这是编辑类 App 最核心的架构决策
- 统一渲染管线:GPUImage 滤镜链(乒乓 FBO)+ Skia 合成 + 离屏 EGL 导出,预览与导出同一引擎;黑屏/GL OOM 防御
- 启动性能工程:DAG 化启动任务 + 主线程空闲再初始化广告 + Booster 插桩 + baseline profiles + 异步 inflate
- 双进程导出 + 前台服务,导出不卡 UI
- 远程配置驱动一切:广告 waterfall/广告位/频控/AB 测试/功能开关全部 Firebase RC 下发,assets 完整本地回退(灰度可回滚)
- 商业化代码独立成 SDK(Shantanu)+ 强混淆,与业务代码解耦;订阅与广告权益单一门面判定
- 全球化的落地:89 个语言目录 + EU 隐私合规差异化
7.2 局限性/教训
- 大量遗留依赖(Volley/Picasso/Room 2.2.5 旧版本)—— 大 App 依赖治理难
- 强混淆反噬调试效率;关键能力(动画引擎/抠图)依赖运行时下载,弱网体验受限
- 反篡改(cer/SignatureKiller 对抗)在 MOD 生态面前效果有限(本包即被 MT 管理器绕过)
8. 产出物清单
| 文件 | 说明 |
|---|---|
apk/Inshot_v2.200.1530.apk |
原始 APK(87.7MB,MOD 版) |
apk_extract/ |
解包产物(assets/lib/META-INF/manifest 二进制) |
out/jadx_src/ |
jadx 反编译源码(30,794 个 .java)+ 解码资源 |
reports/video_editing.md |
视频编辑模块深挖(349 行) |
reports/image_editing.md |
图像编辑/滤镜/AI 抠图深挖(564 行) |
reports/monetization.md |
广告/订阅/埋点/APM 深挖(783 行) |
reports/sdk_inventory.md |
全量库清单/签名/构建痕迹 |
reports/FINAL_ANALYSIS.md |
本总报告 |
tools/ |
自装工具链(Corretto JDK17、jadx 组装版、aapt2 等) |