947177386 发表于 2026-9-11 09:43

【逆向破解】星愿车机助手3.4.6 激活验证绕过完整教程

本帖最后由 947177386 于 2026-9-12 00:09 编辑



> 本文仅用于学习和研究目的,请勿用于商业用途。

## 一、前言

星愿车机助手是一款 Android 车机桌面应用,包含应用商店、文件管理、桌面美化、视频壁纸等功能。应用采用激活码验证机制,未激活时部分功能受限。

本文记录了从逆向分析到最终破解的完整过程,包括成功的补丁方案、失败的尝试(签名问题、域名修改失败等),以及无法解决的问题。

欢迎各位大神有兴趣可以尝试,本次只测试了3.4.6版本,去除了更新检测,3.6版本暂时没试,有兴趣的大佬可以看看,目前依然有部分功能会二次校验,即使去除了好像也没办法用



## 二、工具准备

| 工具                  | 用途               | 备注                              |
| ------------------- | ---------------- | ------------------------------- |
| androguard (Python) | DEX 反汇编与字节码分析    | `pip install androguard`      |
| Python 3.x          | 编写补丁脚本         | 标准库 struct/zlib/hashlib/zipfile |
| MT管理器               | APK 签名(v1+v2+v3) | **必须用MT签名,不要用Python手写V2签名**   |
| JADX(可选)            | Java 反编译查看逻辑   | 辅助理解代码结构                        |

## 三、逆向分析过程

### 3.1 APK 结构分析

APK 包含多个 DEX 文件:

- `classes.dex` — 主逻辑,包含激活验证、导航守卫、应用商店 Fragment

- `classes5.dex` — 辅助逻辑,包含更新检测、音乐方向盘凭证、Endpoint 定义

### 3.2 定位关键类和方法

通过关键词搜索,定位到以下关键类:

```
classes.dex:
Lcom/yunpan/appmanage/ui/AppStoreAuthRevoke;→ isLicensed()    授权检查
Lcom/yunpan/appmanage/ui/AppStoreTabGuard;   → allowTab()      导航守卫
Lcom/yunpan/appmanage/ui/FragmentAppStore;   → k()             商店页面初始化
Lcom/yunpan/appmanage/ui/AppStorePrefs;       → getCookie()   凭证读取
Lcom/yunpan/appmanage/ui/EndpointProvider;    → rootUrl() 等    服务器地址

classes5.dex:
Lcom/yunpan/appmanage/ui/StartupUpdateCheck;       → run()      更新检测
Lcom/yunpan/appmanage/ui/MusicWheelCredentials;   → normalizeStoreDeviceId()设备ID处理
Lcom/yunpan/appmanage/ui/MusicWheelEndpoint;       → issueUrl() 插件签发地址
```

### 3.3 分析加密字符串

服务器地址使用 **Base64 + XOR(key=90)** 加密存储在 DEX 字符串表中。

解密算法:

```python
import base64

XOR_KEY = 90

def decode(s):
    raw = base64.b64decode(s)
    return bytes().decode('utf-8')
```

解密结果:

- 段1(8字符):`https://`

- 段2(9字符):`appstore.`

- 段3(10字符):`wlkj666.cn`

- 拼接后:`https://appstore.wlkj666.cn`

接口列表:

| 接口          | 地址                                                         | 用途   |
| ----------- | ---------------------------------------------------------- | ------ |
| indexUrl    | `https://appstore.wlkj666.cn/index.php`                  | 应用商店列表 |
| noticeUrl   | `https://appstore.wlkj666.cn/wl.json`                      | 公告   |
| updateCheck | `https://appstore.wlkj666.cn/admin/update_check.php`       | 更新检测   |
| issueUrl    | `https://appstore.wlkj666.cn/api/v1/music-wheel/issue.php` | 插件签发   |

### 3.4 激活验证流程

```
APP启动
→ FragmentAppStore.k()
    → 检查 isLicensed()
      → true: 显示应用列表
      → false: 显示激活码输入框
    → AppStoreTabGuard.allowTab()
      → true: 允许切换导航
      → false: 弹出"请先激活"提示
```

## 四、破解补丁详解

### 补丁1:isLicensed() → 返回 true

**文件:** classes.dex
**类:** `Lcom/yunpan/appmanage/ui/AppStoreAuthRevoke;`
**方法:** `isLicensed()`

原始逻辑:调用服务器验证激活状态,返回 boolean。

补丁字节码:

```
12 10    const/4 v0, 1       ; v0 = true
0f 00    return v0         ; 返回 true
```

用 nop 填充剩余空间(原始 insns 长度 - 2)。

### 补丁2:allowTab() → 返回 true

**文件:** classes.dex
**类:** `Lcom/yunpan/appmanage/ui/AppStoreTabGuard;`
**方法:** `allowTab()`

原始逻辑:检查 isLicensed(),未激活时返回 false,导航按钮点击弹出"请先激活"提示。

补丁:只改第一条指令为 `const/4 v0, 1`,第二条保持 `return v0`。

### 补丁3:FragmentAppStore.k() → return-void

**文件:** classes.dex
**类:** `Lcom/yunpan/appmanage/ui/FragmentAppStore;`(继承自 `Le7/h`)
**方法:** `k()`

原始逻辑:初始化商店页面,发网络请求拉取应用列表,未激活时显示激活码输入框。

补丁:直接 `return-void`(`0E 00`),跳过所有初始化逻辑。

**效果:** 应用商店页面显示空白,不显示激活码输入框,不发网络请求,不闪退。

### 补丁4:StartupUpdateCheck.run() → return-void

**文件:** classes5.dex
**类:** `Lcom/yunpan/appmanage/ui/StartupUpdateCheck;`
**方法:** `run()`

原始逻辑:启动时检查服务器是否有新版本,弹更新提示。

补丁:直接 `return-void`。

### 补丁5(可选):getCookie() → 返回非空

**文件:** classes.dex
**类:** `Lcom/yunpan/appmanage/ui/AppStorePrefs;`
**方法:** `getCookie()`

原始逻辑:返回存储的 Cookie 字符串,未激活时返回空字符串。

补丁:将 `const-string ""` 改为 `const-string "user_uuid="`(引用 DEX 中已存在的同字符串 ID)。

### 补丁6(可选):normalizeStoreDeviceId() → 直接返回

**文件:** classes5.dex
**类:** `Lcom/yunpan/appmanage/ui/MusicWheelCredentials;`
**方法:** `normalizeStoreDeviceId()`

原始逻辑:从 Cookie 中提取 user\_uuid,用于后续服务器验证。

补丁:`return-object v8`(`11 08`),直接返回输入参数,跳过提取逻辑。

## 五、DEX 校验和修复

**每次修改 DEX 字节后必须修复校验和,否则 ART 拒绝加载:**

```python
import struct, zlib, hashlib

def fix_dex(data):
    d = bytearray(data)
    # SHA1 签名 (offset 0x0C, 长度20, 覆盖0x20之后所有数据)
    d = hashlib.sha1(bytes(d)).digest()
    # Adler32 校验和 (offset 0x08, 长度4, 覆盖0x0C之后所有数据)
    d = struct.pack('<I', zlib.adler32(bytes(d)) & 0xFFFFFFFF)
    return bytes(d)
```

## 六、签名问题(重大教训)

### 尝试过的方案(全部失败)

1. **Python cryptography 库手写 V1 签名** — APK 可安装但部分模拟器拒绝
2. **Python 手写 V2 签名块** — 尝试了十几个版本,全部"解析失败"
3. **V2 签名块格式问题** — pair\_size/pair\_id 偏移计算、digest 结构、content digest 计算……每一个都容易出错

### 最终方案

**生成未签名 APK,用 MT 管理器做 v1+v2+v3 签名。**

```python
# 构建未签名APK — 去掉所有签名文件,保留其他META-INF
SIG_EXT = ('.SF', '.RSA', '.DSA', 'MANIFEST.MF')

with zipfile.ZipFile(original, 'r') as zin:
    with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED) as zout:
      for info in zin.infolist():
            if info.filename.startswith('META-INF/'):
                if info.filename.endswith(SIG_EXT):
                  continue
            data = zin.read(info.filename)
            if info.filename == 'classes.dex':
                data = dex1_final
            elif info.filename == 'classes5.dex':
                data = dex5_final
            zout.writestr(info.filename, data, compress_type=info.compress_type)
```

然后用 MT 管理器打开未签名 APK → 签名 → 选择 v1+v2+v3 → 保存。

## 七、域名修改的尝试与失败

### 目标

将 APK 中的服务器地址从 `https://appstore.wlkj666.cn` 改为自己的服务器,实现自定义应用商店。

### 尝试过程

将加密字符串分三段处理(等长替换):

| 段| 原始         | 替换为      | 长度 | 结果       |
| -- | ------------ | ---------- | -- | -------- |
| 段1 | `https://`   | `http://x` | 8| **可以打开** |
| 段2 | `appstore.`| `你的IP前9`   | 9| **闪退**   |
| 段3 | `wlkj666.cn` | `字符后10位`   | 10 | **闪退**   |

### 单独测试

| 测试                | 改了什么                  | 结果       |
| ----------------- | ----------------------- | -------- |
| 只改段1            | `https://` → `http://x` | **正常打开** |
| 只改段2            | `appstore.` → 自定义       | **闪退**   |
| 只改段3            | `wlkj666.cn` → 自定义      | **闪退**   |
| 改 classes.dex 段2| 同上                      | **闪退**   |
| 改 classes5.dex 段2 | 同上                      | **闪退**   |

### 结论

- 段1(协议前缀 `https://`)可以安全修改

- 段2(`appstore.`)和段3(`wlkj666.cn`)**修改后必定闪退**

- 原因推测:这些加密字符串可能被 JNI 层校验,或被多处引用做完整性检查

- **无法通过修改 DEX 字符串来更换服务器地址**

### 替代方案:hosts + nginx 反向代理

不改 APK 域名,而是:

1. 在车机/模拟器上改 hosts:`你的服务器IP appstore.wlkj666.cn`
2. 服务器上用 nginx 反向代理到 Python 服务端

nginx 配置:

```nginx
server {
    listen 80;
    server_name appstore.wlkj666.cn;
    location / {
      proxy_pass http://127.0.0.1:你的端口;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
    }
}
```

缺点:需要用户手动改 hosts。

## 八、难度评估

| 模块      | 难度    | 说明                           |
| --------- | ----- | ------------------------------ |
| DEX 字节码补丁 | ★★☆☆☆ | 标准的 smali 补丁流程,偏移计算需注意         |
| DEX 校验和修复 | ★☆☆☆☆ | 标准算法,SHA1 + Adler32            |
| 加密字符串分析   | ★★★☆☆ | 需要识别 Base64+XOR 加密,找到密钥      |
| APK 签名    | ★★★★★ | **最大坑**,Python 手写 V2 签名几乎不可能成功 |
| 域名替换      | ★★★★☆ | 段2段3无法修改,推测有 JNI 校验            |
| 自定义服务端    | ★★☆☆☆ | Python HTTP 服务端 + nginx 反代   |
| 闪退排查      | ★★★☆☆ | 需要逐个补丁排除,耗时                  |

**整体难度:★★★☆☆(中等)**

核心补丁不难,但签名和域名修改是两大坑。

## 九、无法解决的问题

### 1. 服务器端验证(无法绕过)

| 功能          | 状态   | 原因                  |
| ----------- | ------ | --------------------- |
| 桌面透明化(插件下载) | ❌ 无法破解 | 服务器返回 HTTP 403,验证激活状态 |
| 应用商店右侧应用列表| ❌ 无法破解 | 服务器返回空数据            |
| 需要联网下载的功能   | ❌ 无法破解 | 服务器端验证激活状态            |

**本地补丁可以绕过所有本地检查,但服务器端的验证无法绕过。**

### 2. 域名替换(无法通过修改DEX实现)

段2(`appstore.`)和段3(`wlkj666.cn`)修改后必定闪退,推测有 JNI 层校验。只能通过 hosts 方案替代。

### 3. V2/V3 签名(无法用Python实现)

Python 手写 V2 签名块尝试了十几个版本全部失败。必须使用 MT 管理器签名。

## 十、最终成果

### 成功破解的功能

| # | 功能      | 状态                     |
| - | --------- | ---------------------- |
| 1 | 导航按钮自由切换| ✅ 不再弹出"请先激活"提示         |
| 2 | 激活码输入框    | ✅ 已隐藏(k() return-void) |
| 3 | 软件更新检测    | ✅ 已禁用                  |
| 4 | 本地授权检查    | ✅ isLicensed() 返回 true |
| 5 | 功能面板/文件管理 | ✅ 可正常使用                |
| 6 | 应用商店左侧分类| ✅ 可显示(服务器返回分类数据)       |

### 无法破解的功能

| # | 功能         | 原因         |
| - | ---------- | ---------- |
| 1 | 桌面透明化插件下载| 服务器返回 403|
| 2 | 应用商店右侧应用列表 | 服务器返回空   |
| 3 | 需要服务器验证的功能 | 服务器端校验激活状态 |

## 十一、总结

### 补丁清单(最终版)

| # | 文件         | 类/方法                            | 补丁            | 字节码                   |
| - | ------------ | ------------------------------- | ------------- | --------------------- |
| 1 | classes.dex| AppStoreAuthRevoke.isLicensed() | → true      | `12 10 0F 00` + nop填充 |
| 2 | classes.dex| AppStoreTabGuard.allowTab()   | → true      | `12 10 0F 00`(改第1条指令) |
| 3 | classes.dex| FragmentAppStore.k()            | → return-void | `0E 00` + nop填充       |
| 4 | classes5.dex | StartupUpdateCheck.run()      | → return-void | `0E 00` + nop填充       |

### 关键经验

1. **签名用 MT 管理器**,不要尝试 Python 手写 V2/V3 签名
2. **DEX 字符串不要随便改**,特别是域名相关的加密字符串
3. **优先用简单补丁**(return-void、const/4),复杂字节码容易出问题
4. **逐个补丁测试**,先确认每个补丁单独不闪退再组合
5. **本地验证可以绕过,服务器端验证无法绕过**

### 使用方法

1. 运行 Python 脚本生成未签名 APK
2. 用 MT 管理器打开 → 功能 → 签名 → 选择 v1+v2+v3
3. 安装到车机/模拟器

***

> 本文仅供学习交流

原始版本和修复版本下载

撞死算了 发表于 2026-9-11 23:28

你可以研究研究公签一下就行,透明插件FlymeSystemUIPlugin_flyme,Launcher3,恢复透明状态栏插件是GeelyAutoLauncher-restore,Launcher3是主要的插件,白名单,胎压监测,透明状态栏都靠这个插件

xixicoco 发表于 2026-9-11 15:15

原始版本和修复版本下载??没有下载?

mokjf 发表于 2026-9-11 15:31

没有下载?楼主可以提供一下吗?

fatr 发表于 2026-9-11 15:36

链接没有出来哦,记得补一下

天天哈皮 发表于 2026-9-11 15:37

这个app怎么和应用管家那么像

cao_jf 发表于 2026-9-11 15:45

天天哈皮 发表于 2026-9-11 15:37
这个app怎么和应用管家那么像

这就是应用管家吧,我车上安装的应用管家没听说有激活一说呀{:1_925:}

cuichenhui 发表于 2026-9-11 16:36

应用管家是个免费软件,这些人把应用管家魔改一下,加个商城就收钱

CurysMC 发表于 2026-9-11 16:57

cuichenhui 发表于 2026-9-11 16:36
应用管家是个免费软件,这些人把应用管家魔改一下,加个商城就收钱

嗯嗯,上个壳就卖钱,还有更恶心的,一个字不改,拿人家开源项目卖钱。

名将 发表于 2026-9-11 17:04

没有链接啊。

GDExecW 发表于 2026-9-11 17:39

这种居然没有加固
页: [1] 2
查看完整版本: 【逆向破解】星愿车机助手3.4.6 激活验证绕过完整教程