Time to get serious
Over the last couple of months, we do a lot of ROP exploitation to bypass the anti-exploit mechanism that enforces by many modern OS. This approach is good because it gives us the flexibility to craft our own exploit by reusing a specific part of the program.
But it needs a lot of work and relatively hard to get it right since the necessary gadget may not available and ASLR will make it harder, not to mention it cannot be implemented cross-platform so it is not really that flexible.
so is there any other approach for ROP to make it more compact and able to run cross-platform?
introduces Sigreturn ROP (Signal Return Oriented Programming)
What is SigROP?
Think SigROP as just like another type of ROP attack that you can do besides the regular one. The attack works by abusing the way in which most UNIX systems return from a signal handler so we can forge the signal context to emulate its own stack frame at runtime.In layman term, if we manage to take control of the instruction pointer and chained it with ROP gadget that calls sigreturn() function we can set our own register and flags to execute any syscall. When the function is finished, it will restore the original CPU context
pretty neat huh ?!
this is the structure of stack(sigcontext structure) that we must push upon calling the sigreturn function
Don't worry using pwntools you don't have to fill every part of register and flags inside the structure (The size of the stack is 248 bytes)
Warm-Up
Now that we have the basic knowledge, it is time to do some warm-up before going to the real challengecreate the following program with this source code
#include <stdio.h>
#include <stdlib.h>
void syscall_(){
__asm__("syscall; ret;");
}
void set_rax(){
__asm__("movl $0xf, %eax; ret;");
}
int main(){
// ONLY SROP!
char buff[100];
printf("Buff @%p, can you SROP?\n", buff);
read(0, buff, 5000);
return 0;
}
source: https://0x00sec.org/t/srop-signals-you-say/2890
compile it with: gcc vuln.c -o vuln -fno-stack-protector -no-pie
we are gonna do exploitation using sigROP and as you may notice that we put some helpful gadget to help us call the sigreturn function and we leak the stack address since the ASLR is on
We need to crash the program in order to know how much padding we need to supply for taking over the RIP register. As you can from the above figure we can control the instruction pointer by supplying 120 bytes of char.
so our plan is to create an exploit that will call sigreturn and then emulate the stack to set register for calling mprotect function
We create our first part of the code like this, the code inside the Redbox is responsible to get the leaked address and stored into the variable for later used and the leaked address will be used to save our shellcode location
Also by getting the leaked address of the stack, we can determine the base address by overwriting the last three number with "000"
The second part will be constructing the gadget to call the sigreturn function we don't have to worry since we already provide the necessary gadget at the source code earlier.
now, this is the fun part, where we set up our own stack frame. Notice that we don't need to set up all of the register, only the one that is necessary to call mprotect() function.
- RAX will hold the syscall number for mprotect
- RDI as the register to hold the first parameter of mprotect that define the start of the address( you can get the value by typing "vmmap" in your gdb-peda)
- RSI as the register to hold the second parameter that defines the size of affected memory
- RDX as the register to hold the third parameter that defines the permission that we want to set, which in this case will be "RWX" (7)
- RSP we need to set the stack pointer so that it can hold payload and the stack frame(remember the 248 is the size of the stack frame)
- RIP will set to have syscall address so we can execute mprotect
Let's run it at GDB and see how it goes. I put a breakpoint at the read function
once it hits the breakpoints just continue the execution until it arrived at "ret" instruction.
we can see that it execute our ROP to prepare a call for sigreturn function and if you continue down the line. We managed to change the permission of the stack into executable again. (Pay Attention to the register! you can see that it temporarily changed based on our set up sigframe to call mprotect function)
cool! now we are able to change the permission of program memory and we can use this to make the stack executable again and put shellcode in there.
all we have to is just changing the rdi register value in frame stack pointing to stack address and we change the "AAAA" value earlier to be shellcode address
Run the exploit script and we got a shell, yeayy!!!!!
Ok, so that's the end of this post because I don't want you guys to be overwhelmed with the material I decided to split this post into two part, next, we are going to use sigreturn ROP to bypass NX and ASLR.
Hope you enjoy this post :)
references:
https://thisissecurity.stormshield.com/2015/01/03/playing-with-signals-an-overview-on-sigreturn-oriented-programming/
https://www.cs.vu.nl/~herbertb/papers/srop_sp14.pdf
https://amriunix.com/post/sigreturn-oriented-programming-srop/
Comments
Post a Comment