某投屏软件去除强制更新

2026 春节回老家了一趟, 节前跟高中同学在一张床上深入交流了一下, 还跟另外一个在非洲肯尼亚的同学打了个视频, 他们老板在那边装了星lian, 按之前的网速是没法打微信视频的. 他也算搭上老板的顺风车了, 并且还各种摸鱼,
北京时间是晚上十点, 他们那边大概是下午两点的样子, 边上班边跟我们视频,他做的是桥梁设计,他开了 chatgpt pro 的会员,一个月大概1000多,让gpt 生成一个 50多页的pdf, 大概已完成了 60%-80,然后再反复迭代优化提示词,听他说能否节约一般的工作时间.

好了说正事, 就是这个深入交流的同学, 他家新盖了房子, 买了新的电视, 需要投屏. 有一款app 强制更新,让我帮忙看看, 于是有了这篇文章.

打开app, 申请完权限后, 直接进入到了自动更新.

img_2.png

我们jadx 打开app, 全局搜索 “更新”

img_2.png

此处比较可疑,我们frida hook 看看

1
2
3
4
5
6
7
8
9
10
11
12
Java.perform(function() {
let MainActivity = Java.use("com.cctv.tv.mvp.ui.activity.MainActivity");
MainActivity["a"].overload('boolean', 'boolean').implementation = function (z, z2) {
console.log(`MainActivity.a is called: z=${z}, z2=${z2}`);
this["a"](z, z2);
// this["a"](false, false);
// return this["a"](true, false);
console.log(111111)
// return this["a"](false, true);
// return this["a"](false, false);
};
});

结果是 MainActivity.a is called: z=true, z2=true
我们使用 frida 改改参数看看能否绕过更新, 亲测不管怎么组合, 都不能绕过更新。

于是问 chatgpt 如何绕过强制更新, gpt 说某些强制更新是通过服务端下发的数据来判断是否本地需要更新的, 于是试试看 charles 抓包
看 charles 能否 patch 掉自动更新.

img.png

直接 block List, 直接禁用该请求, 发现app 强制更新不弹出了. 直接成功.
还有一个办法, compose 这个请求,将返回值中的 versionCode 和 versionName 置为空 也可以跳过强制更新.

到此处已经有可用方案了, 就是通过 charles patch response. 但我同学不懂技术,他要装charles, 并且还要设置证书, 我想着有没有什么apk, 可以拦截 url, 于是尝试了 netguard 工具, 好像无法像charles 一样直接拦截, 我想如果有的话,应该就是小黄鸟这种或者如果设备够新的话,支持ebpf 特性,应该可以实现.

这里我没有试小黄鸟了. 我想重打包一下 apk, 这样,我这个不懂技术但深入交流过的同学就可以傻瓜式的使用了.

于是打开 AndroidManifest.xml, 找到 启动 activity.

img.png

大致看一下整个MainActivity, 有几处更新字眼, 大概率是有更新相关的逻辑的, 然后将整个 MainActivity 的代码 copy 给 chatgpt, 让它帮我们分析一下, 更新的逻辑大致在哪里.

gpt 回答说是在 onResume 里, jadx 查看 onResume

img.png

发现并没有反编译完全, 这里不想去用 android killer 等其他工具了, 直接看 smali 代码吧, 之前帮另一个同学重打包过一个应用, 也是改的 smali 代码, 不过那个时候是 2022年, 还没有 gpt 这么强大的工具, 需要自己学习,硬改smali 代码, 添加寄存器,用前还要申请, 一不小心就崩溃了.

这里我们让gpt 帮我们修改.

img.png

大致是patch, 将检测的结果颠倒黑白, 即可.

于是我们试试将源代码转化为 smali 代码.

1
java -jar apktool_3.0.1.jar d   video.apk -o app_src

然后按照gpt 的方法, 将 sget-boolean v0, Lc/e/c/l/a/h;->c:Z 改为 const/4 v0, 0x1. 让后续的条件永远不会满足,这样也不会走强制更新的逻辑.

然后将 smali 转为 java 代码.

1
java -jar apktool_3.0.1.jar b app_src -o unsigned_video.apk

然后这个时候还需要对 apk 进行签名. 否则
adb install unsigned_video.apk
Performing Streamed Install
adb: failed to install yangshi.apk: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed collecting certificates for /data/app/vmdl1002557303.tmp/base.apk: Failed to collect certificates from /data/app/vmdl1002557303.tmp/base.apk: Attempt to get length of null array]

签名

1
git clone https://github.com/techexpertize/SignApk.git
1
java -jar signapk/signapk.jar SignApk/certificate.pem signapk/testkey.pk8 unsigned_video.apk signed_video.apk

然后安装

1
adb install signed_video.apk

打开后发现,app正常使用,不会强制更新了.

总结:

  1. 这个apk 33M, 比较小, 强制更新的逻辑在 MainActivity, 将这个类的代码直接扔给gpt, 直接给出了结果,运气比较好.
  2. 巩固了如何对 apk 进行反编译, 回编, 签名.
  3. 改 smali 代码是 gpt 帮忙生成的. 如果自己改, 可能会面临闪退, 并且你不知道是不是由于有签名验证造成的。 不过这个应用是没有签名检测的. 如果想验证是不是smali 语法导致的闪退也很简单, 添加一个无关紧要的 smali 代码,例如打个日志,或者print hello 等,就是特别简单不会出错的代码, 然后再重打包,如果崩溃了就是有apk签名检测. 如果没有崩,说明就是smali 语法问题.