In the past, AppLocker was available only for Windows Enterprise and Education subscribers. In this post, I will show you a way to use AppLocker on Windows 10 Pro and Windows 11 Pro.

AppLocker is a Group-Policy-based mechanism that allows you to control the applications that run on your PC. It is a core security feature.

Microsoft also lists other use cases, namely:

  • Application inventory
  • Licensing conformance
  • Software standardization

Unfortunately, Microsoft has decided to treat AppLocker as an enterprise benefit and has made it unavailable in the Home and Professional editions of Windows. However, ever since Microsoft has come up with Mobile Device Management (MDM) as a sort of Group Policy 2.0, its documentation now contains this claim:

You can use the AppLocker CSP to configure AppLocker policies on any edition of Windows 10 and Windows 11 supported by Mobile Device Management (MDM).

You might wonder which editions MDM supports—any edition, Microsoft has included MDM capabilities in all editions!

It did not take long until someone had a look at the internals and found out that not even MDM licenses were required to make it work. In fact, you only need to know how to script it.

Creating AppLocker rules ^

Sandy Zeng (Microsoft MVP) seems to be the first who published working scripts. However, Sandy did not go into detail about the syntax; she left us working examples, but she didn't explain how she put them together. This article fills this gap.

You will need Windows 10 Pro or Windows 11 Pro. Even though Windows 10 Home and Windows 11 Home allow applying these rules, there is no easy way to create these rules for the Window Home edition. Honestly, I don't think AppLocker is for the Home edition.

Note that all screenshots come from Windows 10 Pro. Things might look a bit different on Windows 11.

Disclaimer: If you are unaware, AppLocker is able to render the OS completely unusable when configured incorrectly. I recommend trying this on a virtual machine, which enables you to create and return to snapshots in case you lock yourself out.

First, open secpol.msc and navigate to Application control policies > AppLocker. Below that, you will see four sections containing governing rules for executables (.exe), Windows installer files (.msi and .msp), scripts (.ps1, .bat, .cmd, etc.), and packaged apps (modern apps from the Windows Store, including those preinstalled by Microsoft, such as the weather app, calculator, and Paint 3D).

If you were hoping Microsoft would let you use this built-in GUI, you would be mistaken. The GUI is for enterprise and education edition users only; using it on Pro does not enable AppLocker. Still, we will use it to create the scripts that will be used later to enable AppLocker on Windows 10 Pro and Windows 11 Pro.

We start by creating a rule for executables. To play it safe for these tests, let us first create the default rules. It is not the most secure configuration, but for this test, I recommend it. Right-click Executable Rules and select Create default rules. Three rules are created.

Now create a fourth rule that denies access to WordPad ("%ProgramFiles%\Windows NT\Accessories\wordpad.exe") for anyone.

Disallowing WordPad with AppLocker

Disallowing WordPad with AppLocker

Aren't rules 1 and 4 contradictory? Rule 4 will win since it is more specific than rule 1—that is how AppLocker works. WordPad will indeed be disallowed.

Next, we will open regedit and navigate to
HKEY_LOCAL_Machine\Software\Policies\Microsoft\Windows\SrpV2

Inside, open the Exe key. You should see something similar to this, just with different GUIDs:

Regedit showing EXE policies

Regedit showing EXE policies

There are four keys below the Exe key that correspond to our four rules; the Deny policy for WordPad is depicted. Now for the big aha: the data of the depicted registry value can be directly used in the syntax of our script. In other words, the AppLocker GUI uses the registry in a way that we don't need to convert or tamper with.

Okay, hold your horses for a moment, leave regedit open at that spot, open a text editor, and paste the following four lines:

<?xml version="1.0" encoding="utf-8" ?>
<RuleCollection Type="Exe" EnforcementMode="Enabled"> 

</RuleCollection>

Save that as C:\Applocker_on_Win10pro\exe.xml (later, we will use this path in PowerShell ISE). You will have noticed that blank line number 3. Fill it in with the contents of the Value entries of those four registry keys that complete exe.xml:

The EXE XML file

The EXE XML file

Now open powershell_ISE.exe as system account (!) using the following command on an elevated command prompt:

psexec -si powershell_ise

You can download psexec, which is a part of PsTools from Microsoft, and extract it to c:\windows.

In the ISE, paste the following code and save it as Create_Applocker_Exerule.ps1:

<#
.SYNOPSIS
    This function create new AppLocker settings using MDM WMI Bridge

.DESCRIPTION
    This script will create AppLocker settings for EXE

.NOTES
    File name: Create-AppLockerEXE.ps1
    VERSION: 2005a
    AUTHOR: Sandy Zeng
    Created:  2020-09-20
    Licensed under the MIT license.
    Please credit me if you find this script useful and do some cool things with it.

.VERSION HISTORY:
    1.0.0 - (2020-09-20) Script created
    1.0.1 - 
#>

$namespaceName = "root\cimv2\mdm\dmmap" #Do not change this
$className = "MDM_AppLocker_ApplicationLaunchRestrictions01_EXE03" #Do not change this
$GroupName = "AppLocker001" #You can use your own Groupname, don't use special characters or with space
$parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName"
$policyData = Get-Content C:\Applocker_on_Win10pro\exe.xml -raw
Add-Type -AssemblyName System.Web
$pdata = [System.Web.HttpUtility]::HtmlEncode($policyData);
New-CimInstance -Namespace $namespaceName -ClassName $className -Property @{ParentID=$parentID;InstanceID="EXE";EnforcementMode="Enabled";Policy=$pData}

Note that I modified Sandy's original script by sourcing out the XML policy content to an extra file, which I believe makes it easier to handle.

Now, launch the script right from ISE. It needs to be executed as a system account, and, of course, the execution policy needs to be set to at least remotesigned. Afterward, try to launch WordPad; it should be blocked.

WordPad is blocked by AppLocker

WordPad is blocked by AppLocker

Deploying AppLocker rules with Group Policy ^

Now, let me show you a way to deploy and maintain this with GPOs if you want to use this in your Windows 10 professional network.

The network deployment is simple:

  • Create a GPO with AppLocker settings the regular way, as you would for the Enterprise edition. That GPO will deploy the registry settings that we need to configure the rules in the second step.
  • Deploy a scheduled task that runs a PowerShell script to utilize the WMI MDM Bridge to apply these rules. The script for step 2 will be the following (save it as applocker.ps1). I will omit the credits for Sandy Zeng to save space here, but if you decide to utilize it, please give her credit by including the notes, as seen in the script above):
###The first code block deletes all existing rules so that new rules can be written.###

$namespaceName = "root\cimv2\mdm\dmmap"
$GroupName = "AppLocker001"

$className = "MDM_AppLocker_ApplicationLaunchRestrictions01_EXE03"
$parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName"
Get-CimInstance -Namespace $namespaceName -ClassName $className -Filter "ParentID=`'$parentID`' and InstanceID='EXE'"  | Remove-CimInstance

$className = "MDM_AppLocker_MSI03"
$parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName"
Get-CimInstance -Namespace $namespaceName -ClassName $className -Filter "ParentID=`'$parentID`' and InstanceID='Msi'"  | Remove-CimInstance

$className = "MDM_AppLocker_Script03"
$parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName"
Get-CimInstance -Namespace $namespaceName -ClassName $className -Filter "ParentID=`'$parentID`' and InstanceID='Script'"  | Remove-CimInstance

$className = "MDM_AppLocker_ApplicationLaunchRestrictions01_StoreApps03"
$parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName"
Get-CimInstance -Namespace $namespaceName -ClassName $className -Filter "ParentID=`'$parentID`' and InstanceID='StoreApps'"  | Remove-CimInstance

###This code block will retrieve all rules from the registry and write them to temporary XML files (one for each of the 4 Applocker sections) in c:\windows\temp###
 
echo '<RuleCollection Type="Exe" EnforcementMode="Enabled">' | out-file $env:temp\exe.xml -Encoding utf8 
$keys = (reg query hklm\Software\Policies\Microsoft\Windows\SrpV2\Exe | findstr HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SrpV2\Exe\)
foreach ($key in $keys) {(Get-ItemProperty -Path Registry::$key).Value | Out-file $env:temp\exe.xml -Encoding utf8 -Append} 
echo '</RuleCollection>'| Out-file $env:temp\exe.xml -Encoding utf8 -Append  

echo '<RuleCollection Type="Appx" EnforcementMode="Enabled">' | out-file $env:temp\StoreApps.xml -Encoding utf8 
$keys = (reg query hklm\Software\Policies\Microsoft\Windows\SrpV2\Appx | findstr HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SrpV2\Appx\)
foreach ($key in $keys) {(Get-ItemProperty -Path Registry::$key).Value | Out-file $env:temp\StoreApps.xml -Encoding utf8 -Append} 
echo '</RuleCollection>'| Out-file $env:temp\StoreApps.xml -Encoding utf8 -Append  

echo '<RuleCollection Type="Script" EnforcementMode="Enabled">' | out-file $env:temp\script.xml -Encoding utf8 
$keys = (reg query hklm\Software\Policies\Microsoft\Windows\SrpV2\Script | findstr HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SrpV2\Script\)
foreach ($key in $keys) {(Get-ItemProperty -Path Registry::$key).Value | Out-file $env:temp\script.xml -Encoding utf8 -Append} 
echo '</RuleCollection>'| Out-file $env:temp\script.xml -Encoding utf8 -Append  

echo '<RuleCollection Type="Msi" EnforcementMode="Enabled">' | out-file $env:temp\msi.xml -Encoding utf8 
$keys = (reg query hklm\Software\Policies\Microsoft\Windows\SrpV2\Msi | findstr HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\SrpV2\Msi\)
foreach ($key in $keys) {(Get-ItemProperty -Path Registry::$key).Value | Out-file $env:temp\msi.xml -Encoding utf8 -Append} 
echo '</RuleCollection>'| Out-file $env:temp\msi.xml -Encoding utf8 -Append

###This codeblock will apply all rules###

$namespaceName = "root\cimv2\mdm\dmmap"
$className = "MDM_AppLocker_ApplicationLaunchRestrictions01_EXE03"
$GroupName = "AppLocker001"
$parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName"
$policyData = Get-Content $env:temp\exe.xml -Raw
Add-Type -AssemblyName System.Web
$pdata = [System.Web.HttpUtility]::HtmlEncode($policyData);
New-CimInstance -Namespace $namespaceName -ClassName $className -Property @{ParentID=$parentID;InstanceID="EXE";EnforcementMode="Enabled";Policy=$pData}

$className = "MDM_AppLocker_ApplicationLaunchRestrictions01_StoreApps03"
$parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName"
$policyData = Get-Content $env:temp\StoreApps.xml -Raw
Add-Type -AssemblyName System.Web
$pdata = [System.Web.HttpUtility]::HtmlEncode($policyData);
New-CimInstance -Namespace $namespaceName -ClassName $className -Property @{ParentID=$parentID;InstanceID="StoreApps";EnforcementMode="Enabled";Policy=$pData}

$className = "MDM_AppLocker_Script03"
$parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName"
$policyData = Get-Content $env:temp\Script.xml -Raw
Add-Type -AssemblyName System.Web
$pdata = [System.Web.HttpUtility]::HtmlEncode($policyData);
New-CimInstance -Namespace $namespaceName -ClassName $className -Property @{ParentID=$parentID;InstanceID="Script";EnforcementMode="Enabled";Policy=$pData}

$className = "MDM_AppLocker_MSI03"
$parentID = "./Vendor/MSFT/AppLocker/ApplicationLaunchRestrictions/$GroupName"
$policyData = Get-Content $env:temp\msi.xml -Raw
Add-Type -AssemblyName System.Web
$pdata = [System.Web.HttpUtility]::HtmlEncode($policyData);
New-CimInstance -Namespace $namespaceName -ClassName $className -Property @{ParentID=$parentID;InstanceID="Msi";EnforcementMode="Enabled";Policy=$pData}

The scheduled task that you use for this needs system privileges, so the executing account needs to be "System." I suggest making it an immediate task ("Immediate Task (at least Windows 7") so that it applies to any GPO background refresh. This script executes very quickly, which means no significant performance overhead. If you have Win10/11 Pro, but no domain, you need to create the same task manually and use this event based task trigger ("on an event"), so that whenever you change Applocker Settings, my script runs:

Log: Microsoft-Windows-GroupPolicy/Operational, Source: GroupPolicy, Event ID: 4004

Conclusion ^

I provided a helper script that automates rule processing to enable deploying AppLocker on Windows 10 Professional and Windows 11 Professional.

avatar
27 Comments
  1. Abhku 5 months ago

    —————————————————————————————————————-
    New-CimInstance : The requested object could not be found.
    At line:28 char:1
    + New-CimInstance -Namespace $namespaceName -ClassName $className -Prop …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (MDM_AppLocker_A…ictions01_EXE03:CimInstance) [New-CimInstance], CimException
    + FullyQualifiedErrorId : MI RESULT 6,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand

    • Author
      Welf Alberts 5 months ago

      Hi Abhku.

      The error message proves that you have modified my script, since line 28 is empty, normally. Please use my script and see if it works unmodified. It it does, tell me what you are trying to change or let me look at your modified script.

  2. bunglegrind 5 months ago

    Please be aware of this issue:

    https://github.com/MicrosoftDocs/windows-itpro-docs/issues/6813

    I mean, adding rules for scripts it’s a matter of trial and error…
    Do you know any workaround?

  3. Author
    Welf Alberts 5 months ago

    @bundlegrind
    What do you need a workaround for? Please be specific.
    What you link shows that logging is not working as expected, still blocking works as expected.

  4. bunglegrind 5 months ago

    I mean, the audit mode is useless if I can’t see what is blocked and what not. And tuning becomes a very difficult task

    • Author
      Welf Alberts 5 months ago

      Agreed. I will look at audit mode logging soon and share feedback.

    • Author
      Welf Alberts 5 months ago

      @bunglegrind
      You are right, this MDM implementation has issues.
      If I take my script and change all 8 occurences of EnforcementMode=”Enabled” to EnforcementMode=”AuditOnly”, it works as expected (things run), but ONLY FOR EXE, the audit log is used, not for MSI or scripts. That is strange. Will need to investigate further.

      When I tested logging, I must admit that I did only .exe, assuming the rest would work as well (why shouldn’t it)…

  5. bunglegrind 5 months ago

    Thanks a lot!

    • Author
      Welf Alberts 4 months ago

      I found out what this is about.
      Although MS claims “all editions support this”, the logging only works for exe and appx since only those use SRPv2 (=Applocker) blocking, the rest still uses SRPv1 (Software restriction policies).. But there is a way to do logging for the rest:

      Just create the following Reg_SZ entry “LogfileName”at HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers
      with a value like c:\log\mylog.txt
      That log will be populated with entries for ALL types, example entries:

      cmd.exe (PID = 6852) identified C:\Users\a\test\test.bat as Disallowed using SRPv2 rule, Guid = {c71b5435-1293-4848-b0a3-b53066c76ca2}
      msiexec.exe (PID = 1496) identified C:\Users\a\Desktop\ISORecorder31x64.msi as Disallowed using SRPv2 rule, Guid = {c71b5435-1293-4848-b0a3-b53066c76ca2}

      So this interesting log shows the GUIDs of the rules, which it correctly identifies as applocker (=SRPv2) rules, but the GUIDs… where does it find those? No idea.
      And what if we want to do audit logging and receive these “would have been blocked” messages? Nope, can’t be done for MSI or script… in auditing mode, that SRP logfile would read
      msiexec.exe (PID = 9024) identified C:\Users\a\Desktop\ISORecorder31x64.msi as Unrestricted using SRPv2 rule, Guid = {c71b5435-1293-4848-b0a3-b53066c76ca2}

      Conclusion: not 100% the same when it comes to logging, only when it comes to blocking 😐

  6. bunglegrind 4 months ago

    Thank you very much for your effort. I’ve enabled the log file and it works!

    cheers

  7. bunglegrind 4 months ago

    Concerning the DLL rules (MDM_AppLocker_DLL03) it looks like it’s working correctly (your script doesn’t provide the DLL feature, but it could be easily extended). I’m running the DLL rules in audit mode, and logs are correctly showed in events manager.

  8. Sabine 3 months ago

    I wanted to use Applocker on my standalone Win-10-Laptop.
    When I run the ps1-file, I get this error message:

    PS C:\Windows\system32> C:\Windows\PSTools\Create_Applocker_Exerule.ps1
    New-CimInstance : The operation cannot be performed because an object already exists.
    In C:\Windows\PSTools\Create_Applocker_Exerule.ps1:28 Characters: 1
    + New-CimInstance -Namespace $namespaceName -ClassName $className -Prop …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ResourceExists: (MDM_AppLocker_A…ictions01_EXE03:CimInstance) [New-CimInstance], CimExcepti
    on
    + FullyQualifiedErrorId : MI RESULT 11,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand

  9. Author
    Welf Alberts 3 months ago

    Sabine, please use the script “as is” for a start. It will not throw an error. If you modify it, you need to share it in order to get help.

  10. George 3 months ago

    I tried to apply this powershell code, but then same issue happens:

    PS C:\Windows\system32> C:\Applocker_on_Win10pro\Create_Applocker_Exerule.ps1
    New-CimInstance : The requested object could not be found.
    Location C:\Applocker_on_Win10pro\Create_Applocker_Exerule.ps1:24 char:1
    + New-CimInstance -Namespace $namespaceName -ClassName $className -Prop …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (MDM_AppLocker_A…icationLaun…):CimInstance) [New-CimInstance], CimException
    + FullyQualifiedErrorId : MI RESULT 6,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand

    I’d exactly done same thing presented in this article: with same file names, same directory, and same procedure. I’d appreciate it if you could take a look at what the problem is. Thank you!

    • Author
      Welf Alberts 3 months ago

      George and others with this error: If I remember correctly, this error occurs, if you start the script as admin. You must start it as system account via psexec, as outlined.

      • George 3 months ago

        Thank you for answering! I’d checked it with whoami script after the script in admin powershell: psexec -si powershell_ise, and the result was:

        PS C:\Windows\system32> whoami
        nt authority\system

        So this must be a system account, I think. Is there any additional procedure I must do?

      • George 3 months ago

        https://youtu.be/DZo5s-yCYDo

        Thank you for answering! I’d recorded the whole procedure. I executed the script .\psexec.exe -si powershell_ise, and whoami command showed the result nt authority\system. This means that I’m in system account, isn’t it…?

  11. bunglegrind 3 months ago

    I guess:

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

    • Sabine 3 months ago

      Hi, my problem remains. ExecutionPolicy ist RemoteSigned, I am on system account, still I get this:
      [img]https://up.picr.de/44303293tb.jpg[/img]

  12. Sabine 3 months ago

    I did exactly the same as George.

  13. Author
    Welf Alberts 3 months ago

    Ok, Sabine, George: Watched the video, all looks good except for the backslash in the paths which is a chinese sign for you, George – not sure if that might bother PowerShell, but I cannot tell for sure. What OS build do you use?

  14. Author
    Welf Alberts 3 months ago

    Saw Sabines Screenshot and that’s something different to Georges’s problem. Use the delete_all_rules part (lines 3-20) in the lowest code, then retry.

    • George 3 months ago

      https://imgur.com/a/FxrFVIx

      Thank you for reviewing! That backslash \ is replaced to ₩ just because this windows is korean version, which have ₩ in keyboard instead of \. All korean os builds use ₩ in representing its directory, so I think that won’t bother much.
      My window version is Window 10 pro, version 21H2(build 19044.1889). I also checked out Set-ExecutionPolicy -ExecutionPolicy RemoteSigned, and the same error occured.

    • George 3 months ago

      Actually I reinstalled windows 10 pro and it worked! This error might be related to some optimization and tweaks that I did in the start. I’ll remind here if I can find which tweak is related with this issue. Thank you!

  15. Author
    Welf Alberts 3 months ago

    Fine, thanks for the feedback!

  16. Sabine 3 months ago

    Hi, my screenshot was cut off because the error message was at the bottom. I had copied the code for Create_Applocker_Exerule.ps1 1:1 from your script.

    Interestingly, I had tried it on my old Win10Pro-Laptop, and there it was executed one time and WordPad is now blocked. Later I tried to run it for a second time there, but then it gave the same error message as on the other laptop. The other laptop has a newly installed Windows 10 Pro.
    Here’s s the script:
    [img]https://up.picr.de/44305578qj.jpg[/img]

    • Author
      Welf Alberts 3 months ago

      Sabine, the proof of concept is not meant for repeated runs. You have not reacted to my suggestion before, which told you what lines to execute now to overcome this.

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2022

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account