这是一个 LSPosed 模块,用于修复部分 ColorOS 相册无法连接飞牛 NAS 的问题。问题根因是相册在本地加载 token 解密 prefix 时调用 cryptoeng cmd 26,但系统底层拒绝了 com.coloros.gallery3d 进程,导致 prefix 为空、token 解密失败、NAS 连接流程无法继续。
- 只作用于
com.coloros.gallery3d。 - Hook 相册内 token 解密类的
e(),也就是相册侧 prefix 加载方法。 - 先按已知混淆类名(
erq、in80、op80、qp80)和完整方法结构查找;未确认命中时按结构扫描相册 APK 的 dex,扫描失败后才使用兼容旧版相册的类名 fallback。 - 优先保留系统原始
cryptoeng路径,只有原方法返回空字符串或null时才提供 fallback。 - fallback 会优先解析当前安装的相册 APK dex 字符串池,自动提取包含
GwToken的精确 prefix。 - 如果 APK 扫描失败,会使用当前已验证的飞牛 token prefix 作为兜底。
- 这是纯 legacy Xposed Bridge 模块,不使用 libxposed API。
- 模块内置 legacy 作用域推荐,LSPosed 应自动推荐
相册 / com.coloros.gallery3d。
ColorOS 相册会通过已保存的 access token 和 refresh token 构造飞牛 NAS 的 ConnectionSetupData。token 解密使用 AES-GCM,密钥派生方式是:
SHA-256(prefix + deviceId)
受影响的系统版本中,相册会通过 cryptoeng cmd 26 获取 prefix。但 cryptoeng 根据调用进程做权限检查,拒绝了相册进程,导致 prefix 为 null。随后 token 解密返回 null,相册也就不会继续建立 NAS 连接。
本模块只在原始 prefix 加载方法执行之后检查结果:
- 如果原方法已经成功返回 prefix,模块不做任何修改。
- 如果原方法返回空或
null,模块从相册 APK 的 dex 字符串池中解析飞牛 prefix 并返回给相册。 - 相册随后继续执行它自己的 token 解密和 NAS 连接流程。
模块不会伪造 token,不会伪造连接对象,也不会跳过飞牛服务端认证。它只恢复相册原有链路缺失的本地 prefix 值。
- 不修改相册 APK。
- 不修改 MyDevices。
- 不修改数据库。
- 不修改账号绑定或 NAS 设备记录。
- 不绕过飞牛服务端认证。
- 不打印、不保存、不上传 token。
- 不在相册进程外解密 token。
LSPosed/Xposed 要求:
- 最低声明 API:
82 - 推荐作用域:
com.coloros.gallery3d - 入口:
assets/xposed_init - 作用域推荐:
AndroidManifest.xml中的xposedscopemetadata - 不包含
META-INF/xposed/java_init.list,不声明 libxposed 入口。 - 编译依赖:
de.robv.android.xposed:api:82
已在 ColorOS 16 / Android 16 的相册版本上验证。附近版本理论上也可用,但需要保持以下点不变:
- 目标包名:
com.coloros.gallery3d - prefix 加载方法:
e(),无参、返回String - token 解密入口:
b(String, String),返回String - token 解密类的日志 tag 字面量:
TokenDecryptor - token 密钥派生方式:
SHA-256(prefix + deviceId)
相册每次大版本都会重排混淆类名,已核实的对应关系:
| 相册版本 | token 解密类 |
|---|---|
| 早期 ColorOS 16 | com.oplus.aiunit.vision.erq |
| 早期 ColorOS 16 | com.oplus.aiunit.vision.in80 |
| 16.40.13 | com.oplus.aiunit.vision.op80 |
| 16.40.22 | com.oplus.aiunit.vision.qp80 |
16.40.22 的真实 DEX 与设备 hook 验证记录见 docs/validation/gallery-16.40.22.md。
所以类名只作为快速路径。已知类全部失配或不满足完整方法结构时,模块会扫描相册 APK 的 dex,找出同时声明 e() 与 b(String, String) 且代码里加载了 TokenDecryptor 日志 tag 的类 —— 在 16.40.22 上全 APK 有且仅有一个类满足(qp80)。只要上面那几点不变,后续改名不再需要发新版。结构扫描仍无结果时,才会按类名兼容缺少 b(String, String) 标记的早期版本。
如果 OPPO/OnePlus 后续改了方法名、结构或 token 派生方式,模块仍需跟进适配。
GitHub Actions 会在每次 push、pull request 和手动触发时自动构建 APK。主线 push 和手动构建会上传使用项目固定 release key 签名的 APK;外部 pull request 因无法读取仓库 Secrets,只上传 unsigned release APK。
也可以用 Android Studio 打开本仓库,然后运行 app 构建任务。
本地有 Gradle 时可以执行:
gradle :app:assembleRelease如果发布前需要仓库内置 Gradle Wrapper,可以在有 Gradle 的机器上执行一次:
gradle wrapper --gradle-version 8.7本地构建产物位置:
app/build/outputs/apk/release/app-release-unsigned.apk
release APK 需要自行签名后再分发。
GitHub Actions 主线构建会额外生成:
app/build/outputs/apk/release/app-release-signed.apk
固定 release 证书 SHA-256:
37653B3C5DF69F83C3BB16C6BF7ADC7BE25AD0B34EB0EDCFA27A33CD2F3EB1BD
从 0.1.4 开始,正式安装和后续覆盖升级均使用该证书签名的 release APK。CI debug APK 使用临时 debug key,不作为稳定升级包。
- 安装 GitHub Actions 生成的 signed release APK。
- 在 LSPosed 中启用模块。
- LSPosed 应自动推荐
相册 / com.coloros.gallery3d作用域,只保留这个作用域即可。 - 强停相册或重启手机。
- 打开相册,进入飞牛 NAS / 私有云入口。
LSPosed 日志中应能看到:
ColorOSFeiniuBridge: installed for com.coloros.gallery3d class=com.oplus.aiunit.vision.qp80 via=known-name
ColorOSFeiniuBridge: prefix fallback supplied source=apk-dex len=33
via= 说明目标类是怎么找到的:
known-name:命中已知混淆类名,且该类同时带b(String, String)解密入口。dex-scan:已知类名全部失配或不满足完整解密结构,改由 dex 结构定位命中。相册刚升级过大版本时属正常。known-name-unconfirmed:DEX 结构扫描失败后,回退到仅确认e()的旧版已知类。
随后相册会继续原有连接流程,并连接飞牛 NAS 服务。
- 没有
ColorOSFeiniuBridge日志:模块没有被 LSPosed 加载,检查模块是否启用、作用域是否包含com.coloros.gallery3d、是否重启或强停相册。 prefix fallback unavailable for com.coloros.gallery3d:模块加载了,但一个可 hook 的目标都没找到 —— 已知类名全部失配,dex 结构定位也没命中。相册的 token 解密结构变了,需要重新适配。dex scan did not find a token decryptor class:结构定位扫完全部 dex 无果,同上。- 没有
prefix fallback supplied:原始cryptoeng可能已经成功,或者没有触发飞牛入口。 - fallback 后仍无法连接:检查相册日志里是否有
AEADBadTagException、token 过期、NAS 不可达、账号绑定异常等问题。 - token 解密成功但相册为空:本模块只恢复连接构造,照片索引和同步状态由相册与飞牛 NAS 自身处理。
常用排查命令:
adb shell logcat | grep -iE 'ColorOSFeiniuBridge|FeiniuNasSDK|TokenDecryptor|NasAlbum|cryptoeng'
adb shell su -c 'ss -tnp | grep 5667'本模块仅用于用户访问自己拥有并已绑定的飞牛 NAS。模块恢复的是相册本地 prefix 加载失败的问题,不改变 token 来源、不改变服务端校验、不改变账号或设备绑定。
请不要将本模块用于访问你不拥有或无权访问的设备、账号或 NAS 服务。
MIT