A practical example of bypassing Windows Defender’s signature detection by modifying source code. I’ll be using Rubeus as my malicious binary and I suggest you clone it and follow along to better your learning experience.
What is Signature Based Detection?
Before starting we need to understand what signature based detection is and how antivirus agents use it to catch malicious binaries. An antivirus signature is a continuous sequence of bytes within a malicious binary that uniquely identifies it. Files on your machine are scanned and compared against the a signature database and if there is a match then that file is quarantined and removed off the machine.
If you compile Rubeus and upload the binary to VirusTotal a hash of the file will be generated. This hash can be used as a signature to uniquely identify the file, although most antivirus agents will create custom signatures of the file by taking excerpts of the source code. The following image shows VirusTotal’s output after uploading an unmodified Rubeus binary.
What happens if we remove a single comment from the source code?
You should notice 2 differences.
- The signature (hash) of the file changed
- The detection rate went down. This means some AV vendors only used the hash of the file for signature detection
Reducing The Detection Rate
First thing’s first, let’s find and replace the term ‘Rubeus’ with a new word. I’m using Visual Studio so to do that use Ctrl+Shift+H:
You also want to do the following:
- Open up the .sln file with a text editor and replace all instances of Rubeus with your new word
- Modify the ‘Rubeus’ folder names of the project and ‘Rubeus.csproj’ to your new word
- Right click the project in Visual Studio and select ‘Properties’ then replace all instances of ‘Rubeus’ to your new word
- Compile and build as a x64 executable
Detection rate dropped to 23
Modifying Variables, Comments And Functions
We want to change the program as much as possible without changing the functionality. One thing you can do is find and replace all on variable names and function names. Look for malicious keywords like ‘Bruteforcer’ and replace that. Remove comments and modify text within print methods (e.g. Console.WriteLine()).
The problem with this method is we are arbitrarily replacing words without knowing whether it’ll have an effect or not. In the next section we’ll try to pinpoint the signature.
Finding The Malicious Signature
So far it’s been simple changes and Defender is still detecting our program. We need a better way to pinpoint the signature that’s triggering Defender.
What we want to do next is split our binary by grabbing the first X bytes and slowly increasing the number of bytes until Defender detects the binary as a malicious file. My main binary file is 254,464 bytes, so I’ll start off by getting the first 180,000 bytes and seeing if Defender triggers on it. Make sure you whitelist your working directory first.
#Get the first 180,000 bytes from Mrdox.exe and save it to test.exe #Use either Powershell or Bash #Powershell Get-Content .\Mrdox.exe -Encoding Byte -TotalCount 180000 | Set-Content test.exe -Encoding byte #Bash head -c 180000 Mrdox.exe > test.exe
Defender doesn’t trigger. Let’s change that to 181,000 bytes instead:
#Powershell Get-Content .\Mrdox.exe -Encoding Byte -TotalCount 181000 | Set-Content test.exe -Encoding byte #Bash head -c 181000 Mrdox.exe > test.exe
Still nothing… let’s try 181,500 bytes:
#Powershell Get-Content .\Mrdox.exe -Encoding Byte -TotalCount 181500 | Set-Content test.exe -Encoding byte #Bash head -c 181500 Mrdox.exe > test.exe
Great! Now we know that Defender is triggering somewhere between 181,000 and 181,500 bytes. Let’s open the last file with HxD and check out the last 500 bytes.
Defender’s signature is somewhere in the highlighted part. The most common word we see is ‘tickets’ so let’s do a find and replace on ‘tickets’ and replace it with a different word.
Now when we scan the file Defender doesn’t trigger! We successfully bypassed Defender and can now run Rubeus.