WinCC V5/V6 Project Protection: Hardware Dongles and Script Locks

David Krause15 min read
SiemensTechnical ReferenceWinCC
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview: Why Protect a WinCC Project?

WinCC (versions 5 and 6, both classic and the early TIA-aligned runtime) stores an entire SCADA project as a set of unencrypted files on the engineering station and on the runtime station. The runtime database (typically a .pdb project file plus the GraCS directory containing .pdl pictures, .fct actions, .pas scripts, .db archives, and .log files) can be copied from a working plant, transported to a competitor's PC, and reopened in WinCC Explorer. Because the C actions and VBS scripts are not compiled to native code, they are plain text and can be edited freely by anyone with WinCC engineering installed. The WinCC software license itself is tied to a license key (either a software license on the hard disk or, in later versions, a USB license stick called the Automation License Manager / ALM dongle), but the project is not protected by that mechanism. This article documents the field-proven techniques used by integrators to bind a WinCC V5/V6 runtime project to a specific PC using a hardware security key (USB dongle), MAC address binding, encrypted project media, and password-locked C scripts.

Architecture Constraints of WinCC V5 and V6

Before any protection strategy is selected, the engineer must understand the file layout and runtime model of WinCC V5/V6 because they dictate the attack surface:

Component File Type Readable Without Password Copyable Executable Without Dongle
WinCC Explorer Project File *.pdb / *.mcp Yes (binary, opens in WinCC) Yes Yes
Graphics (Pictures) *.pdl in GraCS\ Yes (opens in Graphics Designer) Yes Yes
C Actions / Global Script *.fct Yes (plain-text C source) Yes Yes
VBS Actions *.pas Yes (plain-text VBScript) Yes Yes
Tag Management / Archives *.db, *.ldf Binary, but portable Yes Yes
Compiled Runtime None — V5/V6 do not produce a compiled runtime image N/A N/A N/A

Because every project file is unencrypted and the project itself contains no native binary runtime, any third party with a matching or higher WinCC version and a valid runtime license can copy the GraCS folder plus the project file to a new PC and start the application. The standard Siemens Automation License Manager (ALM) license for WinCC Runtime only proves that the local PC is authorized to run WinCC, not that the running project is the integrator's original one.

Key constraint: WinCC V5/V6 do not support AES or RSA encryption of the project database. The project must be protected indirectly through runtime checks (script-level hardware key verification, MAC binding, file fingerprinting) rather than through file-level cryptography native to WinCC.

Hardware Dongle Concepts and Vendors

A hardware dongle (also called a hardware key, security key, or HASP/HL key) is a physical USB device that contains a secure element. Modern security keys implement cryptographic challenge-response or store a per-customer secret that is not extractable to the host. The conceptual model is well documented by the major consumer-platform vendors for the FIDO2 / WebAuthn case:

The industrial-grade equivalents follow the same architecture but expose a vendor-specific DLL instead of a FIDO2 interface. For WinCC V5/V6 the typical candidates are:

Vendor / Product Interface DLL API Style Notes for WinCC
SafeNet (Thales) Sentinel HL / HASP SRM USB hasp_login(), hasp_read(), hasp_encrypt() Widely deployed in industrial software; runtime library redistributable
MatrixLock ( WIBU-Systems CodeMeter ) USB / SD / CF CmAccess(), CmGetInfo() Supports binding to a feature ID and a per-license expiry
Aladdin HASP4 / HASP HL USB / Parallel (legacy) hasp() legacy calls Still found on older WinCC V5 / V6 stations
Rockwell FactoryTalk Activation (reference) USB Vendor-locked to FT Not directly usable in WinCC, but proves the dongle model is industry-standard
YubiKey (FIDO2) / Titan / Feitian USB / NFC WebAuthn / CCID Designed for browser SSO, not for runtime licensing of WinCC
General-purpose FIDO2 / Titan / YubiKey devices are not designed for industrial software licensing. They are listed here only to clarify that consumer security keys are not a drop-in replacement for an industrial dongle when protecting a WinCC project.

Implementation Strategy: Indirect Binding via C Script

Because WinCC V5/V6 does not compile C actions to native code, the protection logic must be embedded into the C action and triggered on every meaningful event. The recommended pattern is to verify the dongle at three points in the project lifecycle:

  1. Project open (WinCC startup): check the dongle, abort Runtime start if absent.
  2. Periodic background check (global action, e.g. every 60 s): confirm the dongle is still present; if removed, degrade to a safe state.
  3. Critical action gating (e.g. motor start, setpoint write, recipe load): re-check before each write that affects the process.

Step 1 — Vendor DLL Registration

Copy the vendor-supplied runtime DLLs (e.g. hasp_windows_103275.dll, CmActLicense.dll) into the WinCC project directory <Project>\bin\ or into %SystemRoot%\System32\. The vendor license runtime must be installed on the runtime PC; the matching developer SDK only needs to be present on the engineering station where the C action is written.

Step 2 — Declare the Dongle API in the C Action

Open the Global Script editor in WinCC Explorer, create a new C action, and declare the API prototypes. The example below uses the legacy SafeNet HASP API; substitute the equivalent calls for your dongle vendor.

// ----- WinCC V5/V6 C action: Dongle presence check -----
#include "apdefap.h"

// Vendor prototype (HASP HL example)
extern "C" int WINAPI hasp_login(int feature, int vendor_code,
                                  void *handle);
extern "C" int WINAPI hasp_check_service(int feature, int vendor_code);
extern "C" int WINAPI hasp_logout(void *handle);

#define HASP_FEATURE 1          // assigned by vendor
#define HASP_VENDOR  0x1234ABCD // your vendor code

BOOL g_dongleOK = FALSE;
static void *g_handle = NULL;

void CheckDongleOnStart(void)
{
    int rc = hasp_login(HASP_FEATURE, HASP_VENDOR, &g_handle);
    g_dongleOK = (rc == 0);
    if (!g_dongleOK) {
        // Optional: log to internal WinCC tag for diagnostics
        SetTagBit("@DongleMissing", TRUE);
    } else {
        SetTagBit("@DongleOK", TRUE);
    }
}

The function CheckDongleOnStart() should be called from a startup function in the project's ApStart sequence or attached to the @Startup project function so it fires when WinCC Runtime is launched.

Step 3 — Periodic Re-Verification in a Global Action

Configure a WinCC global action that runs every 60 seconds and re-validates the dongle:

void OnTimedDongleCheck(void)
{
    int rc = hasp_check_service(HASP_FEATURE, HASP_VENDOR);
    if (rc != 0) {
        // Dongle removed or service stopped
        SetTagBit("@DongleOK", FALSE);
        SetTagBit("@DongleMissing", TRUE);

        // Safe-state: clear enable tags, raise alarm
        SetTagBit("@Plant_Enable", FALSE);
        SetTagWord("@DongleAlarm", 1001); // 1001 = dongle removed
    }
}

Schedule the action via the WinCC scheduler: trigger = cyclic, period = 60 s, pointer = OnTimedDongleCheck. For WinCC V6, the equivalent VBScript wrapper would use CreateObject("HASP.HLAPI"); for older V5 the legacy HASP4 API uses hasp(1, 0) returning a session handle.

Step 4 — Gate Critical Writes

For any C action that writes a tag tied to a process output (motor start, valve open, setpoint, recipe), add a guard that requires @DongleOK == TRUE:

if (GetTagBit("@DongleOK") == FALSE) {
    SetTagBit("Motor_Start_CMD", FALSE);
    SetTagWord("@LastError", 2003); // 2003 = protected action blocked
    return;
}

// Original action logic follows
SetTagBit("Motor_Start_CMD", TRUE);

MAC Address Binding as a Second Layer

Even with a dongle, an attacker who can read the dongle's session bytes can in principle replay them. A second binding layer — the MAC address of the host's primary network interface — adds friction. WinCC V5/V6 supports reading the MAC through a C action that calls the Win32 IP Helper API:

#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")

BOOL ReadPrimaryMac(BYTE macOut[6])
{
    ULONG bufLen = 0;
    GetAdaptersInfo(NULL, &bufLen);                // first call -> size
    PIP_ADAPTER_INFO pInfo = (PIP_ADAPTER_INFO)malloc(bufLen);
    if (GetAdaptersInfo(pInfo, &bufLen) != ERROR_SUCCESS) {
        free(pInfo); return FALSE;
    }
    memcpy(macOut, pInfo->Address, 6);             // first adapter
    free(pInfo);
    return TRUE;
}

// Compare against a hard-coded expected MAC
static const BYTE EXPECTED_MAC[6] = { 0x00, 0x0E, 0x8C, 0x4A, 0x12, 0x9F };

void VerifyMacAtStartup(void)
{
    BYTE mac[6];
    if (!ReadPrimaryMac(mac)) return;
    if (memcmp(mac, EXPECTED_MAC, 6) != 0) {
        SetTagBit("@DongleOK", FALSE);
        SetTagWord("@DongleAlarm", 1002); // 1002 = MAC mismatch
    }
}

The expected MAC is a constant in the C source. To make the check less obvious, do not store it as a six-byte literal: XOR it with a project-specific 6-byte key first, or read it from a registry value that is written during commissioning. The MAC check must run on the same startup hook as the dongle check; if either fails, Runtime must not start the plant.

Field note: MAC binding is trivially defeated by a knowledgeable attacker who can spoof the MAC of the primary NIC. Use it only as a friction layer on top of a hardware dongle, never as the sole protection.

Password-Protected C and VBS Actions

WinCC's C actions and VBS actions support a script-level password. The protection is in the editor only — the source text is still stored on disk — but it prevents a casual user from opening the script in Graphics Designer and deleting the dongle check. To apply the password:

  1. In WinCC Explorer, right-click the Global Script node and select Open.
  2. Open the action and choose Edit > Password.
  3. Set a strong password (minimum 12 characters, mixed case, digits, one symbol). The password applies to both read and write of the script source.

Combine script-level passwords with the dongle and MAC binding: a password by itself stops the casual integrator, a dongle stops the determined user, MAC binding raises the cost of forging a runtime environment.

Encrypted USB as Project Carrier

An alternative to a license-only dongle is to ship the project on an encrypted USB stick (e.g. an Apricorn Aegis, iStorage datAshur, or an IronKey device). WinCC Runtime is then configured to load the project from a path on the USB rather than from C:\Siemens\WinCC\.... The encrypted USB enforces two properties at once:

  • Without the PIN, the project files cannot be enumerated or copied, so the project cannot be exfiltrated.
  • If the operator tries to start Runtime without the USB inserted, the project path is missing and Runtime fails to start.

Configure the encrypted-USB approach in WinCC Explorer > Computer > Properties > Startup: set the project path to the mount letter of the encrypted USB (e.g. E:\Project\MyPlant.pdb). Combine with an AutoStart entry in the Windows shell startup folder so that Runtime launches immediately after the user logs in; with a USB-only project, the plant cannot be reproduced without that physical key.

Hardening the Runtime PC

Dongles and encrypted USB devices still rely on the host PC being cooperative. Apply these host-level controls:

Control Mechanism Defeats
Disable Windows hot-keys Group Policy > User Configuration > Administrative Templates > Windows Components > File Explorer > Turn off Windows+X hotkeys Operator opening Explorer, copying files
Disable Task Manager HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System\DisableTaskMgr = 1 Operator killing WinCC Runtime
Run Runtime as a custom shell HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell = "C:\Siemens\WinCC\bin\WinCCExplorer.exe -r" Operator reaching the desktop
Restrict USB write to approved devices only Group Policy > Removable Storage Access Copying project to unencrypted USB
Disable WinCC Explorer and Graphics Designer File system ACL — deny read/execute to operator user Operator opening project in configuration mode
Disable right-click context menus in Runtime WinCC project property > Disable hotkeys and context menu Operator invoking task switcher

Each of these controls can be bypassed by an administrator with a Windows recovery disk, but the combination raises the cost above the value of the project for a typical plant deployment.

Limitations and Known Bypass Techniques

No WinCC V5/V6 protection scheme is cryptographically complete. Document these limitations for the customer before commissioning:

  1. PDL copy attack: An attacker can create a blank WinCC project, delete the default GraCS contents, and copy in the protected project's .pdl, .fct, and .pas files. Pictures will render, but internal tags and alarms that referenced global script variables will fail. If the dongle check is implemented as a missing-tag return, the attacker can stub the tag and bypass it.
  2. Script edit attack: An attacker who recovers the script password can simply delete the CheckDongleOnStart() call. Mitigate by distributing the check logic across many small C actions and by adding redundant checks in the periodic background task.
  3. DLL proxy attack: An attacker can replace the vendor DLL with a stub that always returns success. Mitigate by signing the DLL and verifying the signature inside the C action (Win32 WinVerifyTrust).
  4. Dongle emulation: A determined attacker can build a software emulator for the dongle's challenge-response. Field-grade industrial dongles (SafeNet Sentinel HL with SL key, WIBU CodeMeter with CmDongle) include anti-emulation features, but no dongle is unbreakable given enough time.
  5. Project export/import via WinCC Excel tool: The WinCC Excel-based tag export/import tool accesses the project database directly. If the project is opened in configuration mode without a dongle check, the attacker can rebuild the project offline.

Commissioning and Verification Checklist

Run this checklist on the customer PC before signing off the project:

  1. Insert the dongle. Start WinCC Runtime. Confirm @DongleOK = TRUE within 5 seconds.
  2. Remove the dongle. Within 60 seconds, confirm @DongleOK = FALSE and @Plant_Enable = FALSE.
  3. Reinsert the dongle. Confirm Runtime resumes normal operation without a manual restart.
  4. Copy the entire project folder to a second PC that has a WinCC runtime license but no dongle. Attempt to start Runtime. Confirm Runtime aborts and an alarm is raised.
  5. Open Graphics Designer on the engineering PC. Try to open each C action. Confirm a password prompt is shown for the protected actions.
  6. Boot the runtime PC and confirm WinCC Runtime starts automatically without the operator reaching the Windows desktop.
  7. From a second PC, ping the runtime PC. Confirm the project is not served on any open SMB share.
  8. Edit the registry to disable the dongle vendor service. Confirm Runtime aborts within one scheduling cycle.

Comparison of Protection Methods

Method Strength Implementation Cost Defeats Does Not Defeat
USB hardware dongle (SafeNet, WIBU) High Medium — DLL integration, action edits Casual copying, blank-project attack DLL proxy, dongle emulator
MAC address binding Medium Low — Win32 IP Helper in C action PC swap, accidental license transfer MAC spoofing, NIC replacement
Script password Low Trivial Casual browsing, accidental edits Password recovery, file copy
Encrypted USB project carrier High (for offline attacks) Low — path change in WinCC Project exfiltration via file copy PC cloning with the USB plugged in
Custom shell + auto-start Medium Low — registry change Operator reaching the desktop Administrator with recovery media
Combined: dongle + MAC + encrypted USB + custom shell Very high (for a SCADA project) Medium All of the above State-level adversary with dongle emulator and recovery disk

Field Notes and Pitfalls

  • Never store the dongle vendor code as a literal in the C action. Either encrypt it with a per-project key or read it from a registry value written during commissioning.
  • Do not put all the protection logic in a single global action. Spread checks across the picture-level actions so that removing one check does not defeat the entire scheme.
  • If the project uses VBS actions (WinCC V6), the equivalent of hasp_login() is a CreateObject call to the vendor COM object. The vendor COM object is also a plain-text reference and can be removed; protect it behind a password the same way you would protect a C action.
  • If the customer requires the same project to be licensed for two PCs, buy a multi-seat dongle (vendor feature "2 network seats") and embed the seat count in the C action.
  • Document the protection scheme in a sealed file left with the customer. If the dongle is lost, the integrator needs the vendor code and the expected MAC to issue a replacement.
  • Always test the protection on a fresh PC with no project history. The most common commissioning failure is that the dongle check passes on the engineering PC (because the DLL is installed there) and fails on the runtime PC (because the runtime DLL is missing or blocked by antivirus).
  • Some dongle vendors require a separate "runtime" redistribution license for the DLL. The development SDK is for engineering only and is not redistributable.

FAQ

Can I use a YubiKey, Titan, or Apple security key to protect a WinCC V5/V6 project?

No. YubiKey, Google Titan, and the Apple security key implement the FIDO2 / WebAuthn protocol for second-factor authentication on web services (see Microsoft's security-key guide and Google's Titan page). They do not expose a generic challenge-response API that a WinCC C action can call. Use an industrial dongle vendor (SafeNet Sentinel HL, WIBU CodeMeter, or Aladdin HASP) instead.

Why not just buy one WinCC runtime license and stop the customer from copying the project?

A WinCC runtime license authorizes the PC to run WinCC; it does not bind the project to that PC. Without additional protection, the customer's engineer can copy the GraCS folder and the project file to any PC that has its own valid WinCC runtime license and run the same SCADA application there.

Does a password-protected C action stop a determined attacker from removing the dongle check?

No. The WinCC C action password is editor-level only; the source text is still present on disk. A password slows down a casual user but does not stop someone who is willing to spend time recovering the password. Combine the password with code-level obfuscation (split checks across many actions, indirect calls, and runtime tag gating) and with a hardware dongle.

What is the difference between a hardware dongle and an encrypted USB project carrier?

A hardware dongle is a small USB device with a secure element that answers cryptographic challenges; the WinCC project lives on the PC's hard disk and the dongle is checked at runtime. An encrypted USB project carrier stores the project files on a hardware-encrypted USB stick; the dongle is the file system itself, and the project cannot run without the unlocked stick inserted. The two approaches are complementary and are often combined in high-value SCADA deployments.

How do I recover a project if the dongle vendor goes out of business?

Buy the dongle from a vendor that publishes a long-term support roadmap (Thales/SafeNet and WIBU-Systems have 10+ year histories in industrial automation) and keep a record of the vendor code, the feature ID, and the runtime DLL version. If the vendor disappears, the runtime DLL can still call the dongle on existing hardware; the limitation is that you cannot license new dongles. Plan for this by purchasing a small spare pool of pre-programmed dongles at project hand-over.

Back to blog