Digitally signing my Toast Notification Script to use with ConfigMgr, AppLocker and Constrained Language Mode

Introduction

My Toast Notification Script unfortunately only works in PowerShell Full Language Mode (for the time being. I have plans to look into this).

This requirement does not work well with AppLocker and having Constrained Language Mode enabled. My solution to this, is to digitally sign the New-ToastNotification.ps1 file. While working my way through the process myself, I realized that a few changes to the Toast Notification Script itself was needed.

The changes made to this “edition” of the script, are only targeted  Configuration Manager. I’m not sure that moving between PowerShell Language Modes coming from Proactive Remediations in Intune, is something that’s possible (if anyone knows this, please let me know).

Additionally to the changes needed, I thought the process itself would make a decent and useful blog post. So here goes. 🙂

AppLocker

Fast-forwarding past all of the setup of AppLocker and verifying things are working, you will start noticing, that some of your scripts which used to work, no longer work as intended.

With the broken functionality comes following entries in the AppLocker event log: Microsoft-Windows-AppLocker/MSI and Script

  • %OSDRIVE%\USERS\MAB\APPDATA\LOCAL\TEMP\__PSSCRIPTPOLICYTEST_PWABLEXA.45H.PSM1 was prevented from running.
  • %OSDRIVE%\USERS\MAB\APPDATA\LOCAL\TEMP\__PSSCRIPTPOLICYTEST_WN0403TR.GPB.PS1 was prevented from running.

Constrained Language

Then you realize, that PowerShell is operating in what’s called Constrained Language Mode, and therefore have reduced functionality, which is the reason for the Toast Notification Script is no longer working.

You can verify the current language mode by running: $ExecutionContext.SessionState.LanguageMode

Below is an illustration of the broken functionality, when running the New-ToastNotification.ps1 file directly on a system, where AppLocker is configured and Constrained Language Mode enabled:

Certificate Authority

The solution to this, is to digitally sign the New-ToastNotification.ps1 file.

There are 2 routes to accomplish this: 1) buy a code signing certificate from a public vendor 2) issue your own code signing certificate from an internal CA.

I chose the latter, and created a code signing template on our internal CA server and issued the template, making it available for certificate requests.

I will not go into details on the CA portion, but for your convenience, find a few snippets of the template and certificate I created below.

Certificate Template:

Certificate Enrollment:

Final Certificate:

PowerShell Code Signing

Sign the New-ToastNotification.ps1 file using PowerShell similar to below:

$cert = Get-ChildItem -Path Cert:\CurrentUser\My –CodeSigningCert
Set-AuthenticodeSignature -Certificate $cert -FilePath "C:\Temp\ToastNotificationScript\New-ToastNotification.ps1"

The result will be an added signature block, in the very end of the New-ToastNotification.ps1 file:

AppLocker whitelisting

Regardless of how you prefer to manage your AppLocker rules, you will need to whitelist the publisher, matching that of your newly issued code signing certificate.

Below is an illustration when this is done via Group Policy:

Toast Notification Script

What really changed in this “edition”, is the addition of a new function: Terminate-ToastProcess.

Long story short is, that calling the New-ToastNotification.ps1 file (which requires Full Language Mode) from a Constrained Language Mode session, requires dot-sourcing in order to protect the boundary between the two sessions.

Otherwise running the script will return following error:

Cannot dot-source this command because it was defined in a different language mode. To invoke this command without importing its contents, omit the '.' operator.

Now, this part was indeed tricky and the only real solution to the problem, was to call powershell.exe with the parameter -noexit:

  • powershell.exe -ExecutionPolicy RemoteSigned -Noexit .\New-ToastNotification.ps1 -Config “https://krpublicfiles.blob.core.windows.net/toastnotification/config-toast-rebootpending.xml”

-Noexit also means that powershell.exe, when run from ConfigMgr, will run indefinitely. To counter this part, I created the mentioned function, which terminates the parent powershell.exe process gracefully with exit code 0 (to satisfy the program in ConfigMgr).

Configuration Manager

Using this edition of the script is similar to the current official version.

Create a package containing the New-ToastNotification.ps1 file, distribute to your distribution points, and create a program running the script similar to this:

  • powershell.exe -ExecutionPolicy RemoteSigned -Noexit .\New-ToastNotification.ps1 -Config “https://krpublicfiles.blob.core.windows.net/toastnotification/config-toast-runpackageid.xml”

GitHub

Find the New-ToastNotification-AppLocker-Edition.ps1 on my GitHub repository: Toast-Notification-Script/New-ToastNotification-AppLocker-Edition.ps1 at master · imabdk/Toast-Notification-Script (github.com)

ENJOY 🙂

6 thoughts on “Digitally signing my Toast Notification Script to use with ConfigMgr, AppLocker and Constrained Language Mode”

  1. we are using your script for toast notifications, but have seem issues where the notification will not “pop up”, but after a reboot (possible a logoff/logon too) that they show up in the notifications list. thoughts?

    Reply
    • Do you have focus assist enabled? Can you try and set the scenario option in the config.xml to alarm instead of reminder. Setting it to alarm, basically bypasses focus assist. Also, are you using your own custom app for doing the notification? See version 2.3.0. Let me know how you proceed.

      Reply
  2. Hey Martin!
    We was gonna use it now, we have applocker and I signed the .ps1 file and it run, but after clicking install it did not start the feature update from software center.

    Then I looked at the applocker logs and it prevented the .cmd script to run.

    %OSDRIVE%\USERS\ANWT\APPDATA\ROAMING\TOASTNOTIFICATIONSCRIPT\SCRIPTS\TOASTRUNUPDATEID.CMD was prevented from running.

    Am I doing something wrong or is this problem for everybody with applocker scripting rules enabled?

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.