# Feature Authorization System — 功能授權體系完整解碼

> 靜態重構（jadx + native 符號）。授權算法分佈：**驗證邏輯 Java 側，hash 算法 native 側（`HDscClassIf.hash_*`）**。

## 1. 總覽：三種探頭硬件，三種授權存儲

| 探頭類 | 硬件 | 授權存儲 | 驗證方式 |
|---|---|---|---|
| `HSUsbProbe`（S 系列 USB） | Cypress USB | **EEPROM** 地址表 | `hash(SN) == EEPROM 授權碼` |
| `HRUsbProbe`（R 系列 RGB 機） | RGB 接口 + SD | **SD 卡 block 2-12** | `hash(SN) == SD 授權碼` |
| `HRTLUsbProbe`（Realtek 系） | Realtek | **寄存器**（`ProbeReg(4)` 單 byte） | bitmask 直讀 |
| `HUsbProbe`（基類）/ `HSUsbProbeCh16` | — | — | **VerifyAuth() 硬編碼 `return true`** |

## 2. 授權算法（HRUsbProbe / HSUsbProbe 通用）

授權碼 = **對探頭 SN 字符串計算 hash**（native `libdoppler` 內實現）：

| 功能 | hash | 存儲位置（R: SD block / S: EEPROM addr） |
|---|---|---|
| B 模式 | `DJBHash` | block 6 / EEPROM 28,288 |
| Color | `BKDRHash` | block 4 / EEPROM 28,256 |
| PW 多普勒 | `FNVHash` | block 3 / EEPROM 28,240 |
| DICOM | `BPHash` | block 2 / EEPROM 28,224 |
| 人/獸醫切換 | `JSHash` | block 8 / EEPROM 28,308 |
| **使用時間/計次** | `DEKHash` | block 12（隨機數+計數器） |

全部係經典公開 hash 算法（DJB2/BKDR/FNV-1/BP/JS 均為標準教科書算法）。SN 格式：`"<probeSN>-<SD/EEPROM SN hex>-<useTimeRandom hex>"`。

## 3. 關鍵漏洞/後門（靜態證據）

### 3.1 SN 清零自動全授權（HRUsbProbe.VerifyAuth）

```java
boolean z = b == 0 && bArr3[1] == 0;   // SN 頭兩字節為 0 = 未初始化
int iReadAuthCode = ReadAuthCode(4);   // Color 授權碼
if (iReadAuthCode == 0 && z) {
    WriteAuthCode(4, iHash_BKDRHash_forColor2);  // ← 自動寫入正確授權碼!
}
```
Color/DICOM/PW 三項都有同樣邏輯：**授權位為 0 且 SN 未初始化 → 自動寫入 hash(SN) 全功能授權**。（推測：出廠自檢/新 SN 燒錄流程，但可被利用——清 SN 頭 2 字節 + 清授權位 = 全解鎖）

### 3.2 VerifyAuth 硬編碼 true

- `HUsbProbe.VerifyAuth()`（基類）：`return true`
- `HSUsbProbeCh16.VerifyAuth()`：`return true`（ch16 型號完全無 SN 認證）
- 但功能位仍由 EEPROM hash 驗證（`HSUsbProbe.VerifyAuth` 內 680-706 行）——ch16 跳過嘅係 SN 格式檢查，唔係功能位

### 3.3 萬能 OEM ID = 255

```java
public Boolean GetOEMAuth(int probeOemId) {
    if (probeOemId != 255) { ... if (probeOemId != appOemId) return false; return true; }
    return true;   // ← 255 對任何 App 一律通過
}
```
另有 `IsCheckOEMID(appOemId)` 開關：App 側可配置完全跳過 OEM 驗證（此時 appOemId 視為 1）。

### 3.4 授權寫入通道公開

- vendor request `VR_USB_SET_AUTH=24`：`WriteAuthCode()` 明文寫入，無簽名無加密
- `WriteEEprom(81, addr, code, 4)`：S 系列寫通道
- `WriteSD(block, ...)`：R 系列寫通道
- 31-byte bulk 命令格式已解碼：`{GET_EEPROM_REG3, 'S','B','C', 24,24,24,24, len32, 0x80,0,10,40,0, addr32, 0, len16, 0...}`

## 4. 隱藏功能清單

| 功能 | 證據 | 狀態 |
|---|---|---|
| **使用時間/計次授權**（租賃模式） | `Readrandomandnum(12)`、`SetUseTimeNum`、`hash_DEKHash_forUseTime`；Ultrasys.mUseTimeAuthCode | 檢查點在 native（Java 層只有 set/get） |
| **獸醫等級 0-6** | `ReadVetId` → `bArr[0]-48`（ASCII '0'-'6'）→ `SetVet(i)` + WLAN msg 100；RTL 用寄存器 bit3-5 | 7 級獸醫模式 |
| **NoExpand（影像擴展鎖）** | RTL `mNoExpand = (b & 128)>>7` + WLAN msg -95 | 硬件位 |
| **FPGA 數據寬度 8/16 bit** | `SendMsg 16/17 → SetDataWidth(8/16)` | RGB 機型 |
| **FPGA 電源/配置控制** | `SendMsg 18-21 → SetFPGANConfig/CheckFPGANStatus/CheckFPGANConfigDone/SetFPGAPower` | RGB 機型 |
| **RF 原始數據採集** | `mRFGather` → 讀 2,097,152 B 原始 RF | 工程/研究模式 |
| **多主機模式** | `WlanProbe.GetMultiHost() == 2` | 一探頭多設備（教學?） |
| **FPGA 現場升級** | 外部 `FPGA_ch16_5.rbf` 覆蓋 assets 版 + byteswap | 升級通道 |
| **模擬模式** | `IsSUsbSimOpen()` → ramp 假數據 | 無探頭演示 |
| **第三方 App 集成** | `ThirdPartyManageActivity`（exported）+ returnThirdParty | SDK 模式 |
| **DICOM 獨立授權更新** | `UpdateDicomAuth()` 經 USB | 售後 DICOM 開通 |

## 5. 安全評估

- **保護強度**：授權碼演算法為公開經典 hash + SN 明文 → 可完全離線計算。真正的防護只係「物理訪問探頭存儲」嘅門檻
- **無簽名、無非對稱加密、無挑戰應答** → 無防重放、無防偽造
- **UseTime 計時授權**若在 native 檢查，需進一步動態驗證（Frida hook `SetUseTimeAuthCode` 後觀察 native 行為）
- 商業影響：EEPROM/SD 讀寫器 + SN 讀取 → 全功能解鎖；OEM ID 255 或關閉 IsCheckOEMID → 跨品牌通用
