Disable Windows Defender in powershell – a script to finally get rid of it

Once again, after a Windows update, Windows Defender activated itself again. It finally bothered me enough to take an actual look at how to disable it permanently and reliably, in a fully automated way (a PowerShell script), on my Windows 10 20H2 (build 19042).

TL;DR : the final script can be found here : https://github.com/jeremybeaume/tools/blob/master/disable-defender.ps1

Registry configuration

First, I took some time to look at the registry configuration, where are the parameters located, and how/when the values were changed. Procmon, from SysInternals, is a very convenient tool for this kind of research.

I looked for registry access with “Defender” in the path, and this is the result:

Defender general view

We get a first idea of the configuration location, most interesting keys seems to be under HKLM\SOFTWARE\Microsoft\Windows Defender.

Then I proceeded to check the keys for each parameter.

First on the list is the “Real-Time protection”, modifying the key HKLM\SOFTWARE\Microsoft\Windows Defender\Real-Time Protection\DisableRealtimeMonitoring

Defender Real time key

Then the “cloud-delivered protection”, with the key HKLM\SOFTWARE\Microsoft\Windows Defender\SpyNet\SpyNetReporting :

Defender cloud protection key

(For reference, the key for “Automatic sample submission” is HKLM\SOFTWARE\Microsoft\Windows Defender\SpyNet\SubmitSampleConsent)

The “Tamper Protection” is next, using 2 keys: HKLM\SOFTWARE\Microsoft\Windows Defender\Features\TamperProtection (4 when disabled) and HKLM\SOFTWARE\Microsoft\Windows Defender\Features\TamperProtectionSource (2 when disabled)

Defender Tamper protection

And lastly, exclusions are stored in subkeys of HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions depending on their type:

Defeder Exclusions

Now, one thing to note is that the Administrator (meaning members of the BUILTIN\Administrators group) cannot change those keys (only SYSTEM can):

Defender Key Permissions

An even as SYSTEM, with tamper protection off, writing is still not authorized:

Defender Writing key denied

So here we are :

  • There is not option to disable “Tamper Protection” in powershel (that’s the point ….).
  • We can’t edit the configuration directly in the registry, even as SYSTEM.

What I used to do was using Set-MpPreference to add whole drives as exception, but sometimes I would still get alerts : Defender is still running and analyzing my actions.

Of course, Microsoft provides ways and documentation to disable Defender, so let’s check them out.

Disable Defender: the Microsoft way

DisableAntiSpyware

Searching on the internet (like here), there seems to be a registry key for that, named DisableAntiSpyware. It is indeed read when opening the configuration:

Defender Read anti spyware

2 Keys are read, one in the “main configuration” key, and one under HKLM\SOFTWARE\Policies. This second one, we can write, to let’s go for it!
I created it, Defender was still running, without warning or anything, so it doesn’t seem to have any effect. But it gets better, it is actually considered a Severe security alert!

Defender Anti Spyware alert

Maybe we need to be more subtle, and use gpedit to edit this policy, let’s try that!

GPO

Here is what we get when editing the policy with gpedit :

Defender Gpedit

The previous key is actually written by a service (svchost.exe -k netsvcs -p -s gpsvc) and another one is written in a policy object. This time is doesn’t raise a security alert, so the second key must be necessary. I also noted that a 3rd key is written when the tamper protection is off:

Defender gpedit no tamper

This 3rd key is written by MsMpEng.exe which happens to be the binary run by the Microsoft Defender service: this is the Defender userland engine. So, we should be good to go then?

Well, nothing is disabled yet, and after reboot …. the policy is removed! So this seems to be completely ignored.

Temporary solution

I finally managed to disable it, by adding a process exclusion (including regedit.exe):

Defender exclusion

Then, with “Tamper Protection” off, and as SYSTEM, the key HKLM\SOFTWARE\Microsoft\Windows Defender\DisableAntiSpyware finally becomes writable. Setting its value to 1 immediately stops Windows Defender:

Defender disabled

So here we are! But …. no 🙂 This is still overwritten on reboot! This a good enough temporary solution, but as we need to disable the “Tamper Protection”, it cannot be scripted in PowerShell.

Disable Defender: the hacker way

How it works

So I did not found any way to configure Defender itself to stop running. But it actually runs in a Service, so maybe there is something there. The service cannot be modified using services.msc as we would usually do:

Defender service

See how everything is greyed out?

We can also find the kernel drivers used by Defender, with msinfo32:

Defender kernel driver

But, and that’s what we’re going to use : we can edit (at least for now) the registry keys associated to those services and drivers, in HKLM\SYSTEM\CurrentControlSet\Services\. We set they Start value to 4, meaning “Disabled”, and after next reboot, the services and driver will not be loaded / started, and so Defender will not be working anymore ! And indeed, after the reboot :

Defender services disabled

We’re good to go, finally! It’s weird that we can edit those registry keys, when services.msc doesn’t let us modify the service, but well … It works! Let’s script the whole thing.

Scripting in PowerShell

I put everything in a convenient script that disables what it can directly in defender (Set-MpPreference), then modify the registry to disable the services, and set itself up to run again after reboot, to complete the removal. I’ll break it down below.

First, I make sure to elevate to Administrator (mandatory, and actually used when the scripted is run after rebooting), and SYSTEM if psexec is available. SYSTEM is optional, but we need it to write in the registry to modify the parameters in case Defender would still re-enable itself one day (because it sure will …).

if(-Not $($(whoami) -eq "nt authority\system")) {
    $IsSystem = $false

    # Elevate to admin (needed when called after reboot)
    if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
        Write-Host "    [i] Elevate to Administrator"
        $CommandLine = "-ExecutionPolicy Bypass `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
        Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
        Exit
    }

    # Elevate to SYSTEM if psexec is available
    $psexec_path = $(Get-Command PsExec -ErrorAction 'ignore').Source 
    if($psexec_path) {
        Write-Host "    [i] Elevate to SYSTEM"
        $CommandLine = " -i -s powershell.exe -ExecutionPolicy Bypass `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments 
        Start-Process -WindowStyle Hidden -FilePath $psexec_path -ArgumentList $CommandLine
        exit
    } else {
        Write-Host "    [i] PsExec not found, will continue as Administrator"
    }

} else {
    $IsSystem = $true
}

Then the script use the Set-MpPreference command to disable everything we can, adding exception for all drive leter, and disabling all available engines.

67..90|foreach-object{
    $drive = [char]$_
    Add-MpPreference -ExclusionPath "$($drive):\" -ErrorAction SilentlyContinue
    Add-MpPreference -ExclusionProcess "$($drive):\*" -ErrorAction SilentlyContinue
}

Write-Host "    [+] Disable scanning engines (Set-MpPreference)"

Set-MpPreference -DisableArchiveScanning 1 -ErrorAction SilentlyContinue
Set-MpPreference -DisableBehaviorMonitoring 1 -ErrorAction SilentlyContinue
Set-MpPreference -DisableIntrusionPreventionSystem 1 -ErrorAction SilentlyContinue
Set-MpPreference -DisableIOAVProtection 1 -ErrorAction SilentlyContinue
Set-MpPreference -DisableRemovableDriveScanning 1 -ErrorAction SilentlyContinue
Set-MpPreference -DisableBlockAtFirstSeen 1 -ErrorAction SilentlyContinue
Set-MpPreference -DisableScanningMappedNetworkDrivesForFullScan 1 -ErrorAction SilentlyContinue
Set-MpPreference -DisableScanningNetworkFiles 1 -ErrorAction SilentlyContinue
Set-MpPreference -DisableScriptScanning 1 -ErrorAction SilentlyContinue
Set-MpPreference -DisableRealtimeMonitoring 1 -ErrorAction SilentlyContinue

Write-Host "    [+] Set default actions to Allow (Set-MpPreference)"

Set-MpPreference -LowThreatDefaultAction Allow -ErrorAction SilentlyContinue
Set-MpPreference -ModerateThreatDefaultAction Allow -ErrorAction SilentlyContinue
Set-MpPreference -HighThreatDefaultAction Allow -ErrorAction SilentlyContinue

Then the services and drivers are disabled, and the script checks if it need to reboot :

$need_reboot = $false

# WdNisSvc Network Inspection Service 
# WinDefend Antivirus Service
# Sense : Advanced Protection Service

$svc_list = @("WdNisSvc", "WinDefend", "Sense")
foreach($svc in $svc_list) {
    if($(Test-Path "HKLM:\SYSTEM\CurrentControlSet\Services\$svc")) {
        if( $(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$svc").Start -eq 4) {
            Write-Host "        [i] Service $svc already disabled"
        } else {
            Write-Host "        [i] Disable service $svc (next reboot)"
            Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$svc" -Name Start -Value 4
            $need_reboot = $true
        }
    } else {
        Write-Host "        [i] Service $svc already deleted"
    }
}

Write-Host "    [+] Disable drivers"

# WdnisDrv : Network Inspection System Driver
# wdfilter : Mini-Filter Driver
# wdboot : Boot Driver

$drv_list = @("WdnisDrv", "wdfilter", "wdboot")
foreach($drv in $drv_list) {
    if($(Test-Path "HKLM:\SYSTEM\CurrentControlSet\Services\$drv")) {
        if( $(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$drv").Start -eq 4) {
            Write-Host "        [i] Driver $drv already disabled"
        } else {
            Write-Host "        [i] Disable driver $drv (next reboot)"
            Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$drv" -Name Start -Value 4
            $need_reboot = $true
        }
    } else {
        Write-Host "        [i] Driver $drv already deleted"
    }
}

# Check if service running or not
if($(GET-Service -Name WinDefend).Status -eq "Running") {   
    Write-Host "    [+] WinDefend Service still running (reboot required)"
    $need_reboot = $true
} else {
    Write-Host "    [+] WinDefend Service not running"
}

To execute after reboot, a shortcut is added in C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\, and deleted after use.

$link_reboot = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\disable-defender.lnk"
Remove-Item -Force "$link_reboot" -ErrorAction 'ignore' # Remove the link (only execute once after reboot)

if($need_reboot) {
    Write-Host "    [+] This script will be started again after reboot." -BackgroundColor DarkRed -ForegroundColor White

    $powershell_path = '"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"'
    $cmdargs = "-ExecutionPolicy Bypass `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments

    $res = New-Item $(Split-Path -Path $link_reboot -Parent) -ItemType Directory -Force
    $WshShell = New-Object -comObject WScript.Shell
    $shortcut = $WshShell.CreateShortcut($link_reboot)
    $shortcut.TargetPath = $powershell_path
    $shortcut.Arguments = $cmdargs
    $shortcut.WorkingDirectory = "$(Split-Path -Path $PSScriptRoot -Parent)"
    $shortcut.Save()

Finally, if we don’t need to reboot, we can finish cleaning up : configure the registry, and delete the files if we wish to :

} else {
    if($IsSystem) {

        # Configure the Defender registry to disable it (and the TamperProtection)
        # editing HKLM:\SOFTWARE\Microsoft\Windows Defender\ requires to be SYSTEM

        Write-Host "    [+] Disable all functionnalities with registry keys (SYSTEM privilege)"

        # Cloud-delivered protection:
        Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender\Real-Time Protection" -Name SpyNetReporting -Value 0
        # Automatic Sample submission
        Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender\Real-Time Protection" -Name SubmitSamplesConsent -Value 0
        # Tamper protection
        Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender\Features" -Name TamperProtection -Value 4

        # Disable in registry
        Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Defender" -Name DisableAntiSpyware -Value 1
        Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender" -Name DisableAntiSpyware -Value 1

    } else {
        Write-Host "    [W] (Optional) Cannot configure registry (not SYSTEM)"
    }


    if($MyInvocation.UnboundArguments -And $($MyInvocation.UnboundArguments.tolower().Contains("-delete"))) {

        # Delete Defender files

        function Delete-Show-Error {
            $path_exists = Test-Path $args[0]
            if($path_exists) {
                Remove-Item -Recurse -Force -Path $args[0]
            } else {
                Write-Host "    [i] $($args[0]) already deleted"
            }
        }

        Write-Host ""
        Write-Host "[+] Delete Windows Defender (files, services, drivers)"

        # Delete files
        Delete-Show-Error "C:\ProgramData\Windows\Windows Defender\"
        Delete-Show-Error "C:\ProgramData\Windows\Windows Defender Advanced Threat Protection\"

        # Delete drivers
        Delete-Show-Error "C:\Windows\System32\drivers\wd\"

        # Delete service registry entries
        foreach($svc in $svc_list) {
            Delete-Show-Error "HKLM:\SYSTEM\CurrentControlSet\Services\$svc"
        }

        # Delete drivers registry entries
        foreach($drv in $drv_list) {
            Delete-Show-Error "HKLM:\SYSTEM\CurrentControlSet\Services\$drv"
        }
    }
}

Write-Host ""
Read-Host -Prompt "Press any key to continue"

And we are done ! Final result can be downloaded here : https://github.com/jeremybeaume/tools/blob/master/disable-defender.ps1

It can be executed from anywhere in the file system. The parameter -Delete will delete the files linked to Defender after reboot. And it should work fine, until the Tamper Protection also protects the services ergistry key, which is bound to happen someday. I’m actually surprised it doesn’t already …

4 thoughts on “Disable Windows Defender in powershell – a script to finally get rid of it

  1. Er is that really necessary, all that? Easier way to disable:
    1. Turn off real time protection and tamper protection in the app.
    2. Open Regedit. Navigate to HKLM/Software/Policies/Windows Defender. Place the DsiableAntiSpyware key in manually and set to 1.
    3. Navigate to HKLM/System/CurrentControlSet/wscsvc. Change the start value to 4. This disables the Security Service on the next boot.
    4. Restart. The Security Service fails to start and the Defender service stops running (eventually…….). Note that the DisableAntiSpyware key is NOT removed this time.
    5. To re-enable security centre, change the Start value back to 2 and restart again.
    6. Security will be re-enabled but Defender remains OFF. This persists until the DisableAntiSpyware key is removed manually.
    7. To re-enable Defender, simply remove the DisableAntiSpyware key manually. Press the “Restart Now” under Virus and Threat Protection and Defender (and its service) will immediately turn back on.

    • Hi ! Not “necessary” for sure, but I like to automate everything, and that’s the solution I came with. But doing it manually can be indeed quite simple, as you mentionned.

  2. in latest insider build (21390), even elevation to SYSTEM is not enough to disable the services and drivers in registry, I had to use AdvancedRun from nirsoft to launch the script as TrustedInstaller to make it work…

Leave a Reply

Your email address will not be published.