場景
ActiveX 控制項 (DLL,寄宿於瀏覽器) 需呼叫 `CreateFile(\\.\PhysicalDrive0, ...)` 讀取硬碟序號。EXE 可用「以管理員身分執行」或 Manifest `requireAdministrator` 解決,但 DLL 無法直接提權。
核心衝突
- UAC 機制:標準用戶無權開啟實體磁碟 (`GENERIC_READ` on `\\.\PhysicalDriveX`)。需要 `SeManageVolumePrivilege` / 管理員 Token。
- ActiveX 安全模型:瀏覽器以**中等/低完整性層級**啟動,載入的 ActiveX 繼承此權限,**無法自行提權**。
- 殺毒軟體攔截**:嘗試繞過 UAC (如 `AdjustTokenPrivileges`、DLL 注入、COM 昇高) 會被視為惡意行為攔截。
錯誤嘗試
- DLL 內呼叫 `AdjustTokenPrivileges` → 失敗,無 `SE_TCB_NAME`/`SE_ASSIGNPRIMARYTOKEN_NAME` 權限。
- Manifest `requireAdministrator` → 僅對 EXE 有效,DLL 載入進程 Token 已定型。
- COM Elevation Moniker (`CoCreateInstance` with `CLSCTX_LOCAL_SERVER`) → 需註冊獨立 Out-of-process COM Server,複雜且仍受 UAC 彈窗確認。
正確架構方案
方案一:分離高權限服務 (標準模式)
- 開發 **Windows Service (本地系統帳戶運行)** 或 **Out-of-process COM LocalServer (註冊 `LocalServer32`、啟用 `RunAs` = `Interactive User` 或 `Administrator`)**。
- Service/COM Server 提供 `GetDiskSerialNumber()` 介面。
- ActiveX (低權限) 透過 **IPC (Named Pipe / RPC / COM / HTTP localhost)** 呼叫高權限服務取得序號。
- **優點**:權限隔離清晰、安全、符合最小權限原則、可被企業群組策略部署管理。
方案二:讀取邏輯磁碟而非實體磁碟 (若業務允許)
- `CreateFile(_T("\\\\.\\C:"), ...)` 讀取邏輯卷通常**不需要管理員權限** (需 `FILE_SHARE_READ|WRITE`)。
- 用 `GetVolumeInformation(_T("C:\\"), ...)` 直接取得序號,**完全不需要 CreateFile**,標準用戶即可調用。
方案三:企業環境群組策略部署 (針對 ActiveX)
- 將 ActiveX 簽名、加入**受信任站點**、**降低安全性等級**、**啟用「未標記為安全的 ActiveX 初始化並指令碼執行」**。
- 透過 **Group Policy** 強制安裝、設定 `HKLM\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\2` 相關鍵值。
- **前提**:企業內網環境、IT 管控、使用者接受彈窗確認。
銀行/騰訊/QQ 插件的做法
**彈出提示框要求使用者「以管理員身分執行瀏覽器」或「允許 UAC 彈窗」**,實際上是引導使用者手動提權瀏覽器進程,使載入的 ActiveX 繼承高權限 Token。**這是安全規範內唯一可行的互動方式**——**不破壞 UAC,引導用戶授權**。
結論
**DLL/ActiveX 無法自行提權存取實體磁碟。** 正確路徑:
1. **業務允許時,改用 `GetVolumeInformation` 讀取邏輯卷序號 (無需高權限)。**
2. **必須讀取實體磁碟,架構分離:低權限 ActiveX + 高權限 Windows Service/COM Server (IPC 通訊)。**
3. **企業環境:Group Policy 部署簽名 ActiveX + 引導用戶 UAC 授權。**
**切勿嘗試在 DLL 內破解 UAC**,違反安全模型、被殺毒攔截、法律風險。