前言¶
接手一個 LabVIEW 項目時常見一種情況:前面板能打開,框圖卻提示需要密碼。傳統解法是裝幾 GB 的 NI 運行時,或者改用 pylabview、第三方解密腳本,前者笨重,後者依賴 Python 和特定版本環境。
下面介紹的 dsh-labview 是社區插件,它用一個無依賴的 JavaScript 引擎直接解析 LabVIEW 文件的 RSRC 容器,在字節層面把密碼記錄抹掉,不需要 LabVIEW、不需要 Python、不需要聯網。
這是什麼¶
dsh-labview 由維護者 yxfvvv 開發並託管在 yxfvvv/dsh-labview,許可證爲 MIT,分類爲 admin-security。它處理的問題很具體:把 *.vi、*.ctl、*.vit、*.ctt(以及配置擴展名中的 .xctl)文件裏被鎖定的框圖解除保護,原地修補少量字節。
先說清它的本質:LabVIEW 的“密碼保護”並不是加密。框圖本身以明文存在文件裏,擋住你的只是一小段記錄。插件把這段記錄改成“空密碼 + 正確哈希”,再把版本塊裏的一個保護標誌位清掉,LabVIEW 打開時就不再詢問密碼。
工作原理¶
鎖定信息存在兩個塊裏:
| 塊 | 含義 |
|---|---|
BDPW |
md5(password) + hash_1 + hash_2,即密碼記錄 |
LVSR |
版本塊;execFlags 的 bit 13(LibProtected,0x2000)標記該庫受保護 |
插件要做的就是四步:
password_md5→md5(""),即d41d8cd98f00b204e9800998ecf8427ehash_1→md5(md5("") ‖ LIBN ‖ LVSR ‖ salt)hash_2→md5(hash_1 ‖ contentHash(BDH))- 清掉
LVSR裏的VI_EXEC_FLAGS.LibProtected
唯一未知量是 12 字節 salt,LabVIEW 由連接器面板上各端子類型的數量推導。引擎不去解析類型描述符,而是對這三個小整數做暴力枚舉——典型計數值小於 20,多數文件幾毫秒內就能解出。文件其餘部分不動:不重新序列化、不重新壓縮、不改變長度;原本沒鎖的文件保持字節一致。
安裝與啓用¶
以下命令來自 README。第一種是從 npm 安裝,但 README 註明要等包發佈之後纔可用;第二種指向本地檢出。
dsh plugin --profile web add dsh-labview # from npm, after it is published
dsh plugin --profile web add link:/path/to/dsh-labview # local checkout
裝好後重啓 harness(或在市場頁面切換插件開關),三個工具會在每個會話裏出現。運行環境要求 Node >=20.19.0,DSH 側要求 >=0.1.0-rc.6 <0.3.0。
README 提到 lib/engine.js 是獨立模塊,也可以直接 import 進來使用解析和修補邏輯,繞過 harness。
使用¶
插件暴露三個工具,可以用自然語言調用,也可以直接調用。
lv_scan(dir?, lockedOnly?) 是隻讀檢查,逐文件報告 LabVIEW 版本、框圖是否被保護、能否解鎖以及不能解鎖的原因。它不寫任何內容,可以在生產副本上安全運行。
lv_unlock(dir?, dryRun?, hashSource?, limit?) 先把每個原件備份到 <dir>/_lv_unlock_backup/…,再修補文件,並且在落盤前先在內存裏校驗修補後的字節。已經打開的文件會被計數並跳過。dryRun: true 只報告將要做什麼、不做任何寫入,大目錄建議先跑一遍。
lv_restore(dir?, dryRun?, limit?) 把備份複製回工作文件,撤銷解鎖。
一個典型會話是:
掃描
D:\SCADA\FC MAS V1裏被鎖的 LabVIEW 文件,然後解鎖,並告訴我需要哪個 LabVIEW 版本才能打開這個項目。
模型會調用 lv_scan,看到 140 × LabVIEW 2015 / 83 × LabVIEW 8.5,再運行 lv_unlock,把兩者一併彙報。原件保留在 _lv_unlock_backup/,直到你手動刪除。
安全模型與配置¶
lv_unlock 的安全順序是:先備份、再校驗、後落盤。具體約束有幾條:
- 第一字節寫入之前先複製原件到備份樹,且已有備份永不覆蓋,第二次
lv_unlock不會破壞原始副本。 - 修補後的緩衝區會被重新解析,必須報告“無密碼”才寫入文件,任何異常都會被拒絕。
- 寫入通過
<file>.lvunlock.tmp+ rename 完成,中斷運行不會留下半個 VI。 - 每個文件只改兩處,並報告確切的字節區間;不需要改動的文件永遠不會被重寫。
- 全程不需要 LabVIEW,引擎直接解析
RSRC,不運行 VI、不解編譯框圖、不需要許可證。
所有配置項都有可用默認值,僅在需要時覆蓋:
| 配置項 | 默認值 | 含義 |
|---|---|---|
backupDir |
_lv_unlock_backup |
備份目錄,相對掃描根目錄 |
extensions |
.vi .ctl .vit .ctt .xctl |
要處理的文件類型 |
maxFiles |
20000 |
單次掃描的上限 |
concurrency |
4 |
並行處理的文件數 |
hashSource |
auto |
新哈希覆蓋哪個版本塊(auto/final/original) |
對應 profile 配置:
# profile cordis.patch.yml
- id: labview-unlock
config:
backupDir: _lv_backup
concurrency: 8
版本處理上有一處細節:刪除密碼也會清掉 LibProtected,而 LabVIEW 是在這之後纔對版本塊做哈希,所以 hash_1 覆蓋的是已清除標誌位的塊;舊版本保存的 VI 使用遺留版本塊佈局,標誌位從未進入哈希。引擎通過 hashSource: "auto" 自動識別兩種情況並復現對應行爲,"final" 或 "original" 可強制其中一種。
支持範圍¶
支持 LabVIEW 8.0 到 2019 保存的文件(以及最後由這些版本保存的舊文件)。LabVIEW 2020 及以上改變了框圖佈局,這類文件會被報告爲不支持,而不是被寫入。
適用場景與注意¶
適合接手了遺留 LabVIEW 項目、需要批量恢復框圖訪問權限、又不方便鋪開整套 NI 環境的人。需要注意幾點:
- 插件以當前 dsh 進程的權限運行。安裝前應先檢查源碼與許可證(本插件爲 MIT),確認來源可信。
- 插件無法打開 LabVIEW,所以“已解鎖”只表示文件自身的密碼記錄如此。對不可替代的項目做批量解鎖前,先用 LabVIEW 打開一個文件驗證。
- 動詞暴力搜索有上限,每個計數最多搜到 255(約 1670 萬種組合)。連接器面板超出此範圍的文件會被報告爲不可解鎖,而不會被靜默誤處理。
- 解除
*.ctl的密碼同樣會暴露其框圖;原本被當作不透明黑盒使用的類型,現在可以被編輯。 - 倫理邊界:只對你擁有或被授權維護的軟件使用本工具。恢復公司已付費項目的訪問屬於維護,破解廠商的授權限制則不是。
README 裏的驗證數據來自插件自述:在真實工業代碼上,重新解鎖後與原件逐字節比較 223 / 223 一致;此前一個 601 文件項目隨機抽查 597 個已解鎖、0 個仍被鎖;密碼鹽恢復 223 / 223 正確;誤改文件 0 個,每個差異都只是密碼塊加一個標誌字節。平均每文件約 35 ms,最慢的一個約 0.9 s。
結尾¶
dsh-labview 的價值在於把一個依賴重運行時的逆向維護任務,收斂成純 JavaScript 的字節修補,並配了備份、校驗、原子寫入這三層保護。它目前星標爲 0,屬於早期階段的社區項目,功能與限制都寫在 README 裏。
目錄頁在 https://www.skillhub.cn/plugins/yxfvvv/dsh-labview ,源碼在 https://github.com/yxfvvv/dsh-labview 。需要說明的是,skillhub 是社區維護的獨立目錄站點,與 DeepSeek 及幻方沒有官方從屬關係,不是官方應用商店。