Showing posts with label Exploit Development. Show all posts
Showing posts with label Exploit Development. Show all posts

Wednesday, June 7, 2017

Exploit Dev 101: Bypassing ASLR on Windows

Note: This post is quite theoretical (yuk!) but I'll work on providing a hands-on demo sometime in the future.

What is ASLR?

Address space layout randomization (ASLR) is a memory protection techniques that tries to prevent an attacker from creating a reliable exploit. What it does is simple, a binary is loaded at a different base address in memory upon restart (or reboot for OS dlls). It also randomizes the base addresses for memory segments like the heap and the stack. This makes it harder for attackers to guess the correct address.

ASLR was introduced in Windows Vista and is in all newer versions. To make use of it, the executable needs to be compiled with /DYNAMICBASE option as well. OS dlls have that by default.

A way to see this taking place is by attaching an executable supporting ASLR (WinRAR in example below). Attach it to OllyDbg and go to the memory tab (ALT+M).

Restart WinRAR.


Note that the he higher two bytes get randomized, lower ones don't.

How does it make exploitation harder?

Most exploits require a way to redirect execution to the payload, this can be done by many different ways. What all these techniques got in common is finding an instruction that will "trigger" the payload by jumping to the address. Since addresses are hard coded they won't work after restart/reboot/different machine.

Example: JMP ESP is at 0x12345678 in test.dll, upon restart, address is now located at 0xABCD5678.

Bypassing ASLR

Next I'll discuss 4 (more like 3) techniques on bypassing ASLR, each with pros, cons and study cases if any.
 

1. Abusing non-ASLR enabled libraries

Programmers make mistakes, to make full use of ASLR, all loaded libraries need to be supporting it. If a single module doesn't you can make use of it by finding search that library for the needed instruction to jump to your shellcode.

Pros:
  • Reliable.
Cons:
  • None.
Study case:
  • CoolPlayer+ Portable 2.19.6 - '.m3u' Stack Overflow (Egghunter + ASLR Bypass), can be found here.

 

 2. Partial EIP overwrite

Since you control EIP, you also control how much of EIP you want to overwrite.
As already mentioned, ASLR only randomizes the higher two bytes, what if you can make use of that and only overwrite the lower 2 bytes?

Example: DLL is loaded at 0xAABB0000, if you overwrite only the lower two bytes (thanks to small endianness) you can basically control EIP to jump anywhere in 0xAABB0000 to 0xAABBXXYY.

Pros:
  • Big pool to search for the needed instruction from (16^4).
Cons:
  • Can't use bad characters.
Study case:
  • MS07-017, more info can be found here.

2.1 Single byte overwrite

Sometimes a character gets appended to your string, for example a null byte. This will mess up with the previous technique as when you try to overwrite the lower 2 bytes of EIP it becomes 0xAA00XXYY instead of 0xAABBXXYY. Although this limits the possibility of finding a proper instruction, you might still be able to get away with a single byte.

Search the 0xAABB0000 to 0xAABB00FF for possible instructions that can be used to land you your shellcode. 256 combinations aren't a lot so good luck with that.

Pros:
  • It's not over yet.
Cons: 
  • Very small search space (0x00 to 0xFF)
  • Still can't use bad characters.

3. Bruteforcing address space

Since we know that only the 2 higher bytes are randomized, what if we try to bruteforce all the possible combination? This method is risky (might crash the service), slow and adds a lot of overhead.

Pros:
  • Unless the higher bytes contain a bad char, it should work.
Cons: 
  • Large search space (0x0000 to 0xFFFF)
  • Huge overhead, service might crash and not restart.
  • Still can't use bad characters.
Study case:
  • Samba 2.2.8 (Linux x86) - 'trans2open' Overflow (Metasploit), can be found here.

4. Ultra-luck mode


Needed instruction is found at 0x0000XXYY, 0x0001XXYY, ... , 0xFFFFXXYY.

Pros:
  • Very cool.
Cons: 
    • Doesn't work.


    That's it! I'll work on a demo to utilize those techniques in the future.

      - Abatchy

        Tuesday, May 30, 2017

        Exploit Dev 101: Jumping to Shellcode

        Note: This post summarizes the techniques discussed in Corelan post on jumping to shellcode. Read it for better understanding.

        So you managed to control EIP and you want to jump to your shellcode. Check the condition for each technique and see if you can make it work to reach your shellcode.

        1. JMP/CALL register

        Conditions:
            ○ A register points to shellcode.
        Example:
            ○ [Register] → [Shellcode]
            ○ EIP → JMP/CALL [register]
            ○ EIP now points to [register] where shellcode.
        Pros:
            ○ Easy to apply.
            ○ Common instruction.
        Cons:
            ○ None.

        2. POP RET / POP POP RET / POP POP POP RET

        Condition:
            ○ Address at [ESP+4], [ESP+8], [ESP+12] (and so on) points to address to shellcode OR directly to shellcode.
        Example 1:
            ○ [ESP] → [4 bytes][Address to shellcode].
            ○ EIP → POP [register] followed by RET.
                § POP [register]: ESP now points to old_ESP + 4
                § RET: EIP now contains address to shellcode.
            ○ EIP now points to shellcode.
        Example 2:
            ○ [ESP] → [8 bytes][Address to JMP ESP][shellcode].
            ○ EIP → POP [register] followed by POP [register] followed by RET:
                § POP [register], POP [register] will get rid of 8 bytes, new ESP → old ESP + 8 (Address to JMP ESP)
                § RET places address to JMP ESP in EIP and now ESP now points to shellcode.
                § JMP ESP: EIP now contains ESP
            ○ EIP points to current ESP value which points to start of shellcode.
        Pros:
            ○ Straightforward (slightly harder than method 1).
            ○ Lots of possible combinations to find instruction.
        Cons:
            ○ Less frequent pattern.

        3. PUSH  RET

        Condition:
            ○ A register points to shellcode and can't/don't want to use method 1.
        Example:
            ○ [Register]→ [Shellcode]
            ○ EIP → PUSH [register], followed by RET
                § Stack will first push register, then pop it to EIP.
            ○ EIP now points to shellcode.
        Pros:
            ○ Easy to apply.
            ○ Fallback if method 1 can't be done.
        Cons:
            ○ None.

        4. JMP [register + offset]

        Condition:
            ○ A register + offset points to shellcode.
        Example:
            ○ [Register] → [Shellcode]
            ○ EIP → JMP [register + offset]
            ○ EIP will point to [register + offset] where the shellcode starts.
        Pros:
            ○ Easy to apply.
        Cons:
            ○ Doesn't work if [register + offset] points to address to shellcode as ESP doesn't change and a RET won't work.
           

        5. Blind return

        Condition:
            ○ Shellcode is always loaded to the same address.
            ○ Address doesn't contain a null byte.
            ○ You control at least the first 4 bytes at [ESP]
        Example:
            ○ Shellcode is always at 0xdeadbeef
            ○ Since you control the first 4 bytes at ESP, put 0xdeadbeef at ESP.
            ○ By pointing EIP to a RET, address at ESP will be popped to EIP.
            ○ EIP now points to address 0xdeadbeef where the shellcode starts.
        Pros:
            ○ Easiest method, only need a RET.
            ○ Fixed address.
        Cons:
            ○ Heavy dependency on hardcoded address.
            ○ Address can't contain null byte (good luck with stack at low address).
            ○ Assumes no ASLR.

        6. POPAD

        Condition:
            ○ Shellcode is located at [ESP + 32x + offset]
            ○ Enough controllable space to execute POPAD y times then JMP ESP.
        Example:
            ○ [ESP + 240] → [Shellcode]
            ○ [ESP + 32 * 7] → [NOP sled]
            ○ [ESP] → POPAD 7 times followed by JMP ESP
            ○ EIP → [JMP ESP]
                § EIP will execute POPAD 7 times, ESP = old_ESP + 224
                § EIP goes over NOP sled
            ○ EIP after executing NOP sled, it will point to [ESP + 240] where the shellcode starts.
        Pros:
            ○ POPAD is a single byte.
            ○ ESP gets incremented with 32 every time POPAD is executed.
        Cons:
            ○ Requires NOP sled.
            ○ Less reliable than Method 1/2/3/4

        7. Short jumps (backwards, forwards, conditional)

        Condition:
            ○ Shellcode is located at [ESP + offset] where -128 < offset < 127.
        Example:
            ○ [ESP + 30] → [Shellcode]
            ○ [ESP] → JMP 30
            ○ EIP → [JMP ESP]
                § EIP will execute a short JMP
            ○ EIP will point to [ESP + 30] where the shellcode starts.
        Pros:
            ○ Simple instruction.
            ○ Reliable, no NOP sled is needed.
        Cons:
            ○ Restricted by being a short JMP.
           

        8. Hardcoded address

        Condition:
            ○ Shellcode is always located at specific address.
        Example:
            ○ 0xdeadbeef → [shellcode]
            ○ EIP → JMP ESP
            ○ ESP → JMP 0xdeadbeef
        Pros:
            ○ Simple instruction.
        Cons:
            ○ Unreliable.
            ○ Address can't contain null bytes.

        Following repo contains some snippets on various payload generation for the techniques below: https://github.com/abatchy17/ExploitDevSnippets/tree/master/Corelan