Stack unrolling

Hello.
In this blog, I will talk about stack unrolling techniques which is mostly used on kernel exploit.
The Goal behind stack unrolling is primarily to avoid crash after buffer is overwritten, by returning to the calling function, the target software can continue to run without segmentation fault alike.

This is mainly used on kernel exploit because, often kernel exploit is broken into multiple parts to achieve successful remote code execution in case of a remote bug. we'll apply this techniques in the case of a generic remote freebsd kernel exploit. 

This allow us to overcome the limitation of payload size, by sending multiple payload separately.
I'm using a Linux distribution Ubuntu with gdb-peda and ASLR disabled.
Disabling ASLR in Ubuntu :  
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space 
 
We use the vulnerable c server below for demo.


We have a buffer overflow vulnerability in stack_two function. It's take the length used in the memcpy from the packet without checking it's size against the actual buffer size. 
Compilation:
gcc -fno-stack-protector -o server-vuln server-vuln.c
./server-vuln 8080


Here is our exploit:


 First let's run first the exploit before explaining it's internal.
                                                       Figure 1: The server running on port 8080
                                                         Figure 2: The actual exploit sending payload multiple time

In General, the exploit use ROP gadget to make the stack executable by using the current value of RSP and by calling mprotect. Our actual payload to unroll the stack is located on the stack just before the ROP gadget address.

The shellcode used to unroll the stack is extracted from this assembly code


The role of the shellcode is:
- Increment the value of RSP
- Check for first signature on the stack 
- jump to start if not egal
- check for a second signature 
- jump again if not egal
- adjust the value of RSP
- Popping rbp
- ret

The signature in our case is the local IP address located on the stack in the function server_accept. This function declare a struct sockaddr which used to
store the IP address of the connected client.

The shellcode walk the stack from stack_two stack frame upward until it match a signature. Because we are exploiting the server from localhost, we are looking for the local address IP as signature on the stack.
If we were exploiting this from a remote machine, then we just look for our own ip address in the stack.


                                              Figure 3: Backtrace, frame for server_accept


In our case:
&clientAddr: 0x7fffffffdd20
rbp at 0x7fffffffdd40 

The difference is 0x20.
Once the signature matched, we add 0x20 to the current RSP, and as we want to return in the  main function we pop rbp and execute ret.

The server can continue it's normal execution.
In one image.

Now you can add an additional payload before the stack unrolling payload like an arbitrary write primitive.
 
        mov rax, destaddr
        mov rbx, data
        mov QWORD [rax], rbx

        
Using this you can send multiple 8 bytes separately from network while keeping the serve running without any crash.

We'll apply this in the Freebsd kernel generic remote exploit.




Comments