|
| 1 | +--- |
| 2 | +permalink: /blogs/20241001-wemod |
| 3 | +title: 学习某订阅付费程序过程 |
| 4 | +--- |
| 5 | + |
| 6 | +{% include title_patch.html %} |
| 7 | + |
| 8 | +{% include gen_index.html %} |
| 9 | + |
| 10 | +# 背景 |
| 11 | + |
| 12 | +玩单机游戏玩的不爽,想搞个 wemod 玩玩。可惜 wemod 今年年初开始付费使用,免费用户只有俩小时。 |
| 13 | +本人非常不爽开始搞事。 |
| 14 | + |
| 15 | +免责声明:本 blog 仅记录搞事的过程,不提供学习手段,请支持正版(doge) |
| 16 | + |
| 17 | +# 信息收集 |
| 18 | + |
| 19 | +先看 wemod 目录,看到一个 `app.asar`,可以大致确定是个 electron 程序。自己从零开始成本太高, |
| 20 | +看看前人有没有什么成果。 |
| 21 | + |
| 22 | +看到前人有搞学习版的,大致浏览了一下都是打包好的 `app.asar` 提供下载,不过版本都太老了。继续搜索, |
| 23 | +发现贴吧有人搞,时间还挺新,那么就开始研究这个。看到截图里的名字,开始搜索发现 github 被 dmca 了, |
| 24 | +但是在 google 的搜索中发现 rust 公开仓有这个东西,遂开始读代码。 |
| 25 | + |
| 26 | +# electron patch 逻辑 |
| 27 | + |
| 28 | +rust 仓里对 `app.asar` 进行 patch,主要 patch 了以下几个地方: |
| 29 | + |
| 30 | +## app-bundle.js |
| 31 | + |
| 32 | +对 `app-bundle.js` 的访问请求进行 patch,对结果是 json 格式的且访问的 URL 以 `/account` 结尾的 |
| 33 | +覆盖其订阅信息为 pro 版本 `{subscription: { type: 'pro'}}`。 |
| 34 | + |
| 35 | +这个效果就是将 wemod 获取用户信息的接口变更,始终返回 pro 版本订阅。 |
| 36 | + |
| 37 | +代码如下: |
| 38 | +```js |
| 39 | +if ("application/json" === e.headers.get("Content-Type")) { |
| 40 | + if (new URL(e.url).pathname.endsWith('/account')) { |
| 41 | + var originalData = await e.json(); |
| 42 | + return { |
| 43 | + ...originalData, |
| 44 | + subscription: { |
| 45 | + type: 'pro' |
| 46 | + }, |
| 47 | + ...{ |
| 48 | + |
| 49 | + username: 'Pro Unlocker' |
| 50 | + } |
| 51 | + } |
| 52 | + } |
| 53 | + return e.json() |
| 54 | +} |
| 55 | +return e.text() |
| 56 | +``` |
| 57 | + |
| 58 | +除了更改订阅,作者还对创作者身份进行了更改。众所周知,wemod 加入创作者需要申请和审核,因此这里修改后直接可以 |
| 59 | +使用创作者的对 cheat 的 debug 功能。 |
| 60 | + |
| 61 | +修改也非常简单,把 get 方法始终返回 true 即可: |
| 62 | + |
| 63 | +```python |
| 64 | +content.replace("get isCreator(){", "get isCreator(){return true;") |
| 65 | +``` |
| 66 | + |
| 67 | +## vendor.js |
| 68 | + |
| 69 | +对 `vendor.js` 文件新增一个逻辑,将所有的 pro 版本的 promotion 信息以及手机远程操作的功能入口进行关闭。 |
| 70 | +这个是因为远程操作的功能是需要远程服务器支撑的,我们不能暴露自己(doge),因此进行了防误触删除。 |
| 71 | + |
| 72 | +代码如下: |
| 73 | +```js |
| 74 | +;(()=>{ |
| 75 | + console.info("Pro Unlocker") |
| 76 | + let trig = () => { |
| 77 | + document.querySelectorAll('promotion-banner').forEach(element => element.remove()); |
| 78 | + document.querySelectorAll('remote-button').forEach(element => element.remove()); |
| 79 | + }; |
| 80 | + |
| 81 | + setInterval(() => trig(), 1000); |
| 82 | + trig(); |
| 83 | +})(); |
| 84 | +``` |
| 85 | + |
| 86 | +## index.js |
| 87 | + |
| 88 | +最后,为了我们 debug 方便,这个脚本还修改了 index.js,开启了 wemod 的 debug console,但是这里,作者的 |
| 89 | +版本不是最新的,最新的更换了写法: |
| 90 | + |
| 91 | +```python |
| 92 | +content = content.replace( |
| 93 | + "devMode:process.defaultApp", "devMode:process.argv.includes('-dev')") |
| 94 | +``` |
| 95 | + |
| 96 | +这样,当我们运行 wemod 时加个 `-dev` 的参数就可以开启 debug console 了。 |
| 97 | + |
| 98 | +# 完整性校验 |
| 99 | + |
| 100 | +当我们 patch 完,满心欢喜打开 wemod,却发现什么反应也没有。用终端打开看看有什么信息,果不其然,是 `app.asar` |
| 101 | +的完整性校验没过: |
| 102 | + |
| 103 | +``` |
| 104 | +[20068:1001/195046.954:FATAL:asar_util.cc(163)] Integrity check failed for asar archive (xxx vs xxx) |
| 105 | +``` |
| 106 | + |
| 107 | +无奈之下我选择了: |
| 108 | + |
| 109 | +原神启动!(不是 |
| 110 | + |
| 111 | +在 IDA 里打开 `app` 目录里带的 `WeMod.exe`,我们可以直接搜这个字符串:`Integrity check failed for asar archive`,只有一个函数: |
| 112 | + |
| 113 | +注意,这里不能打开外面那一层的 exe,那个只是一个入口,实际有功能实现的是 `app` 目录里的 `exe`。 |
| 114 | + |
| 115 | +<div style="text-align:center"> |
| 116 | +<img src="/static/blogs/20241001-wemod/asarcheck.png" alt=""/> |
| 117 | +</div> |
| 118 | + |
| 119 | +这里没啥想法,也不好 patch,再四处搜寻一下。。。 |
| 120 | + |
| 121 | +看到这个函数头有打 log,发现函数名 `ValidateIntegrityOrDie`,然后就能找到相应的源码: |
| 122 | +[https://github.com/electron/electron/blob/main/shell/common/asar/asar_util.cc](https://github.com/electron/electron/blob/main/shell/common/asar/asar_util.cc) |
| 123 | + |
| 124 | + |
| 125 | +看到这个函数返回值是 `void`,就可以直接把这个函数 patch 成 `ret` 就好: |
| 126 | + |
| 127 | +<div style="text-align:center"> |
| 128 | +<img src="/static/blogs/20241001-wemod/asarbypass.png" alt=""/> |
| 129 | +</div> |
| 130 | + |
| 131 | +# 尾声 |
| 132 | + |
| 133 | +最后运行程序就会弹 pro 激活了 |
| 134 | + |
| 135 | +<div style="text-align:center"> |
| 136 | +<img src="/static/blogs/20241001-wemod/result.png" alt=""/> |
| 137 | +</div> |
| 138 | + |
| 139 | +整体来说不是很难,核心就是在客户端读订阅信息的时候改成 pro 就能轻松学习。就是对 `exe` 打 patch 这里 |
| 140 | +还需要琢磨一下怎么搞成自动化的。 |
0 commit comments