Does BlockExecution work with AppLocker/ConstrainedLanguageMode?

I was experimenting with adding -BlockExecution to the installation welcome dialog, which semi-works.
It blocks the process from launching, but the message dialog doesn’t appear for me.

What I find is if I configure the Toolkit_TempPath inside AppDeployToolkitConfig.xml to store the temp files in a location that our AppLocker policies will allow scripts to run from, I see the event log entries written indicating the scripts launched, but because AppLocker is active, powershell uses constrained language mode which prevents the nested script from dot-sourcing.
I’ve tried signing the .PS1s associated (deploy-application, AppDeployToolkitMain, etc) to no avail. For this experiment, in an elevated account, I’ve dot-sourced AppDeployToolkitMain.ps1 and simply set:

Block-AppExecution -ProcessName notepad

Once that completes processing and sets the IFEO regkeys I can no longer launch notepad, but I don’t see any message. If I pick apart what the debugger is that the IFEO keys use, I can emulate it as below:

It’s running from an approved location, so I don’t really understand how I can get the benefit from using the BlockExecution switch and am starting to suspect this just won’t work with AppLocker or within ConstrainedLanguageMode?

My experience with AppLocker is that it let you run full language PowerShell scripts if you launch PSADT elevated.

How are you launching PSADT?

If you launch PSADT in lets say Intune, you’ll need systemUI.exe to make dialogs show.

It’s not the PSADT deployment that’s the problem, it’s the way that using -BlockAppExecution sets itself up as a nested script that is launched when the blocked app is invoked by the user - this all happens in the users context and is subject to the IFEO registry key (which is just acting as a debugger - clever idea, that!), and therefore the applocker aspects come into play.

Without Block-AppExecution, it works perfectly, but then we get our muppets re-launching Outlook straight after PSADT kills it off and that might be whats damaging a small percentage of our installs.

In our deployments via SCCM (with UI interaction enabled) and Intune, we’re wrapping PSADT up using ServiceUI.exe so we can interact with RDP sessions/WindowStations, but this is all exected in the system context.

I think I understand.

Many of the Show-* command like Show-InstallationWelcome respawns (create another instance of) PSADT.
In your case (as per your screenshot), it copies files to C:\Program Files\PSADT and launches in the User context (Not sure about that part) to make it visible.

AppLocker will complain and block that new instance if C:\Program Files\PSADT only allows Constrained Language PS1. (For other readers: Constrained Language means no .Net stuff, etc) But PSADT is full of Full Language stuff so you get your error.

My current environment doesn’t have AppLocker enabled but my previous environment did. We had Show- commands working just fine without signing the PSADT PS1 files. We just had directories like C:\Program Files and its subfolders able to run Full Language PS1s. It was secure because Users could not write there.

Try creating a simple Full Language PS1 file in C:\Program Files\PSADT and see if the user can launch it.

TL;DR: Check your AppLocker config. Make sure C:\Program Files and its subfolders are allowed to Full Language PS1 files to run as user.

Thanks for that. I’ve created a simple script in C:\Program Files\PSADT\Dummy.ps1 that simply has the code:

[System.Console]::WriteLine("Hello")
new-object System.Net.WebClient

  • I can execute this perfectly, but I cannot dot-source it. In hindsight, I’m not sure if that’s a good enough experiment…
  • We’ve also got the default applocker script rule that whitelists %PROGRAMFILES%\*.

What I’m learning is the language mode isn’t defined by the .PS1 content but instead by whether or not PowerShell was able to execute %TMP%\__PSSCRIPTPOLICYTEST_*.*.PS1 during its startup. That is what determines the language mode powershell uses, at least, according to PowerShell Constrained Language Mode - PowerShell Team

Alternatively, it appears one can mangle where %tmp% is just prior to launching a powershell, as described here: %Temp%orary Constrained Language mode in AppLocker – Oddvar Moe's Blog - that’s a little spooky, but might be useful at some point later on…

I’ve also experimented and added to our applocker script rules the allow setting:

%OSDRIVE%\Users\*\AppData\Local\Temp\__PSSCRIPTPOLICYTEST_*.*.PS1

With this in place, the PSADT blocked message appears as expected!
Unfortunately, I’m not really comfortable with all scripts running with full language mode but I can’t see any pragmatic compromise.

  • Perhaps did you have the psscriptpolicytest file scheme added into your applocker script path rules in your old environment? (I can’t see how else it would’ve worked, to be honest)
  • I’ve just stumbled across session configuration files and that may be something to look into, but at this stage, I’m exhausted with it all :slight_smile:

I found this ( Cannot dot-source this command because it was defined in a different language mode. - Microsoft Community Hub)
It seems it might to be related to WDAC or GPOs or 22H2.

Then I found this
PowerShell Constrained Language mode and the Dot-Source Operator - PowerShell Team (microsoft.com)
and It talks about WDAC, too.

Thanks!

I’ve tried Get-WDACInfo.ps1 from https://techcommunity.microsoft.com/t5/windows-powershell/cannot-dot-source-this-command-because-it-was-defined-in-a/m-p/3642722 and that’s confirmed that there’s no WDAC in play, just our Applocker rules.

  • I’ve confirmed if I whitelist %OSDRIVE%\Users\*\AppData\Local\Temp\__PSSCRIPTPOLICYTEST_*.*.PS1, the blocked dialogs work perfectly.
  • If I remove the above rule & put applocker into audit mode, of course it works perfectly (logging the warnings that these would be blocked).

I just can’t see how this is compatible with ConstrainedLanguage mode.

While I wasn’t the one who setup AppLocker at my previous job, I don’t understand how a test in a user’s profile dictates the language mode to be used in C:\Program Files\PSADT

Did you at least change Toolkit_TempPath in AppDeployToolkitConfig.xml to <Toolkit_TempPath>$envProgramFiles</Toolkit_TempPath> ?

Hi again,

Yes, the XML was altered to use C:\Program Files\PSADT for <Toolkit_TempPath>.

It’s because it’s a PowerShell engine thing - if it detects applocker or WDAC policies in place then the entire runtime or API set is restricted to ConstrainedLanguage mode (and not a bad idea, there’s plenty of malware out there that’s exploiting powershell’s abilities…). That the target script file is in program files is irrelevant, sadly.

It’s kinda a shame that -ExecutionPolicy has no bearing on this but I understand why now.

I suppose I could mangle the AppDeployToolkitMain.ps1 so the .VBS wrapper it uses handles the actual messagebox instead of calling the main .PS1 script again with -ShowBlockedAppDialog -AsyncToolkitLaunch (and the rest of the parameters it uses). I think we’ll just avoid Block-AppExection entirely, I’m trying to avoid too much proprietary code.