Microsoft Workplace Community Blog

Font size: +
7 minutes reading time (1337 words)
Featured

Windows Defender Application control - Part 2

In part 1 of my blog, I explained step by step how to get started with application control in a simple way. In this part of my blog, I'm going to discuss how to use the company portal in Intune as a managed installer. The benefit of this is that you don't have to adjust the application control policies every time. There is one limitation though, that is only .EXE files can be installed, .MSI files are not supported.

The managed installer works as follows. When an application (.EXE) is downloaded and/or installed from the company portal, these files are tagged. The "tag" uses an NTFS feature called extended attributes to store that data. The managed installer is an implementation mix of Microsoft AppLocker settings & Windows Defender Application Control.

Read about the managed installer .EXE only: Allow apps deployed with a WDAC managed installer (Windows)

Application Microsoft Defender Application Control (WDAC)
Weblink
Microsoft Endpoint Manager admin center
Topic
Windows Defender Application Control - Intune

In this blog

After reading all the Microsoft documentation, I came across an article that it was possible to use managed installers. Unfortunately, the documentation is not very detailed and I had to rely on the Internet to figure it out myself. I even read on a blog that managed installer only works in conjunction with SCCM. So this is not the case, otherwise I would not write this blog.

WDAC Policy - Configure Policy Template Windows Defender Application Control Wizard
Powershell Script - Managed installer
Local Machine PowerShell
Intune Configuration - Intune PowerShellLocal Machine PowerShell
Upload Powershell to Intune
Microsoft Endpoint Manager admin center
Windows Event Log - Application Control eventsLocal Machine

Managed Installer with Intune

WDAC Policy - Disable Script Enforcement
Windows Defender Application control - App

Since Constrained Language is so limited the script I use to set everything up for the managed installer is blocked. The solution to this is simple: add these scripts (or better, your code signing authority that signed them) to your application control policy. This will allow your approved scripts to run in Full Language mode.

Below is the describe from the Microsoft website.

This option disables script enforcement options. Unsigned PowerShell scripts and interactive PowerShell are no longer restricted to Constrained Language Mode. NOTE: This option is required to run HTA files, and is only supported with the Windows 10 May 2019 Update (1903) and higher. Using it on earlier versions of Windows 10 is not supported and may have unintended results.


WDAC Policy - Managed installer
Windows Defender Application control - App

This option needs little explanation. Without turning this option on, the managed installer will not work.

Below is the describe from the Microsoft website.

Use this option to automatically allow applications installed by a software distribution solution, such as Microsoft Endpoint Configuration Manager, that has been defined as a managed installer.


Powershell Script - Managed installer
Local Machine PowerShell

The following components are integrated in this script.

  1. Line two has a "true "or False statement in it. On False the whole script will run and on True it will only check if the managed installer is compliant.
  2. Between lines 20 and 65 is the AppLocker managed installer configuration policy.
  3. The two services that need to be started can be found on lines 146 and 147

Information from the Microsoft Website: Allow apps deployed with a WDAC managed installer (Windows)

param (
    [switch] $CheckComplianceOnly = $False
	)

# Variables
[System.Int32]$policyBinaryTimeoutSeconds = 300
[System.Int32]$waitBatchSeconds = 5
[System.Int32]$maxWaitSeconds = 300

[string]$miPolicyBinaryPathRoot = "$env:windir\System32"

if(-not ([Environment]::Is64BitProcess))
{
    $miPolicyBinaryPathRoot = "$env:windir\Sysnative"
}

[string]$miPolicyBinaryPath = Join-Path -Path $miPolicyBinaryPathRoot -ChildPath "AppLocker\ManagedInstaller.AppLocker"

[string]$SccmMiPolicy = 
@"
<AppLockerPolicy Version="1">
    <RuleCollection Type="Appx" EnforcementMode="NotConfigured" />
    <RuleCollection Type="Dll" EnforcementMode="AuditOnly">
        <FilePathRule Id="86f235ad-3f7b-4121-bc95-ea8bde3a5db5" Name="Dummy Rule" Description="Dummy Rule" UserOrGroupSid="S-1-1-0" Action="Deny">
            <Conditions>
                <FilePathCondition Path="%OSDRIVE%\ThisWillBeBlocked.dll" />
            </Conditions>
        </FilePathRule>
        <RuleCollectionExtensions>
            <ThresholdExtensions>
                <Services EnforcementMode="Enabled" />
            </ThresholdExtensions>
            <RedstoneExtensions>
                <SystemApps Allow="Enabled" />
            </RedstoneExtensions>
        </RuleCollectionExtensions>
    </RuleCollection>
    <RuleCollection Type="Exe" EnforcementMode="AuditOnly">
        <FilePathRule Id="9420c496-046d-45ab-bd0e-455b2649e41e" Name="Dummy Rule" Description="Dummy Rule" UserOrGroupSid="S-1-1-0" Action="Deny">
            <Conditions>
                <FilePathCondition Path="%OSDRIVE%\ThisWillBeBlocked.exe" />
            </Conditions>
        </FilePathRule>
        <RuleCollectionExtensions>
            <ThresholdExtensions>
                <Services EnforcementMode="Enabled" />
            </ThresholdExtensions>
            <RedstoneExtensions>
                <SystemApps Allow="Enabled" />
            </RedstoneExtensions>
        </RuleCollectionExtensions>
    </RuleCollection>
    <RuleCollection Type="ManagedInstaller" EnforcementMode="Enabled">
       <FilePublisherRule Id="70104ed1-5589-4f29-bb46-2692a86ec089" Name="MICROSOFT.MANAGEMENT.SERVICES.INTUNEWINDOWSAGENT.EXE version 1.39.200.2 or greater in MICROSOFT® INTUNE™ from O=MICROSOFT CORPORATION, L=REDMOND, S=WASHINGTON, C=US" Description="" UserOrGroupSid="S-1-1-0" Action="Allow">
            <Conditions>
                <FilePublisherCondition PublisherName="O=MICROSOFT CORPORATION, L=REDMOND, S=WASHINGTON, C=US" ProductName="MICROSOFT® INTUNE™" BinaryName="MICROSOFT.MANAGEMENT.SERVICES.INTUNEWINDOWSAGENT.EXE">
                    <BinaryVersionRange LowSection="1.38.300.1" HighSection="*" />
                </FilePublisherCondition>
            </Conditions>
        </FilePublisherRule>
    </RuleCollection>
    <RuleCollection Type="Msi" EnforcementMode="NotConfigured" />
    <RuleCollection Type="Script" EnforcementMode="NotConfigured" />
</AppLockerPolicy>
"@

function MergeAppLockerPolicy([string]$policyXml)
{
    $policyFile = '.\AppLockerPolicy.xml'
    $policyXml | Out-File $policyFile

    Write-Host "Merging and setting AppLocker policy"

    Set-AppLockerPolicy -XmlPolicy $policyFile -Merge -ErrorAction SilentlyContinue

    Remove-Item $policyFile
}

function VerifyCompliance([xml]$policy)
{
    $result = $false
    $miNode = $policy.AppLockerPolicy.ChildNodes | Where-Object{$_.Type -eq 'ManagedInstaller'}

    if(-not $miNode)
    {
        Write-Host('Policy does not contain any managed installers')
    }
    else
    {
        $ccmexecNode = $miNode.ChildNodes | Where-Object{($_.LocalName -eq 'FilePublisherRule') -and ($_.Name -eq 'MICROSOFT.MANAGEMENT.SERVICES.INTUNEWINDOWSAGENT.EXE version 1.39.200.2 or greater in MICROSOFT® INTUNE™ from O=MICROSOFT CORPORATION, L=REDMOND, S=WASHINGTON, C=US')}

        if(-not $ccmexecNode)
        {
            Write-Host('Policy does not have Intune managed installer policy.')
        }
        else
        { 
            {
                $result = $true
            }
        }
    }

    return $result
}

# Execution flow starts here
# Get and load the current effective AppLocker policy
try
{
    [xml]$effectivePolicyXml = Get-AppLockerPolicy -Effective -Xml -ErrorVariable ev -ErrorAction SilentlyContinue
}
catch 
{ 
    Write-Error('Get-AppLockerPolicy failed. ' + $_.Exception.Message)
    exit 10
}

# Check if it contains MI policy and if the MI policy has rules for Intune
try
{
    $compliant = VerifyCompliance($effectivePolicyXml)
}
catch
{
    Write-Error('Failed to verify AppLocker policy compliance. ' + $_.Exception.Message)
    exit 12
}

if($compliant)
{
    Write-Host("AppLocker policy is compliant")
    exit 0
}

Write-Host("AppLocker policy is not compliant")

if($CheckComplianceOnly)
{
    exit 2
}

# Start services
Write-Host 'Starting services'

[Diagnostics.Process]::Start("$env:windir\System32\sc.exe","start gpsvc")
[Diagnostics.Process]::Start("$env:windir\System32\appidtel.exe","start -mionly")

[System.Int32]$waitedSeconds = 0

# Check service state, wait up to 1 minute
while($waitedSeconds -lt $maxWaitSeconds)
{
    Start-Sleep -Seconds $waitBatchSeconds
    $waitedSeconds += $waitBatchSeconds

    if(-not ((Get-Service AppIDSvc).Status -eq 'Running'))
    {
        Write-Host 'AppID Service is not fully started yet.'
        continue
    }

    if(-not ((Get-Service appid).Status -eq 'Running'))
    {
        Write-Host 'AppId Driver Service is not fully started yet.'
        continue
    }

    if(-not ((Get-Service applockerfltr).Status -eq 'Running'))
    {
        Write-Host 'AppLocker Filter Driver Service is not fully started yet.'
        continue
    }

    break
}

if (-not ($waitedSeconds -lt $maxWaitSeconds))
{
    Write-Error 'Time-out on waiting for services to start.'
    exit 1
}

# Set the policy
try
{
    MergeAppLockerPolicy($SccmMiPolicy)
}
catch
{
    Write-Error('Failed to merge AppLocker policy. ' + $_.Exception.Message)
    exit 14
}

# Wait for policy update
if(test-path $miPolicyBinaryPath)
{
	$previousPolicyBinaryTimeStamp = (Get-ChildItem $miPolicyBinaryPath).LastWriteTime
	Write-Host ('There is an existing ManagedInstaller policy binary (LastWriteTime: {0})' -f $previousPolicyBinaryTimeStamp.ToString('yyyy-MM-dd 
HH:mm'))
}

if($previousPolicyBinaryTimeStamp)
{
	$action = 'updated'
	$condition = '$previousPolicyBinaryTimeStamp -lt (Get-ChildItem $miPolicyBinaryPath).LastWriteTime'
}
else
{
	$action = 'created'
	$condition = 'test-path $miPolicyBinaryPath'
}

Write-Host "Waiting for policy binary to be $action"

$startTime = get-date

while(-not (Invoke-Expression $condition))
{
	Start-Sleep -Seconds $waitBatchSeconds

	if((new-timespan $startTime $(get-date)).TotalSeconds -ge $policyBinaryTimeoutSeconds)
	{ 
		Write-Error "Policy binary has not been $action within $policyBinaryTimeoutSeconds seconds"
	    exit 1
	}
}

Write-Host ('Policy binary was created after {0:mm} minutes {0:ss} seconds' -f (new-timespan $startTime $(get-date)))

# Check compliance again
try
{
    [xml]$effectivePolicyXml = Get-AppLockerPolicy -Effective -Xml -ErrorVariable ev -ErrorAction SilentlyContinue
}
catch 
{ 
    Write-Error('Get-AppLockerPolicy failed. ' + $_.Exception.Message)
    exit 10
}

# Check if it contains MI policy and if the MI policy has rules for Intune
try
{
    $compliant = VerifyCompliance($effectivePolicyXml)
}
catch
{
    Write-Error('Failed to verify AppLocker policy compliance. ' + $_.Exception.Message)
    exit 12
}

if($compliant -eq $false)
{
    Write-Error("AppLocker policy is not compliant")
    exit 1
}

Write-Host 'AppLocker with Managed Installer for Intune successfully enabled' 

Managed Installer with Intune - Create Policy

Intune Configuration - Intune PowerShell
PowerShell

Following the steps below you can add this PowerShell script to Intune

  1. Login to Microsoft endpoint Manager and create an "PowerShell scripts"
  2. Upload PowerShell script. And leave all other options on "No" see image if necessary
  3. Important! Application control works immediately if it is included in the policy. In order for the managed installer to work, a full reboot of the device is required after the script is executed!

Information from the Microsoft Website: Allow apps deployed with a WDAC managed installer (Windows)


Windows Event Log - Application Control events
Events

I recommend activating the following event logs if not already done. For the managed installer, event log 3090 is of interest

  1. reg add hklm\system\currentcontrolset\control\ci -v TestFlags -t REG_DWORD -d 0x100
  2. reg add hklm\system\currentcontrolset\control\ci -v TestFlags -t REG_DWORD -d 0x300

For all information about the logs, I refer you to Microsoft: Understanding Application Control event IDs (Windows)


See how it Looks

×
Stay Informed

When you subscribe to the blog, we will send you an e-mail when there are new updates on the site so you wouldn't miss them.

Windows Defender Application control - Part 1

Related Posts

 

Comments (2)

Rated 0 out of 5 based on 0 voters
This comment was minimized by the moderator on the site

So you say it does not only work in conjunction with sccm, but does this only work in an on-premise or hybrid environment? The script you provided gets stuck for me at "Write-Host "Waiting for policy binary to be created" and times out after the...

So you say it does not only work in conjunction with sccm, but does this only work in an on-premise or hybrid environment? The script you provided gets stuck for me at "Write-Host "Waiting for policy binary to be created" and times out after the set 300 seconds.

Nothing ever gets created in Windows\System32\AppLocker\ManagedInstaller.AppLocker

Just using Set-AppLockerPolicy -XmlPolicy does nothing. It'll be mirrored back in Get-AppLockerPolicy -Effective -Xml, but it doesn't actually do anything on the machine. The documentation for that cmdlet says "Note that the Set-AppLockerPolicy cmdlet only works with GP. It cannot interact with the AppLocker CSP." Pushing it via powershell isn't necessarily using the CSP, but it's also not GP.

Read More
andrew
This comment was minimized by the moderator on the site

This technique works for SCCM as well as with Intune. I recommend you to read part 1 of the blog first, because using only this script you will not get the desired result. You still need to create the configuration and apply it to the clients.

Leon Boehlee
There are no comments posted here yet

Leave your comments

  1. Posting comment as a guest.
Rate this post:
0 Characters
Attachments (0 / 3)
Share Your Location