Commit 01a2cf55f20bdd20c0ddafded6fdc70307da0da8
1 parent
6d30843c
docs(xhs_lsposed_a16_fix): 更新 STATUS.md + 修复 update_xhshook_db.sh inode 陷阱
- STATUS.md:更新至 2026-06-30 00:33 验证通过状态,新增捕获到的额外 签名 header(x-mini-sig/mua/s1/gid、x-legacy-sid、shield), 补充 curl HTTP 200 复现验证结果,记录 lspd crash 恢复流程 - update_xhshook_db.sh:改用 Termux Python 原地 UPDATE + wal_checkpoint 代替 cp/adb push(后者改变 inode,lspd FileObserver 监听旧 inode 不刷缓存) - STATUS.md "已知不行的路线" 新增 adb push DB 和手动重启 lspd 两条陷阱 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Showing
2 changed files
with
103 additions
and
30 deletions
xhs_lsposed_a16_fix/STATUS.md
| 1 | -# XHS MITM 进度备忘 — 2026-06-29(Hermes 接手版) | 1 | +# XHS MITM 进度备忘 — 2026-06-30(Hermes 接手版) |
| 2 | 2 | ||
| 3 | 写给设备上 Hermes Agent 的完整上下文。**直接可用**,无需 Mac 介入的操作都写了命令。 | 3 | 写给设备上 Hermes Agent 的完整上下文。**直接可用**,无需 Mac 介入的操作都写了命令。 |
| 4 | 4 | ||
| @@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
| 13 | 13 | ||
| 14 | --- | 14 | --- |
| 15 | 15 | ||
| 16 | -## 当前设备状态(2026-06-29 17:22 验证通过) | 16 | +## 当前设备状态(2026-06-30 00:33 验证通过) |
| 17 | 17 | ||
| 18 | ``` | 18 | ``` |
| 19 | 设备:Pixel 10 Pro Fold | 19 | 设备:Pixel 10 Pro Fold |
| @@ -22,6 +22,7 @@ Magisk:30.7 | @@ -22,6 +22,7 @@ Magisk:30.7 | ||
| 22 | LSPosed (Vector fork):正常运行,lspd 进程存活 | 22 | LSPosed (Vector fork):正常运行,lspd 进程存活 |
| 23 | xhshook:注入 com.xingin.xhs 成功 | 23 | xhshook:注入 com.xingin.xhs 成功 |
| 24 | xy-common-params:已捕获(见下方样本) | 24 | xy-common-params:已捕获(见下方样本) |
| 25 | +curl HTTP 200:已用捕获参数成功复现 API 调用 | ||
| 25 | ``` | 26 | ``` |
| 26 | 27 | ||
| 27 | ### 模块布局 | 28 | ### 模块布局 |
| @@ -34,9 +35,9 @@ xy-common-params:已捕获(见下方样本) | @@ -34,9 +35,9 @@ xy-common-params:已捕获(见下方样本) | ||
| 34 | │ ├── framework/lspd.dex # 注入 DEX(182840 字节) | 35 | │ ├── framework/lspd.dex # 注入 DEX(182840 字节) |
| 35 | │ ├── daemon # 启动脚本(已修复入口类名) | 36 | │ ├── daemon # 启动脚本(已修复入口类名) |
| 36 | │ └── service.sh # Magisk 钩子(已去掉不兼容 flag) | 37 | │ └── service.sh # Magisk 钩子(已去掉不兼容 flag) |
| 37 | -├── xhshook/ # Xposed 模块 | 38 | +├── xhshook/ # Xposed 模块(备用 APK,随 Magisk 入库) |
| 38 | │ ├── module.prop | 39 | │ ├── module.prop |
| 39 | -│ └── xhshook.apk # 已更新为 v2(无捆绑 XposedBridge) | 40 | +│ └── xhshook.apk # v2(无捆绑 XposedBridge,classes.dex=3400 字节) |
| 40 | └── xhs_ca/ # MITM 代理 CA 证书 | 41 | └── xhs_ca/ # MITM 代理 CA 证书 |
| 41 | └── system/etc/security/cacerts/36522bbf.0 | 42 | └── system/etc/security/cacerts/36522bbf.0 |
| 42 | ``` | 43 | ``` |
| @@ -44,27 +45,30 @@ xy-common-params:已捕获(见下方样本) | @@ -44,27 +45,30 @@ xy-common-params:已捕获(见下方样本) | ||
| 44 | ### xhshook 配置 | 45 | ### xhshook 配置 |
| 45 | 46 | ||
| 46 | ``` | 47 | ``` |
| 47 | -已安装:com.hermes.xhshook(streamed install,非 incremental) | 48 | +已安装:com.hermes.xhshook(streamed install --no-incremental) |
| 48 | APK 含:assets/xposed_init → com.hermes.xhshook.Hook | 49 | APK 含:assets/xposed_init → com.hermes.xhshook.Hook |
| 49 | -modules_config.db:mid=3, enabled=1, scope=com.xingin.xhs | 50 | +modules_config.db:mid=1, enabled=1, scope=com.xingin.xhs |
| 51 | +APK 路径:/data/app/~~1V3kNj_Xru_4IO7Ixo56Wg==/com.hermes.xhshook-5c7zNdRgh3RtSyoqISuL_A==/base.apk | ||
| 50 | ``` | 52 | ``` |
| 51 | 53 | ||
| 52 | --- | 54 | --- |
| 53 | 55 | ||
| 54 | -## 捕获到的 xy-common-params 样本 | 56 | +## 捕获到的完整 Header 集合 |
| 55 | 57 | ||
| 56 | 打开 XHS 后,用 logcat 实时抓: | 58 | 打开 XHS 后,用 logcat 实时抓: |
| 57 | 59 | ||
| 58 | ```bash | 60 | ```bash |
| 59 | # 在 Termux 里(需要 root) | 61 | # 在 Termux 里(需要 root) |
| 60 | -su -c "logcat -b all | grep -F 'xy-common-params:'" | 62 | +su -c "logcat -b all | grep -E 'xy-common-params:|x-mini-|x-legacy-sid|shield:|xy-platform-info'" |
| 61 | ``` | 63 | ``` |
| 62 | 64 | ||
| 65 | +### xy-common-params(主要签名参数) | ||
| 66 | + | ||
| 63 | 示例值(session 级字段每次启动刷新): | 67 | 示例值(session 级字段每次启动刷新): |
| 64 | 68 | ||
| 65 | ``` | 69 | ``` |
| 66 | fid= | 70 | fid= |
| 67 | -gid=7c9eca1fb5ac54aae84944d1bb4d85a3591f09d9473599ae77728621 | 71 | +gid=7c9ea3f0b4d054aae8494006bb4d85a3591f472947359203774768ef |
| 68 | device_model=phone | 72 | device_model=phone |
| 69 | tz=Asia/Shanghai | 73 | tz=Asia/Shanghai |
| 70 | channel=YingYongBao | 74 | channel=YingYongBao |
| @@ -77,14 +81,33 @@ cpu_abi=arm64-v8a | @@ -77,14 +81,33 @@ cpu_abi=arm64-v8a | ||
| 77 | nqe_score=89 | 81 | nqe_score=89 |
| 78 | project_id=ECFAAF | 82 | project_id=ECFAAF |
| 79 | app_id=ECFAAF01 | 83 | app_id=ECFAAF01 |
| 80 | -id_token=VjEAAN3Pjix... ← 每次启动变 | ||
| 81 | -t=1782724968 ← Unix 时间戳,每次变 | 84 | +id_token=VjEAANwAP8KY... ← 每次启动变 |
| 85 | +t=1782750823 ← Unix 时间戳,每次变 | ||
| 82 | build=9351803 | 86 | build=9351803 |
| 83 | did=058844e5598e4d001b42a122d1a9d1c2 ← 设备固定 | 87 | did=058844e5598e4d001b42a122d1a9d1c2 ← 设备固定 |
| 88 | +launch_id=1782750821 ← 每次启动变 | ||
| 84 | ``` | 89 | ``` |
| 85 | 90 | ||
| 86 | -**固定字段**(可硬编码复现请求):`deviceId`、`did`、`gid`、`platform`、`versionName`、`build` | ||
| 87 | -**Session 字段**(需要 hook 实时拿):`id_token`、`sid`、`t` | 91 | +**固定字段**(可硬编码复现请求):`deviceId`、`did`、`gid`、`platform`、`versionName`、`build`、`channel` |
| 92 | +**Session 字段**(需要 hook 实时拿):`id_token`、`sid`、`t`、`launch_id` | ||
| 93 | + | ||
| 94 | +### 额外签名 Header(2026-06-30 新发现) | ||
| 95 | + | ||
| 96 | +edith 请求还带以下 header,复现 API 时可能需要: | ||
| 97 | + | ||
| 98 | +``` | ||
| 99 | +x-legacy-sid: session.1782715007780944836188 ← 同 sid | ||
| 100 | +x-mini-gid: 7c9ea3f0b4d054aae8494006bb4d85a3591f... ← 同 gid | ||
| 101 | +x-mini-s1: AAsAAAABA8AXUVb7YluNAgap... ← 每次变,base64 | ||
| 102 | +x-mini-sig: de47f603a5d8c1894b08a71008c1c9da... ← 每次变,hex | ||
| 103 | +x-mini-mua: eyJhIjoiRUNGQUFGMDEi... ← JWT 格式,每次变 | ||
| 104 | +xy-direction: 90 | ||
| 105 | +xy-platform-info: platform=android&build=9351803&deviceId=... | ||
| 106 | +xy-scene: fs=1&point=-1 | ||
| 107 | +shield: XYAAQABAAAAAEAAABTAAAAUzUWEe0x... ← 每次变 | ||
| 108 | +User-Agent: Dalvik/2.1.0 (Linux; U; Android 16; Pixel 10 Pro Fold Build/CP1A.260505.005) | ||
| 109 | + Resolution/1080*2364 Version/9.35.1 Build/9351803 | ||
| 110 | +``` | ||
| 88 | 111 | ||
| 89 | --- | 112 | --- |
| 90 | 113 | ||
| @@ -101,7 +124,12 @@ hook 点:okhttp3.Request$Builder.build() | @@ -101,7 +124,12 @@ hook 点:okhttp3.Request$Builder.build() | ||
| 101 | 输出:logcat tag=VectorLegacyBridge | 124 | 输出:logcat tag=VectorLegacyBridge |
| 102 | ``` | 125 | ``` |
| 103 | 126 | ||
| 104 | -### 改 hook 的完整流程(需 Mac 操作) | 127 | +### 改 hook 的完整流程(**必须在 Mac 上执行,设备端无法独立完成**) |
| 128 | + | ||
| 129 | +> ⚠️ **Hermes 不要在设备端跑这段流程。** | ||
| 130 | +> 步骤 2-4 都需要 Mac adb + Mac 上的构建工具。如果只在设备端跑 `pm uninstall` | ||
| 131 | +> 而不走 Mac 端 `update_xhshook_db.sh`,APK 重装后路径变了,lspd 会在下次启动时 | ||
| 132 | +> 因路径失效而崩溃(modules_config.db 里旧路径 → SQLiteCantOpenDatabaseException)。 | ||
| 105 | 133 | ||
| 106 | ```bash | 134 | ```bash |
| 107 | # 1. 编辑 Hook.java | 135 | # 1. 编辑 Hook.java |
| @@ -110,12 +138,12 @@ hook 点:okhttp3.Request$Builder.build() | @@ -110,12 +138,12 @@ hook 点:okhttp3.Request$Builder.build() | ||
| 110 | # 2. 重新编译 + 打包(Mac 上运行) | 138 | # 2. 重新编译 + 打包(Mac 上运行) |
| 111 | bash ~/Documents/LemonAI/pixelphone/xhs_lsposed_a16_fix/rebuild_xhshook.sh | 139 | bash ~/Documents/LemonAI/pixelphone/xhs_lsposed_a16_fix/rebuild_xhshook.sh |
| 112 | 140 | ||
| 113 | -# 3. 推到设备 | 141 | +# 3. 推到设备(Mac adb) |
| 114 | ADB=~/Documents/LemonAI/pixelphone/platform-tools/adb | 142 | ADB=~/Documents/LemonAI/pixelphone/platform-tools/adb |
| 115 | $ADB shell 'pm uninstall com.hermes.xhshook' && \ | 143 | $ADB shell 'pm uninstall com.hermes.xhshook' && \ |
| 116 | $ADB install --no-incremental ~/Documents/LemonAI/pixelphone/xhs_lsposed_a16_fix/xhshook_v2_signed.apk | 144 | $ADB install --no-incremental ~/Documents/LemonAI/pixelphone/xhs_lsposed_a16_fix/xhshook_v2_signed.apk |
| 117 | 145 | ||
| 118 | -# 4. 更新 modules_config.db(脚本自动做) | 146 | +# 4. 更新 modules_config.db(Mac 上运行脚本,通过 adb 操作设备) |
| 119 | bash ~/Documents/LemonAI/pixelphone/xhs_lsposed_a16_fix/update_xhshook_db.sh | 147 | bash ~/Documents/LemonAI/pixelphone/xhs_lsposed_a16_fix/update_xhshook_db.sh |
| 120 | 148 | ||
| 121 | # 5. 杀掉 XHS 进程重启(不需要重启整机!) | 149 | # 5. 杀掉 XHS 进程重启(不需要重启整机!) |
| @@ -126,6 +154,35 @@ $ADB shell 'am force-stop com.xingin.xhs' | @@ -126,6 +154,35 @@ $ADB shell 'am force-stop com.xingin.xhs' | ||
| 126 | $ADB shell 'logcat -d | grep "\[XHSHook\]"' | 154 | $ADB shell 'logcat -d | grep "\[XHSHook\]"' |
| 127 | ``` | 155 | ``` |
| 128 | 156 | ||
| 157 | +### `update_xhshook_db.sh` 的 inode 陷阱(2026-06-30 教训) | ||
| 158 | + | ||
| 159 | +`cp` / `adb push` 替换文件会改变 inode,lspd 的 FileObserver 监听的是旧 inode, | ||
| 160 | +改完后 lspd 内存缓存**不会自动刷新**,GET_BINDER 调用不触发注入。 | ||
| 161 | + | ||
| 162 | +`update_xhshook_db.sh` 已修复为用 Termux Python **原地 UPDATE**(保留 inode), | ||
| 163 | +同时做 `wal_checkpoint(TRUNCATE)` 确保写入主文件。**不需要重启 lspd 或重启整机**。 | ||
| 164 | + | ||
| 165 | +### lspd crash 恢复流程(如果注入彻底失效) | ||
| 166 | + | ||
| 167 | +```bash | ||
| 168 | +# 1. 检查 lspd 日志 | ||
| 169 | +adb shell su -c "tail -50 /data/adb/lspd/log/verbose_$(ls /data/adb/lspd/log/ | tail -1)" | ||
| 170 | + | ||
| 171 | +# 2. 检查 modules_config.db 里的 apk_path 是否还匹配已安装的包 | ||
| 172 | +INSTALLED=$(adb shell pm path com.hermes.xhshook | tr -d '\r' | sed 's/package://') | ||
| 173 | +# 对比 DB 里的路径是否一致 | ||
| 174 | + | ||
| 175 | +# 3. 如果路径不对,用 update_xhshook_db.sh 修复(Mac 端跑) | ||
| 176 | +bash ~/Documents/LemonAI/pixelphone/xhs_lsposed_a16_fix/update_xhshook_db.sh | ||
| 177 | + | ||
| 178 | +# 4. 如果 lspd 进程本身挂了(pidof lspd 无输出),直接重启设备 | ||
| 179 | +adb reboot | ||
| 180 | +# 重启后 Magisk 会通过 service.sh 重新拉起 lspd(unshare -m 方式,无法手动模拟) | ||
| 181 | + | ||
| 182 | +# 5. 重启后需要 PIN 解锁(FBE CE 存储)才能启动 App | ||
| 183 | +# 屏幕上输入 PIN → 解锁后手动点 XHS 图标 | ||
| 184 | +``` | ||
| 185 | + | ||
| 129 | ### 可以加的下一个 hook:CertificatePinner bypass | 186 | ### 可以加的下一个 hook:CertificatePinner bypass |
| 130 | 187 | ||
| 131 | xhs_ca 模块已经把 MITM 代理 CA 证书装进系统了。补上 CertificatePinner bypass 后可以直接用 mitmproxy 抓 OkHttp 流量(edith 仍然走 Cronet,但其他接口会走 OkHttp): | 188 | xhs_ca 模块已经把 MITM 代理 CA 证书装进系统了。补上 CertificatePinner bypass 后可以直接用 mitmproxy 抓 OkHttp 流量(edith 仍然走 Cronet,但其他接口会走 OkHttp): |
| @@ -153,7 +210,7 @@ try { | @@ -153,7 +210,7 @@ try { | ||
| 153 | 210 | ||
| 154 | ## 下一步可以做的事(Hermes 接手) | 211 | ## 下一步可以做的事(Hermes 接手) |
| 155 | 212 | ||
| 156 | -### A. 用捕获到的参数复现 XHS API 请求 | 213 | +### A. 用捕获到的参数复现 XHS API 请求 ✅ curl HTTP 200 已验证 |
| 157 | 214 | ||
| 158 | `xy-common-params` 里的固定字段可以直接复用,session 字段需要先打开 XHS 触发 hook 实时拿。 | 215 | `xy-common-params` 里的固定字段可以直接复用,session 字段需要先打开 XHS 触发 hook 实时拿。 |
| 159 | 216 | ||
| @@ -164,27 +221,31 @@ su -c "logcat -c && am force-stop com.xingin.xhs" | @@ -164,27 +221,31 @@ su -c "logcat -c && am force-stop com.xingin.xhs" | ||
| 164 | su -c "logcat -d | grep 'xy-common-params:' | head -1" | 221 | su -c "logcat -d | grep 'xy-common-params:' | head -1" |
| 165 | ``` | 222 | ``` |
| 166 | 223 | ||
| 167 | -拿到后,用 curl 复现请求: | 224 | +拿到后,用 curl 复现请求(已验证 HTTP 200): |
| 168 | 225 | ||
| 169 | ```bash | 226 | ```bash |
| 170 | -XY_PARAMS="fid=&gid=7c9eca...(完整值)" | 227 | +XY_PARAMS="fid=&gid=7c9ea3f0b4d054...(完整值)" |
| 171 | curl -H "xy-common-params: $XY_PARAMS" \ | 228 | curl -H "xy-common-params: $XY_PARAMS" \ |
| 172 | - "https://edith.xiaohongshu.com/api/sns/v1/homefeed?..." | 229 | + -H "xy-direction: 90" \ |
| 230 | + -H "User-Agent: Dalvik/2.1.0 (Linux; U; Android 16; Pixel 10 Pro Fold Build/CP1A.260505.005) Resolution/1080*2364 Version/9.35.1 Build/9351803 Device/(Google;Pixel 10 Pro Fold) discover/9.35.1 NetType/WiFi" \ | ||
| 231 | + "https://edith.xiaohongshu.com/api/sns/v3/system_service/flag_exp?fetchSceneTag=&deviceLevel=8" | ||
| 173 | ``` | 232 | ``` |
| 174 | 233 | ||
| 175 | -### B. Hook 更多字段(如果 curl 复现失败) | 234 | +### B. 研究 x-mini-sig / shield 签名结构 |
| 176 | 235 | ||
| 177 | -edith 除 `xy-common-params` 外可能还检查其他 header(如 `xy-sign`、cookie)。修改 xhshook 打印所有 edith 请求的全部 header,观察缺什么。 | 236 | +edith 除 `xy-common-params` 外还带 `x-mini-sig`(hex)、`x-mini-mua`(JWT)、`shield`(自定义 base64)。 |
| 237 | +这些字段每次启动都变——研究是否由设备固定字段派生,还是需要服务端签名。 | ||
| 178 | 238 | ||
| 179 | -Hook.java 里已经打印了 `Headers.toString()` 的完整内容——重新抓一次 logcat 即可看到所有 header(logcat 多行输出,每个 header 一行)。 | 239 | +Hook.java 里已经打印了 `Headers.toString()` 的完整内容——重新抓一次 logcat 即可看到所有 header: |
| 180 | 240 | ||
| 181 | ```bash | 241 | ```bash |
| 182 | -su -c "logcat -d -b all | grep 'VectorLegacyBridge' | grep -v '\[XHSHook\]'" | head -30 | 242 | +su -c "logcat -d -b all | grep 'VectorLegacyBridge'" | grep -v '\[XHSHook\]' | head -30 |
| 183 | ``` | 243 | ``` |
| 184 | 244 | ||
| 185 | -### C. 修改 xhshook 做实时转发(高级) | 245 | +### C. 修改 xhshook 做实时转发(高级,需要 Mac 改 Hook.java) |
| 186 | 246 | ||
| 187 | -改 hook 在 `beforeHookedMethod` 里把参数通过 HTTP POST 转到 Hermes 的本地 server(如 `localhost:8765`),让 Hermes 实时处理每条请求。 | 247 | +改 hook 在 `beforeHookedMethod` 里把完整 header 通过 HTTP POST 转到 Hermes 的本地 server |
| 248 | +(如 `localhost:8765`),让 Hermes 实时处理每条请求的签名参数。 | ||
| 188 | 249 | ||
| 189 | --- | 250 | --- |
| 190 | 251 | ||
| @@ -199,7 +260,7 @@ su -c "logcat -d -b all | grep 'VectorLegacyBridge' | grep -v '\[XHSHook\]'" | h | @@ -199,7 +260,7 @@ su -c "logcat -d -b all | grep 'VectorLegacyBridge' | grep -v '\[XHSHook\]'" | h | ||
| 199 | ├── ipc_bridge.cpp ← 已打补丁的源文件 | 260 | ├── ipc_bridge.cpp ← 已打补丁的源文件 |
| 200 | ├── xhshook_src/ | 261 | ├── xhshook_src/ |
| 201 | │ └── Hook.java ← xhshook v2 源码 | 262 | │ └── Hook.java ← xhshook v2 源码 |
| 202 | -└── xhshook_v2_signed.apk ← 预构建的 APK(当前已安装版本) | 263 | +└── xhshook_v2_signed.apk ← 预构建的 APK(当前已安装版本,classes.dex=3400 字节) |
| 203 | ``` | 264 | ``` |
| 204 | 265 | ||
| 205 | --- | 266 | --- |
| @@ -211,3 +272,5 @@ su -c "logcat -d -b all | grep 'VectorLegacyBridge' | grep -v '\[XHSHook\]'" | h | @@ -211,3 +272,5 @@ su -c "logcat -d -b all | grep 'VectorLegacyBridge' | grep -v '\[XHSHook\]'" | h | ||
| 211 | - **常驻 Frida daemon 注入 XHS**:XHS 检测到反调试后崩溃(wechat_plain 里有记录,XHS 同理)。 | 272 | - **常驻 Frida daemon 注入 XHS**:XHS 检测到反调试后崩溃(wechat_plain 里有记录,XHS 同理)。 |
| 212 | - **把 Xposed API 类打进 xhshook DEX**:LSPosed 会检查 `XposedBridge.class.getClassLoader() == initLoader`,打进去的话直接 `Cannot load module`。必须用 `compileOnly`。 | 273 | - **把 Xposed API 类打进 xhshook DEX**:LSPosed 会检查 `XposedBridge.class.getClassLoader() == initLoader`,打进去的话直接 `Cannot load module`。必须用 `compileOnly`。 |
| 213 | - **incremental install(`adb install` 默认)**:Incremental Install 的 marker 会让 `java.util.zip.ZipFile` 解析失败,LSPosed 找不到 `assets/xposed_init`。必须用 `adb install --no-incremental`。 | 274 | - **incremental install(`adb install` 默认)**:Incremental Install 的 marker 会让 `java.util.zip.ZipFile` 解析失败,LSPosed 找不到 `assets/xposed_init`。必须用 `adb install --no-incremental`。 |
| 275 | +- **adb push 替换 modules_config.db**:改变文件 inode,lspd FileObserver 监听旧 inode,缓存不刷新,注入会静默失败(有 GET_BINDER 但无 "Loading Vector" 日志)。必须用 Termux Python 原地 UPDATE。 | ||
| 276 | +- **kill lspd 后手动重启**:lspd 是 init 直接子进程,由 Magisk `service.sh` 用 `unshare -m` 拉起,手动 `app_process` 启动缺少必要的 mount namespace,拉不起来。唯一办法是 `adb reboot`。 |
xhs_lsposed_a16_fix/update_xhshook_db.sh
| @@ -12,6 +12,16 @@ echo "New APK path: $NEW_PATH" | @@ -12,6 +12,16 @@ echo "New APK path: $NEW_PATH" | ||
| 12 | $ADB shell 'su -c "cp /data/adb/lspd/config/modules_config.db /data/local/tmp/mc_upd.db && chmod 644 /data/local/tmp/mc_upd.db"' | 12 | $ADB shell 'su -c "cp /data/adb/lspd/config/modules_config.db /data/local/tmp/mc_upd.db && chmod 644 /data/local/tmp/mc_upd.db"' |
| 13 | $ADB pull /data/local/tmp/mc_upd.db /tmp/mc_upd.db | 13 | $ADB pull /data/local/tmp/mc_upd.db /tmp/mc_upd.db |
| 14 | sqlite3 /tmp/mc_upd.db "UPDATE modules SET apk_path='${NEW_PATH}' WHERE module_pkg_name='com.hermes.xhshook';" | 14 | sqlite3 /tmp/mc_upd.db "UPDATE modules SET apk_path='${NEW_PATH}' WHERE module_pkg_name='com.hermes.xhshook';" |
| 15 | -$ADB push /tmp/mc_upd.db /data/local/tmp/mc_upd.db | ||
| 16 | -$ADB shell 'su -c "cp /data/local/tmp/mc_upd.db /data/adb/lspd/config/modules_config.db && rm -f /data/adb/lspd/config/modules_config.db-wal /data/adb/lspd/config/modules_config.db-shm && echo done"' | ||
| 17 | -echo "DB updated. Now: am force-stop com.xingin.xhs → open XHS manually." | 15 | +# Use Python in-place UPDATE to preserve inode → triggers lspd FileObserver. |
| 16 | +# (adb push / cp replaces the file, changing inode, which FileObserver misses.) | ||
| 17 | +TERMUX_PY=/data/data/com.termux/files/usr/bin/python3 | ||
| 18 | +$ADB shell "su -c \"$TERMUX_PY -c \\\" | ||
| 19 | +import sqlite3 | ||
| 20 | +db = sqlite3.connect('/data/adb/lspd/config/modules_config.db') | ||
| 21 | +db.execute(\\\\\\\"UPDATE modules SET apk_path='${NEW_PATH}' WHERE module_pkg_name='com.hermes.xhshook'\\\\\\\") | ||
| 22 | +db.execute('PRAGMA wal_checkpoint(TRUNCATE)') | ||
| 23 | +db.commit() | ||
| 24 | +db.close() | ||
| 25 | +print('done') | ||
| 26 | +\\\"\"" 2>&1 | ||
| 27 | +echo "DB updated in-place. Now: am force-stop com.xingin.xhs → open XHS manually." |