Levelling up Windows Defender

Enhancing detection and blocking capabilities with the default Windows anti-virus.


Windows Defender is commonplace in smaller organisations without AV centralisation, or those that may not wish to purchase enterprise AV subscriptions. However, what is not commonplace is moving beyond the default configuration to provide enhanced protection for endpoints.

Microsoft provides a variety of configuration options via Group Policy, InTune, PowerShell or SCCM which enhance Defender’s detection capabilities; pushing Defender to the forefront of modern threat detection. This article serves to summarise information provided through Microsoft’s latest security baseline for Windows 10 and Windows Server 2016, along with collating information from other security professionals and official Microsoft documentation in an easily digestible format.

We will cover delivering cloud protection, enhancing cloud-based protection, blocking potentially unwanted programs, and will take a look at Defender’s attack surface reduction rules. This post will cover Group Policy-based deployment, as well as the available PowerShell commandlets, though as mentioned above, InTune and SCCM deployments are available.

Enable and enhance cloud-based protection

Windows Defender’s cloud-based protection “uses distributed resources and machine learning to deliver protection to your endpoints at a rate that is far faster than traditional Security intelligence updates“. This ensures that endpoints take advantage of stronger protection in addition to standard real-time protection.

Group Policy

As with all enhancements discussed herein, Group Policy can be configured to enable/enhance cloud protection. This is achieved through the following path – Computer configuration -> Administrative templates -> Windows Components -> Windows Defender Antivirus -> MAPS.

The “Join Microsoft MAPS” setting should be configured as Enabled with either Basic or Advanced membership (the distinction does not matter on Windows 10 systems). The “Send file samples when further analysis is required” setting should be set to either Send safe samples or Send all samples, depending on your individual requirements.

In summary, the MAPS settings should be configured like so –

These settings can also be defined on local instances, via SCCM or through Microsoft InTune as described in the documentation available at this link.


Cloud-based protection can be enabled through PowerShell on either a standalone machine, or potentially on many machines through remoting or otherwise. Thankfully, Microsoft has made Defender’s PowerShell commandlets incredibly easy to use, with only two commands required to enable cloud-based protection –

Note: These commands must all be ran as an Administrator.

Set-MpPreference -MAPSReporting Advanced
Set-MpPreference -SubmitSamplesConsent AlwaysPrompt

Once enabled, you can confirm whether or not MAPS is enabled on a device by extracting the MAPSReporting setting from the malware protection preferences like so –


A result of 0 indicates that MAPS reporting is not enabled, and either 1 or 2 means that cloud-based protection should be enabled.

Enhancing cloud-based protection

So now we’ve enabled cloud-based protection along with sample submission, but what else can we configure? Well, we can also enable real-time cloud-based detection for suspicious activities, define the cloud protection blocking level and cloud-based scanning for suspicious files.

Group Policy

Real-time cloud-based detection can be enabled through Computer configuration -> Administrative templates -> Windows Components -> Windows Defender Antivirus -> MAPS, by setting the “Configure the ‘Block at First Sight’ feature” setting to Enabled. This requires the following prerequisites –

  • MAPS -> “Join Microsoft MAPS” set to Enabled
  • MAPS -> “Send file samples when further analysis is required” set to Send safe samples or Send all samples
  • Real-time Protection -> “Scan all downloaded files and attachments” must be enabled
  • Real-time Protection -> Do not enable “Turn off real-time protection”

The other two settings are configurable through Computer configuration -> Administrative templates -> Windows Components -> Windows Defender Antivirus -> MpEngine. The current Microsoft security baseline does not recommend adjusting the cloud protection level, and the Microsoft docs warn against setting a higher protection level as it may lead to increased false positives. If desired, you can adjust this setting to either High, High+ or Zero Tolerance (with the risk of false positives naturally increasing at each step change).

As described in the “Configure extended cloud check” help section, the default cloud check timeout is 10 seconds. This can be increased to allow for extended checking – for example, adjusting the setting to 50 seconds will result in an addition 50 seconds of checks alongside the default 10 seconds, i.e. 60 seconds in total.


Note: These commands must all be ran as an Administrator.

Microsoft’s docs on Set-MpPreference seem a little outdated, so at first glance, it does not appear to be possible to adjust either the extended cloud check duration through PowerShell commandlets. But by reviewing the output of Get-MpPreference, extended cloud check and adjusting the cloud protection level is possible like so –

Set-MpPreference -CloudBlockLevel High

High can be substituted with either HighPlus or ZeroTolerance to match the potential options mentioned above.

Block at First Sight can be enabled via the Set-MpPreference commandlet like so –

Set-MpPreference -DisableBlockAtFirstSeen $False

Finally, the cloud-based extended check can be adjusted through the CloudExtendedCheck property –

Set-MpPreference -CloudExtendedTimeout 50

Troubleshooting cloud-based protection

With all these settings enabled, it’s important that we confirm we’re actually receiving the requested protection. Thankfully, Microsoft has well-documented information around confirming and troubleshooting connectivity issues.

Once you’ve deployed the Group Policy changes and allowed them to refresh on a test PC, launch Command Prompt as an administrator (must be an elevated prompt or else you’ll receive a 80070005 error).

From Command Prompt, run the following – "%ProgramFiles%\Windows Defender\MpCmdRun.exe" -validatemapsconnection. You should receive a successful response like so –

If you do receive an error when running the above command, check out Microsoft’s docs page on troubleshooting cloud-based protection – it includes required URLs, and a sample file which should be detected if cloud-based settings are enabled.

Blocking potentially unwanted programs

Group Policy

For whatever reason, Windows Defender doesn’t enable PUP protection by default – a feature offered by most other anti-virus applications. This feature can be enabled through Group Policy via the following path – Computer configuration -> Administrative templates -> Windows Components -> Windows Defender Antivirus through the setting “Configure detection for potentially unwanted applications“.

This setting can be set to either Audit or Block. Block will naturally block potentially unwanted programs, whereas Audit will log an event to the event log under event ID 1160 through Application and Services Logs\Microsoft\Windows\Windows Defender\Operational.

This setting can also be set up through InTune, and is enabled by default through SCCM.


Note: These commands must all be ran as an Administrator.

Potentially Unwanted Programs can be blocked through PowerShell through the following commandlet –

Set-MpPreference -PUAProtection 1

Again, you can easily verify whether or not this setting is enabled by checking the result from Get-MpPreference for the PUAProtection property


Attack surface reductions

Group Policy

Microsoft offers several attack surface reduction rules to prevent common malware behaviours. Unfortunately, these are not the most user-friendly in their naming convention as they use GUIDs (though a mapping from GUID to a friendly description is available here). It is not exactly clear if all of these reduction rules will continue to remain available to users without Defender ATP, however I will include them below anyway.

Attack surface reduction rules can be enabled via Computer configuration -> Administrative templates -> Windows Components -> Windows Defender Antivirus -> Windows Defender Exploit Guard -> Attack Surface Reduction.

Microsoft’s security baseline recommends the following GUIDs set to Block (I have included friendly description mappings from the link above) –

GUIDFriendly description
be9ba2d9-53ea-4cdc-84e5-9b1eeee46550 Block executable content from email client and webmail
b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4 Block untrusted and unsigned processes that run from USB
9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2 Block credential stealing from the Windows local security authority subsystem (lsass.exe)
d4f940ab-401b-4efc-aadc-ad5f3c50688a Block all Office applications from creating child processes
d3e037e1-3eb8-44c8-a917-57927947596d Block JavaScript or VBScript from launching downloaded executable content
5beb7efe-fd9a-4556-801d-275e5ffc04cc Block execution of potentially obfuscated scripts
3b576869-a4ec-4529-8536-b80a7769e899 Block Office applications from creating executable content
26190899-1602-49e8-8b27-eb1d0a1ce869 Block Office communication application from creating child processes
92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B Block Win32 API calls from Office macro
7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c Block Adobe Reader from creating child processes
75668c1f-73b5-4cf0-bb93-3ecf5cb7cc84 Block Office applications from injecting code into other processes


Note: These commands must all be ran as an Administrator.

Again, we can use the Set-MpPreference commandlet to add attack surface reduction rules. This can be achieved like so –

Set-MpPreference -AttackSurfaceReductionRules_Ids RULE_GUID(S) -AttackSurfaceReductionRules_Actions Enabled

As with Group Policy, the action can either be enabled (i.e. the friendly description for the given rule will be enforced), or AuditMode, which will generate an event.

Therefore, to make adding the above rules easier, I have included the above command with each GUID to assist with copying and pasting (hopefully on a test machine!)

Set-MpPreference -AttackSurfaceReductionRules_Idsbe9ba2d9-53ea-4cdc-84e5-9b1eeee46550,b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4,9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2,d4f940ab-401b-4efc-aadc-ad5f3c50688a,d3e037e1-3eb8-44c8-a917-57927947596d,5beb7efe-fd9a-4556-801d-275e5ffc04cc,3b576869-a4ec-4529-8536-b80a7769e899,26190899-1602-49e8-8b27-eb1d0a1ce869,92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B,7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c,75668c1f-73b5-4cf0-bb93-3ecf5cb7cc84 -AttackSurfaceReductionRules_Actions Enabled 


Hopefully this article has given you some further insight into what Windows Defender can offer your environment. Personally, I never really considered Windows Defender to be much of a contender in the anti-virus market, but uncovering all of this information has really changed my mind.

I must include a massive shoutout to SwiftOnSecurity on Twitter – they gave me the inspiration to look more into Defender and its defence capabilities, and of course a shoutout to the Microsoft Security team for their dedication to their products and their receptiveness to community feedback.

Breached password detection with Azure AD

Combine on-premises breached password reset detection with your cloud environment!


This post serves to demonstrate the ability to implement on-premises breached password checking in a hybrid Azure AD environment that allows for self-service password resets.

This is more of a proof-of-concept than an explicit guide – you may well find that the information outlined here does not meet your business requirements. I mostly wanted to confirm that this was indeed possible.

In this instance, I’ll be using my Pwned Passwords password filter on the on-premises side for detection, however you could use any of the various password filters around.

End Goals

By combining the information outlined here with a DLL like my Pwned Passwords filter on-premises, alongside my C# project to detect in-use breached passwords, you could theoretically eradicate breached passwords from your hybrid environment 🙂


In order to implement breached password reset detection for Azure AD, you’ll need

  • A breached password filter on your on-premises domain controllers
  • One of the following licenses on your tenant (for self-service password resets):
    Azure AD Premium P1
    Azure AD Premium P2
    Enterprise Mobility + Security E3 or A3
    Enterprise Mobility + Security E5 or A5
    Microsoft 365 E3 or A3
    Microsoft 365 E5 or A5
    Microsoft 365 F1
    Microsoft 365 Business

Getting Started

To start with, you’ll need a password filter on-premises. While you definitely don’t need to go with my filter, I’ve put some general instructions at the end of my first post here.

Once you’ve got an on-premises solution deployed, you’ll need to enable Azure AD Connect with password writeback – it’s the password writeback requirement that will require Azure self-service resets to be verified against your on-premises domain’s password requirements.

Posts such as this one do a great job of explaining how to set up password writeback, even going to great detail to discuss what permissions are required for the AD Connect account.

However, I’ll give a quick rundown on the process –

  1. On your AAD Connect server, start the Azure AD Connect configuration wizard
  2. Choose ‘Customise synchronisation options’
  3. Connect to Azure AD
  4. Select relevant OUs or domain filters
  5. On the ‘Optional features’ page, select ‘Password writeback’
  6. Select ‘Configure’

Once password writeback is successfully configured, you’ll need to allow your users to have access to self-service password resets in Azure.

This is somewhat more involved, especially if you’re rolling this out to a large amount of users. Once again, Microsoft have some great docs on planning deployment of self-service resets, through to actual deployment and testing.

Once you’ve got your self-service password reset portal in place, all that’s left to do is test it with a non-Administrator user, with a known breached password, and observe the result!


Thanks for reading. This has been my fourth, and likely final, post covering Troy Hunt’s amazing Pwned Passwords service. Through this series of posts, I’ve covered on-premises breached password reset detection, to utilising the online k-Anonymity model with resets, as well as checking currently used passwords against the data set.

With this post, I hope to have covered all possible facets, but I’m sure I’ve missed something somewhere, so please let me know if that’s the case!

As always, if you have any issues with anything here, or would like any extra information/further projects, please let me know 🙂

Pwned Passwords and NTLM Hashes!


Yep, another Pwned Passwords post! This one brings the total to 3, and it now makes up the entirety of my posts here.

A couple of days ago, Troy Hunt released support for NTLM hashes for his Pwned Passwords dataset. This is really cool because it allows us to check live Active Directory hashes from ntds.dit (located under C:\Windows\NTDS on Domain Controllers). However, there’s a little bit of work involved in getting to that step, so I thought I would put together this quick little guide.

Extracting Hashes from NTDS.DIT

So, how do we get the hashes out of that ntds.dit database?

There’s actually a few different ways, but the easiest I found from some cursory searching was to use Michael Grafnetter’s amazing PowerShell tool, DSInternals. If you don’t want to go about doing a manual install of it, you can get it straight from the PowerShell Gallery, with quick instructions here.

Once you’ve got it installed, the next step is to make a copy of ntds.dit. If you try directly from C:\Windows\NTDS, you’ll notice the file is locked. Again, there’s a few ways around this, but a quick way is to do a shadow copy of the system drive, copy it from the shadow copy, and then delete the shadow copy, like so –

Then, you need the SYSTEM registry hive. Luckily, this can be directly saved, by running –


Now that we’ve got both of those files, we can start extracting hashes!

With the system extract and ntds.dit copy in hand, fire up PowerShell, it’s time for DSInternals!

Running the following will extract the hashes in Hashcat format (necessary for the next step) –

$key = Get-BootKey -SystemHivePath '<PATH TO SYSTEM HIVE HERE>'
Get-ADDBAccount -All -DBPath '<PATH TO NTDIS.DIT HERE>' -BootKey $key | Format-Custom -View HashcatNT | Out-File <OUTPUT PATH HERE> -Encoding ASCII

Note: If you receive any errors about your ntds.dit file being invalid, this is a good guide to fix it. Essentially, you just need to run this command on the ntds.dit copy from a Domain Controller –

esentutl /p <PATH TO NTDS.DIT> /8 /o

Comparing the Hashes

Now that we have a neat little hash extraction, we can get to comparing our users’ passwords against the Pwned Passwords dataset. If you don’t have a copy of the NTLM hashes, you’ll need to grab them from here.

In Troy’s original post about adding NTLM hashes, he mentioned a tool to compare the passwords from Pwned Passwords with extracted passwords. This tool is available here. Unfortunately, as it builds a hashmap from a large text file, it’s not that fast.

Once downloaded, all you need to do is specify the function, and supply it with the path to the output file from the previous step, alongside the path to the pwned passwords dataset. The syntax and an example of the output can be seen below –

Note: The time is not representative of the full dataset, this was an example where the hash dictionary contained only the single hash. When using the actual dataset, it will take more than a few minutes (on average) per user.

So, now we know which users are currently using a breached password!

A Look at Faster Comparisons

While the tool above is certainly good, it just doesn’t scale too well. There’s also another great looking tool here, but again, the issue is speed. Definitely cool though! I decided to have a look at changing my original binary search for the original Pwned Passwords dataset (read my post here if you want more information on that).

As binary search requires a sorted input file, and the dataset is ordered by frequency, I went about sorting it myself. The sorting took about 40 minutes, but that’s on some pretty old hardware, and a pretty basic set up. It would be great to have the hashes available sorted by hash, but it’s not too bad if you have to do it yourself. I’d publish the sorted dataset but I don’t think my Australian internet would ever finish the upload.

In any case, I’m sure you could find a better sorting algorithm out there, but I used this and grabbed the necessary Priority Queue and Heap classes from the author’s GitHub. You’ll also need to modify it to ensure the frequency isn’t included when sorting.

You can find my code at my GitHub. Here’s an example of the syntax and the output –

There’s also a release available if you don’t want to compile it yourself.

Final Comments

I think the addition of NTLM hashes to the Pwned Passwords family will offer up even more use cases for the data. I’ve said it before, but it really needs to be said that Troy’s work is invaluable. He provides a great service to the infosec community.

I believe that the combination of this, alongside something to check against password changes (like my Pwned Passwords API checker, or the several others out there), will greatly help security folk, and hopefully help users see just how insecure some passwords are.

If you’ve made it this far, congratulations. I hope you have a great rest of your day/night! 🙂

Checking for Breached Passwords in Active Directory – Using k-Anonymity!

I’d like to preface this post by saying that I 100% understand concerns about using an external API, even when sending it just a small amount of unusable information. The possibility of compromise and subsequent infection on Domain Controllers is a true security risk and it is totally acceptable to not want to take that risk. For those not wishing to use an external API at all, I wrote an original post on checking breached passwords with AD, that works entirely offline with downloaded hashes of Troy Hunt’s Pwned Passwords – you can read about that project here.


Last year Troy Hunt released a freely searchable database of previously breached passwords. The available data was pretty much a godsend for anyone looking to verify that their users aren’t using breached passwords, with the ability to query for passwords through plaintext or as SHA1 hashes via API, as well as the ability to download the entire data set to use offline. A little after the release of this information, I wrote a DLL for use in Active Directory environments. However, that tool required users to download the massive lists of passwords so that it could be queried over the network. While it requires no external service interaction, it still requires downloading and searching through gigabytes of files.

Continue reading “Checking for Breached Passwords in Active Directory – Using k-Anonymity!”

Checking for Breached Passwords in Active Directory

Edit: I have now overhauled the blog post and essentially recreated PwnedPasswordsDLL to run on-premises,
      and return results very quickly. Information regarding set-up and the new release can be
      found below. Changes have now been pushed to GitHub and are available for use.

Introduction –

In simplistic terms, PwnedPasswordsDLL will check a requested Active Direvtory password change against a local store of over 330 million password hashes. If the hash is found in the breached passwords, the requesting password is rejected. This entire process takes ~1 second against over 330 million previously breached password hashes.

Now on to a more technical explanation.

A little known setting through LSASS on Windows PCs is the ability to call a custom filter DLL when a password change request is received. The utilisation of this resource was commonplace back in the Windows 2000 days, but it’s now seldom used; many sysadmins are happy enough using totally third-party solutions or the in-built Group Policy settings.

The concept of a 100% customisable password filter intrigued me, and with Troy Hunt’s new freely searchable database of pwned passwords, I decided to look at setting up a filter DLL to call a local store of the breached passwords to check the prospective password change.

I discovered that writing such a DLL was a very simple process, most of the actual handling of the DLL is done internally, all that needs to be done by an author is to create a function that returns a Boolean expression based around whether or not conditions are met for the requesting password. The result of my research is PwnedPasswordsDLL.

In calling the DLL, the requested password is converted to an SHA1 hash through the Crypto++ library. This SHA1 hash is then passed to a binary search algorithm I wrote that searches the three HaveIBeenPwned breached passwords text files. If the hash is found, a false boolean is returned (i.e. telling LSA that the calling password failed to meet the required password policy).

If you’re willing to give it a whirl, you can find the code here.

If you want to compile for yourself, check out the Compiling the Code section below. If you want to download a Release version, look at the Implementing the DLL section below.

Here is an example of the DLL in use –

Continue reading “Checking for Breached Passwords in Active Directory”