Under Intune-enforced LSA FIPS policy, Profilometer / VRAnalyzer / VRInspection apps crash at device init when MD5CryptoServiceProvider's ctor is called to verify the probe EEPROM calibration (see keyence3000.txt + .png in pxe-images for the dialog + stack). Patch each .exe.config under C:\Program Files\KEYENCE\<model>\ with <runtime><enforceFIPSPolicy enabled="false"/></runtime>. Scope is app-CLR only; OS-wide Lsa FIPS policy stays enforced. CMMC posture: scoped exception, non-CUI integrity hash, documented in SSP. Each affected bay's hostname must be on InfoSec's FIPS-exception list before imaging. 09-Setup-Keyence.ps1 gates the patch behind model=vr3000 only. vr5000 / vr6000 bays do not auto-apply. Verified on win11 VM via qga: 29 configs across vr5000+vr6000 layouts (vr3000 install was incomplete on VM), patched + idempotent on re-run, existing <runtime> children preserved. Also verified on a real PC: 27 patched + 2 skipped (Keyence pre-shipped the element in two configs), 0 errors. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
115 lines
4.1 KiB
PowerShell
115 lines
4.1 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Patches all Keyence VR-series .exe.config files to opt the app out of .NET
|
|
FIPS policy enforcement so the EEPROM MD5 calibration check does not throw
|
|
'This implementation is not part of the Windows Platform FIPS validated
|
|
cryptographic algorithms.'
|
|
|
|
Currently approved only for VR-3000 G2. Before running on a production
|
|
bay, report the PC hostname to GE InfoSec and confirm the bay is on
|
|
the documented FIPS-exception list. Imaging-time auto-apply (in
|
|
09-Setup-Keyence.ps1) gates this script behind model=vr3000.
|
|
|
|
.DESCRIPTION
|
|
Scans C:\Program Files\KEYENCE and C:\Program Files (x86)\KEYENCE for any
|
|
.exe.config under VR-3000 G2, VR-5000, VR-6000 (and any other Keyence model
|
|
that ships in the same root). Injects:
|
|
<runtime>
|
|
<enforceFIPSPolicy enabled="false"/>
|
|
</runtime>
|
|
as a sibling under <configuration>. Preserves any existing <runtime>
|
|
children (generatePublisherEvidence, useLegacyJit, etc).
|
|
|
|
Idempotent. Re-running is a no-op for already-patched configs.
|
|
|
|
This patch is SCOPED to the Keyence app's CLR. It does NOT disable the
|
|
OS-wide LSA FIPS policy. Intune / Defender baseline policies that enforce
|
|
the LSA key remain in effect.
|
|
|
|
.PARAMETER InstallRoots
|
|
Override the default search roots. By default both C:\Program Files\KEYENCE
|
|
and C:\Program Files (x86)\KEYENCE are scanned.
|
|
|
|
.PARAMETER WhatIf
|
|
Show what would be patched without writing any files.
|
|
|
|
.EXAMPLE
|
|
.\Patch-KeyenceFipsConfigs.ps1
|
|
.\Patch-KeyenceFipsConfigs.ps1 -WhatIf
|
|
.\Patch-KeyenceFipsConfigs.ps1 -InstallRoots 'D:\KEYENCE'
|
|
|
|
.NOTES
|
|
Affected EXEs (Profilometer3.exe, VRAnalyzer*.exe, VRInspection_*.exe, etc.)
|
|
must be restarted after the patch for the new config to take effect.
|
|
#>
|
|
[CmdletBinding(SupportsShouldProcess)]
|
|
param(
|
|
[string[]]$InstallRoots = @(
|
|
'C:\Program Files\KEYENCE',
|
|
'C:\Program Files (x86)\KEYENCE'
|
|
)
|
|
)
|
|
|
|
$ErrorActionPreference = 'Continue'
|
|
|
|
$patched = 0
|
|
$skipped = 0
|
|
$errors = 0
|
|
|
|
foreach ($root in $InstallRoots) {
|
|
if (-not (Test-Path -LiteralPath $root)) {
|
|
Write-Host "Root not present, skipping: $root"
|
|
continue
|
|
}
|
|
Write-Host "Scanning: $root"
|
|
$configs = Get-ChildItem -LiteralPath $root -Filter '*.exe.config' -Recurse -ErrorAction SilentlyContinue
|
|
foreach ($cfg in $configs) {
|
|
try {
|
|
[xml]$xml = Get-Content -LiteralPath $cfg.FullName
|
|
$cfgRoot = $xml.configuration
|
|
if (-not $cfgRoot) {
|
|
Write-Warning " [SKIP] No <configuration> root: $($cfg.FullName)"
|
|
$errors++
|
|
continue
|
|
}
|
|
|
|
$rt = $cfgRoot.SelectSingleNode('runtime')
|
|
if (-not $rt) {
|
|
$rt = $xml.CreateElement('runtime')
|
|
$cfgRoot.AppendChild($rt) | Out-Null
|
|
}
|
|
|
|
$existing = $rt.SelectSingleNode("enforceFIPSPolicy[@enabled='false']")
|
|
if ($existing) {
|
|
Write-Host " [SKIP] already patched: $($cfg.FullName)"
|
|
$skipped++
|
|
continue
|
|
}
|
|
|
|
# Remove any other enforceFIPSPolicy variants (enabled=true or no attr).
|
|
$rt.SelectNodes('enforceFIPSPolicy') | ForEach-Object { $rt.RemoveChild($_) | Out-Null }
|
|
|
|
$fips = $xml.CreateElement('enforceFIPSPolicy')
|
|
$fips.SetAttribute('enabled', 'false')
|
|
$rt.AppendChild($fips) | Out-Null
|
|
|
|
if ($PSCmdlet.ShouldProcess($cfg.FullName, 'Inject enforceFIPSPolicy')) {
|
|
$xml.Save($cfg.FullName)
|
|
Write-Host " [OK] patched: $($cfg.FullName)"
|
|
$patched++
|
|
} else {
|
|
Write-Host " [WHATIF] would patch: $($cfg.FullName)"
|
|
}
|
|
} catch {
|
|
Write-Warning " [ERR] $($cfg.FullName): $_"
|
|
$errors++
|
|
}
|
|
}
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "Summary: patched=$patched skipped=$skipped errors=$errors"
|
|
Write-Host ""
|
|
Write-Host "Restart Keyence apps (Profilometer3.exe, VRAnalyzer*.exe, VRLauncher.exe,"
|
|
Write-Host "VRInspection_*.exe, etc.) for the new config to take effect. No reboot needed."
|