Skip to content

Latest commit

 

History

History

README.md

SignedPlugins

Authenticode signature verification for plugins via the OnValidateModule hook.

Architecture

SignedPluginsApp.exe
|   DCC_UsePackage = rtl;fmx;FMXPluginFramework
|
+-- TBPLLoader.Create(BinPath)
+-- FLoader.OnValidateModule := ValidateModule  <- set hook
+-- FLoader.LoadAll(plugins.json)
|   |
|   +-- SignedPlugin.bpl      -> ValidateModule -> VerifyAuthenticode -> OK -> load
|   +-- UnsignedOptional.bpl  -> ValidateModule -> VerifyAuthenticode -> FAIL -> skip (optional)
|   +-- UnsignedRequired.bpl  -> ValidateModule -> VerifyAuthenticode -> FAIL -> Exception (required)
|
+-- Application.Run

What This Demo Shows

  • OnValidateModule hook: Callback is called BEFORE each LoadPackage
  • TSecurityValidator.VerifyAuthenticode: Windows WinVerifyTrust API for signature verification
  • Required vs Optional: plugins.json controls whether a validation failure stops the app or skips the plugin
  • Three plugin variants: Signed, unsigned-optional, unsigned-required

Files

File Purpose
SignedPluginsApp.dpr Host app with ValidateModule callback
SignedPlugins.groupproj Build: Framework -> 3 Plugins -> App
plugins.json Plugin list with required flag
../DemoPlugins/SignedPlugin/ Simulates a signed plugin
../DemoPlugins/UnsignedOptional/ Unsigned, required: false
../DemoPlugins/UnsignedRequired/ Unsigned, required: true

How It Works

  1. Framework is statically linked (DCC_UsePackage)
  2. OnValidateModule is set before LoadAll is called
  3. For each BPL the loader calls the hook -- on false:
    • Optional: Plugin is skipped, app continues
    • Required: Exception is raised, app shows error message
  4. TSecurityValidator.VerifyAuthenticode uses the Windows WinVerifyTrust API

plugins.json

{
  "plugins": [
    { "name": "SignedPlugin",      "file": "SignedPlugin",      "required": false },
    { "name": "UnsignedOptional",  "file": "UnsignedOptional",  "required": false },
    { "name": "UnsignedRequired",  "file": "UnsignedRequired",  "required": true  }
  ]
}

Limitations

  • Framework is loaded BEFORE the app: Since FMXPluginFramework is in DCC_UsePackage, the OS loader loads the framework BPL before the EXE even starts. A tampered framework would not be detected.
  • Only plugin BPLs are checked: The EXE and the framework itself are not validated.

The Authenticode check can be extended with hash-based checks using Plugin.Manifest (from Helpers/). TManifestValidator verifies SHA256 hashes against plugins.json and can be used directly as an OnValidateModule callback.

For pre-load validation of all BPLs, see SecureBootstrap.