Wednesday 18 November 2015

An Easy Guide to Bypass DEP using ROP

               DEP (Data Execution Prevention) was introduced in Windows in 2004 with Windows XP Service Pack 2 which ensures that data does not gets executed unless it has execute memory rights (PAGE_EXECUTE). To bypass DEP  we will use ROP (Return Oriented Programming) gadgets. I have also provided MS Visual Studio solution in a zip for testing. 

What is ROP ?:

           After the introduction of ASLR (Address space layout randomization) shellcodes which had hardened addresses of the APIs started to fail. For example API UrlDownloadToFileA was located at 0x781C4868 in windows XP SP3 even after reboot. Hence it was very easy to develop exploits and shellcodes. From Windows 7 onwards, most of the essential modules started to load at random addresses after every reboot (due to ASLR) which failed all previous shellcodes / exploits which had defined fixed addresses in their exploits. But few remained ASLR disabled (msvcr71.dll, msxml15.dll etc ) which are still loaded at the fixed addresses in similar builds of Windows even after reboots. This gives an opportunity to use some of the code section (gadgets) in an artful way to change memory protection rights of shellcode area. For example, we can find the instructions necessary to prepare the arguments on stack and then call the VirtualProtect function to change the memory rights of shellcode region and then execute it. This can be done by first calculating the instructions which could do this and then populating it on stack in a manner that there is a "ret" instruction at the end of those instructions. When "ret" gets executed OS will pop an address from ESP (stack pointer) and transfer control to that instructions and so on and so forth. Once all parameters to VirtualProtect /VirtualAlloc are prepared a JMP instruction to VirtualProtect will change memory permissions of shellcode region and hence DEP will be bypassed.

Purpose of ROP:

  • Change memory region rights (or allocate memory) of shellcode to PAGE_EXECUTE or PAGE_EXECUTE_READWRITE (DEP bypass)
  • Change EIP control to ROP chain (stack pivot)
  • Execute shellcode

This Blog:

  •  Using C for demonstration of ROP
  •  ROP gadgets creation using mona.py (immunity debugger's extension) in msvcr71.dll
  •  Use of VirtualProtect function for changing memory rights

Requirements:

  1. MS Visual Studio 2008 or higher
  2. Immunity debugger with mona installed. For installation guide click here
  3. Windbg (optional). Download form here

Steps: 

  1. Set up VS project ( Download VS project )
  2. Create ROP chains /suggestion using mona 
  3. Build the exe and open with Immunity or windbg. Program will halt on software breakpoint (int 3) instruction defined in inline assembly 
  4. Step into ROP gadgets and see the behavior of ROP chain. When arguments to VirtualProtect are prepared, PUSHAD instruction pushes arguments on stack and returns which is a jump to VirtualProtect function. 
  5. Shellcode will get executed and calculator will popup showing the successful bypass of DEP by ROP
Build and test environment: Windows 7 x64 SP1

1. Setup project:

Open the .sln file with Visual studio or create new project in visual studio and copy paste the rop_x86.cpp file contents in main file and build the solution. We will use msvcr71.dll for creating ROP chain. This dll is loaded most of the times, but if it isn't loaded already, we can use LoadLibrary API to load it. In this example i have loaded it using LoadLibrary as you can see in the code. 

2. Creating ROP Chains:

    Here i assume that you have installed mona in immunity by now. Now to check which modules (dlls) are ASLR disabled give this command !mona noaslr in the command window at the bottom as shown in image 2.1


Image 2.1
-------------

You can see that there is one module which is ASLR disabled, means we can use this module to generate rop chain. To generate gadgets provide command !mona rop -m msvcr71.dll which will create three files namely rop.txt, rop_suggetsions.txt and rop_chains.txt. Rop_chains.txt will contain nicely prepared rop gadgets in different languages like C, python and ruby. Image 2.2 shows the output of rop generation command. 

Image 2.2
-------------

I have used some of these gadgets and some of my own. You can search for specific gadgets in rop.txt and rop_suggestions.txt files. Some of the gadgets created by mona are shown in image 2.3.

Image 2.3


3. Analysis of ROP with Windbg / Immunity: 

                         Execute the binary and it will break at instruction "int 0x03" as shown in image 3.1. As breakpoint will hit, source file will be loaded and we will be able to see the source as well. Then step into using F11. Next instruction will add 0xd0 to ESP. Actually rop gadgets and shellcode declared in char ROP_shellcode[] are pushed on stack. To trigger the rop chain we have to point ESP to first gadget and execute the "ret" instruction. In real world exploits it is called stack pivot (usually xchg eax,esp ; ret) but in this scenario i have simplified it by pointing ESP to rop chain and then executing "ret" instruction manually. Difference of ESP and rop chain is shown in image 3.2  and difference is evaluated in image 3.3. 


    Image 3.1
    -------------

 Image 3.2
-------------


 Image 3.3
-------------

Image3.4 shows the rop chain in immunity debugger. By stepping in you can see the execution of rop step by step.  

Image 3.4
-------------

 4. ROP Chain Execution: 

                             From here on we will be executing rop chain. Stepping in using F11 will give a fair idea that how rop gadgets are executed. You will notice that every instruction is followed by "ret" which triggers another gadget until the purpose is achieved. Thats why this is called return oriented programming (ROP). 

Image 4.1
-------------


Here (image 4.2) is the chain with symbols (dps display addresses with symbols) showing addresses of msvcr71.dll 

Image 4.2
-------------

 Main purpose of this chain is to prepare arguments to VirtualProtect in registers in an order that when "PUSHAD" intruction is executed, stack should be prepared in following order (image 4.3) at gadget 0x7c3415a2.

Here is little description of VirtualProtect from MSDN.

BOOL WINAPI VirtualProtect(          =>    A pointer to VirtualProtect()
  _In_   LPVOID lpAddress,           =>   Address whose rights have to be changed (some address down the ESP)
  _In_   SIZE_T dwSize,              =>    dwSize up to you to chose as needed (0x201)
  _In_   DWORD flNewProtect,         =>    flNewProtect (0x40)
  _Out_  PDWORD lpflOldProtect       =>    A writable pointer
);

Following image shows the stack when VirtualProtect is called via a jump to pointer ( to VirtualProtect) stored in EAX.


Image 4.3
-------------

To see the memory rights at this point use !address esp command which will show the memory rights of the page as given in image 4.4

Image 4.4
-------------

5. Identifying successful DEP bypass:

Set a breakpoint at gadget pointed by ESP (bp 7c35630c) and run the sample using F5 command or "g". When breakpoint hits, check the memory rights using !address esp command. You will notice that the page will have PAGE_EXECUTE_READWRITE protection rights as shown in image 5.1.









Image 5.1
-------------

After confirming memory rights elevation, we can give command "g" in command panel which should popup the calculator (image 5.2) if everything goes well. In my tests i have observed that sometimes stack is not aligned and an exception occurs, in that case just re-run the sample and it will run fine.

Image 5.2
-------------


You can also visit these links which are more rop development-centric rather than reversing / analysis of rop gadgets:
  1. Corelan
  2. FuzzySecurity

Enjoy exploiting!!!

15 comments:

  1. Very informative. Thanks for writing this.

    ReplyDelete
  2. thank you but I have question How I can write the ShellCode in C after building ROP chain ??

    ReplyDelete
  3. Hi, Sorry for late reply, i was on vacations. You can use inline assembly using __asm { // assembly code } block in C, if you are comfortable with assembly, and write a dynamic shellcode (which uses Process Environment Block PEB to get API addresses) and then extract the opcodes (shellcode) from the start of inline assembly block till the end and insert it after ROP chain. You can find many tutorials about this technique on Google. If you explicitly want to use C for complete dynamic shellcode, you can have a look at this blog https://nickharbour.wordpress.com/2010/07/01/writing-shellcode-with-a-c-compiler/
    If you need more details, please leave a comment. Thanks

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. thank you a lot for answering me. I want to write simple program that uses ROP ,So I am using Visual studio and Immunity debugger to find gadgets then I want to use ROP chain from mona.py files but after that I don't know what to do thanks to your article I understood some steps . So my question after building shellcode how I can executed?? I am beginner to this area.

    ReplyDelete
    Replies
    1. Once you have prepared ROP chain, just append the shellcode to the ROP chain, and last gadget should be "push esp;ret". It will automatically execute the shellcode. This blog uses this technique.

      Delete
    2. thank you for your replay. but I still did not know what to put inside ASM, I want to call another function name fun1 this is my sellcode :char shellcode[] =
      "\x58\xc3" //POP EAX //RETN[KERNEL32.DLL]
      "\x18\x11\x7b\x76"//ptr to&VirtualProtect[KERNEL32.DLL]
      "\x8b\x00\xc3" // MOV EAX,DWORD PTR DS:[EAX] // RETN [KERNEL32.DLL]
      "\x50\x89\x8e\x54\x00\x00\x00\x5e\xc3" // PUSH EAX // MOV DWORD PTR DS:[ESI+54],ECX // POP ESI // RETN [KERNEL32.DLL]
      "\x5d\xc3" // POP EBP // RETN [KERNEL32.DLL]
      "\xff\xe4" // & jmp esp [KERNEL32.DLL]
      "\x5b\xc3"// POP EBX // RETN [KERNEL32.DLL]
      "\x01\x02\x00\x00" // 0x00000201-> ebx
      "\x59\xc3" // POP ECX // RETN
      "\x76\x0e\x7e\x76" // &Writable location [KERNEL32.DLL]
      "\x5f\xc3" // POP EDI // RETN [KERNEL32.DLL]
      "\xc3" // RETN (ROP NOP) [KERNEL32.DLL]
      "\x58\xc3"// POP EAX // RETN [KERNEL32.DLL]
      "\x90 "// nop
      "\x20\x18\x41\x00"; //cal fun1
      then I don't now what to do, in your ASM you put
      int 0x03
      add esp,0xd0
      ret
      why you write int 0x03 and from where you find 0xd0
      . many thanks.

      Delete
    3. 0xdo is just a manually calculated number from where ROP starts its first gadget, i used it intentionally for making the tutorial simple. In real world scenario you will have to find stack pivot to trigger the ROP chain. int 3 is just to break in the debugger so that you can understand the working of ROP chain step by step.

      Delete
    4. thank you . I have question whenever I try to execute the code this error appear Exception thrown at 0x7C34D202 in rop_x86.exe: 0xC0000005: Access violation executing location 0x7C34D202.

      Do you know how solve it ??
      thank you again .

      Delete
    5. Also in my laptop I don't have any library with noalsr , and I want to use kernel32.lib to find gadgets , is that be a problem?

      the last quetion is: in your code you write
      "\x51\xa1\x37\x7c" // pointer to &VirtualProtect - 0xEF ("\x81\x8c\x37\x7c" PUSHAD , add al,0xef will to 0x7c37a140)
      how the pointer converted into opcode ??

      I am sorry for bothering you .

      Delete
    6. Exception might be due to, msvcr71.dll is not loaded in your system or not found, you have to download and load this DLL using LoadLibrary API. Second question's answer: you don't have to convert address into opcode, you have to store the function address into some register, say EAX and then find a gadget which has instruction 'call EAX', in this way VirtualProtect API will be called, but before calling some function you have to push all of its parameters onto the stack, like standard calling convention.

      Delete
    7. Many thanks , its working now. I have a question , I wrote a function and I want to call it how I can do that after calling virtualProtect ??

      Delete
    8. Just replace the shellcode (starting with \xfc\xe8 after ROP ) with your function's bytecode (machine opcodes) but your function must use dynamic linking of code with APIs like in dynamic shellcode otherwise it will fail because in real exploit scenario offsets dont remain the same as in compile time, i would recommend to use a shellcode after ROP which will download the executable from some server and execute, in this way you can easily write in C/C++ or any of your favourite language and achieve what you want. This is what real attacks do.

      Delete
    9. Many thanks.really thank you . I managed to call another functions but now I can't stop the shell code and return to the original program , did you know how I can do it ??

      Delete
    10. My pleasure :) . You can return to original function by saving the state of the stack before execution of the ROP and shellcode. Lets say you knew the return address before execution of the ROP, save that return address on the stack, then after the execution of the stack, make sure the esp points to that return address and then call "ret" instruction. It will take you back to the original function. But you have to take other precautions as well, like saving the state of non-volotile registers, esi,edi and ebx, and restoring them before return to the original function. You can achieve it by using PUSHAD and POPAD instruction before executing and after ROP/shellcode.

      Delete