DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

yxfvvv /

yxfvvv/dsh-labview

Verified

Open password-protected LabVIEW VI/CTL block diagrams without LabVIEW or Python — DSH plugin.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHubProject homepage
READMESource: main@7f26f835

dsh-labview

Open password-protected LabVIEW block diagrams — without LabVIEW, without Python.

Inherited a LabVIEW project whose front panels open but whose block diagrams are locked? This plugin removes that protection from *.vi, *.ctl, *.vit and *.ctt files by patching a few bytes in place. No gigabytes of NI runtime, no pylabview, no network — just a small, dependency-free JavaScript engine.

lv_scan      what is locked, and which LabVIEW version saved each file
lv_unlock    back up, patch, verify, write
lv_restore   put the originals back

Why this exists

LabVIEW "password protection" is not encryption. The diagram is stored in the file in the clear; what stops you from opening it is a small bookkeeping block:

Block Meaning
BDPW md5(password) + hash_1 + hash_2 — the password record
LVSR version block; execFlags bit 13 (LibProtected, 0x2000) marks a locked library

Give LabVIEW an empty password and matching hashes and it opens the diagram without asking. That is exactly what this plugin writes:

  1. password_md5 → md5("") = d41d8cd98f00b204e9800998ecf8427e
  2. hash_1 → md5(md5("") ‖ LIBN ‖ LVSR ‖ salt)
  3. hash_2 → md5(hash_1 ‖ contentHash(BDH))
  4. clear VI_EXEC_FLAGS.LibProtected in LVSR

The only unknown is the 12-byte salt, which LabVIEW derives from the counts of terminal types in the connector pane. Rather than parse the type descriptors, the engine brute-forces the three small integers against the hashes already stored in the file — a typical count is under 20, so most files resolve in a few milliseconds.

Nothing else in the file is touched: no re-serialization, no re-compression, no length changes. A file that was not locked is left byte-identical.

Install

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

Restart the harness (or toggle the plugin in the market page) and the three tools appear in every session.

Use

Ask in plain language — "unlock the LabVIEW files in this project" — or call the tools directly.

lv_scan(dir?, lockedOnly?)

Read-only survey. Reports, per file, the LabVIEW version, whether the block diagram is protected, whether it can be unlocked, and why not when it cannot. Uses no writes, so it is safe on a production copy.

lv_unlock(dir?, dryRun?, hashSource?, limit?)

Backs up every original into <dir>/_lv_unlock_backup/…, patches the file, and verifies the patched bytes in memory before touching the disk. Already-open files are counted and skipped. dryRun: true reports what would happen and writes nothing — always worth doing first on a large tree.

lv_restore(dir?, dryRun?, limit?)

Copies the backups back over the working files, undoing an unlock.

A typical session

Scan D:\SCADA\FC MAS V1 for locked LabVIEW files, then unlock them and tell me which LabVIEW version I need to open the project.

The model runs lv_scan, sees 140 × LabVIEW 2015 / 83 × LabVIEW 8.5, runs lv_unlock, and reports both. Originals stay in _lv_unlock_backup/ until you delete them.

Safety model

  • Backup first. The original is copied to the backup tree before the first byte is written. An existing backup is never overwritten, so a second lv_unlock cannot destroy the pristine copy.
  • Verify, then write. The patched buffer is re-parsed and must report "no password" before it reaches the file. Anything unexpected is refused.
  • Atomic writes. Bytes land through <file>.lvunlock.tmp + rename, so an interrupted run cannot leave a half-written VI.
  • Only two edits. lv_unlock reports the exact byte ranges it changed for every file; a file that needs no change is never rewritten.
  • No LabVIEW required. The engine parses the RSRC container directly. It never runs the VI, never decompiles the diagram, and never needs a license.

Supported range

Files saved by LabVIEW 8.0 through 2019 (and older files that were last saved by those releases). LabVIEW 2020+ changed the block layout; those files are reported as unsupported instead of being written.

Version handling has one subtlety worth knowing: removing a password also clears LibProtected, and LabVIEW hashes the version block after that change — so hash_1 covers the cleared flags. VIs last saved by old releases keep a legacy version-block layout where the flag never made it into the hash. The engine detects this (hashSource: "auto") and reproduces the matching behaviour; "final" or "original" force one or the other.

Evidence

The engine is not a guess: it was validated byte-for-byte against a reference implementation on real industrial code.

Check Result
Files re-unlocked from pristine originals and compared byte-for-byte 223 / 223 identical
Random spot audits of a previous 601-file project 597 unlocked, 0 remaining locked
Password-salt recovery proved correct (re-derives the hashes already in every file) 223 / 223
Files modified by mistake 0 — every diff was the password block plus one flag byte

Average 35 ms per file; the slowest file (a large VI with an unlucky salt) takes about 0.9 s.

Config

Every option has a working default; override only if you want to.

Option Default Meaning
backupDir _lv_unlock_backup Backup directory, relative to the scanned root
extensions .vi .ctl .vit .ctt .xctl File types to process
maxFiles 20000 Safety cap on a single scan
concurrency 4 Files processed in parallel
hashSource auto Which version block the new hash covers (auto/final/original)
# profile cordis.patch.yml
- id: labview-unlock
  config:
    backupDir: _lv_backup
    concurrency: 8

Limitations

  • No in-app verification. The plugin cannot open LabVIEW, so "unlocked" means the file's own password record says so. Open one file in LabVIEW before trusting a bulk run on an irreplaceable project.
  • Salt brute force has a ceiling. Counts are searched up to 255 each (≈16.7 M combinations). Pathological connector panes beyond that are reported as not unlockable rather than silently mishandled.
  • Type definitions. Unlocking a *.ctl exposes its diagram too — as with any password removal, types the project used as opaque boxes can now be edited.
  • Ethics. Use this only on software you own or are authorized to maintain. Recovering access to a project your company paid for is maintenance; defeating a vendor's licensing is not.

Development

The harness ships an Electron binary that runs as Node, which is handy on machines without a separate Node install:

ELECTRON_RUN_AS_NODE=1 "…/DSH Desktop.exe" test/verify-223.mjs <project dir>
ELECTRON_RUN_AS_NODE=1 "…/DSH Desktop.exe" test/smoke.mjs <dir with locked VIs>
ELECTRON_RUN_AS_NODE=1 "…/DSH Desktop.exe" test/harness-swap.mjs

test/verify-223.mjs compares the engine against reference output byte-for-byte; test/smoke.mjs drives the three plugin tools end to end on a temp copy; test/harness-swap.mjs temporarily points the vendored defineTool/Schema stubs at the real modules inside the installed harness and re-runs the smoke test, which is what proves the Host accepts the parameter specs, output schemas and config schema. It restores the stubs afterwards, even on failure.

assets/make-icon.mjs renders the icon with no image dependency.

Publishing steps (npm, GitHub, marketplace PR) are in PUBLISHING.md.

lib/engine.js is standalone — import it from dsh-labview/engine to use the parser and patcher without the harness.

License

MIT.

—/ 5

No ratings yet

Verified DSH bundle

Commit 7f26f8351386

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout