# SaaS - Syscall as a Service__Category__: Pwn   __Points__: 100  
> You've heard of software as a service,  > but have you heard of syscall as a service?>> Attachement: [saas](./saas)
__Important:__   This writeup is an addition to the other writeupsof this challenge. The other writeups show how to read theflag file but this writeup shows how to get full code execution.   Make sure to read [this writeup](https://github.com/Heinzeen/ctf/blob/master/Nahamcom_2020/saas/saas_writeup.md) by [Heinzeen](https://github.com/Heinzeen) to see the intended solution for this challenge.
### Quick RecapThe program lets us make arbitrary amd64 system calls except:- sys_execve- sys_fork- sys_clone- sys_kill- sys_ptrace- sys_tkill- stub_execveat
The return value of the system call is echoed back to the user.
Also the binary has all protections enabled:```RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified       Fortifiable  FILEFull RELRO      Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   77 Symbols     Yes      0               1       saas```
### Exploit StrategyIf the binary wouldn't be position independent, executing shellcode would be trivial: Just mark the text-segment as writable with mprotect() and overwrite .text with our shellcode.Unfortunately we are completely blind.
As the other writeups show, we can use mmap() to get our data into the process.Since mmap() can create executable regions we can use thisto store shellcode that pops a shell (see [shellcode.asm](./shellcode.asm)).    The only question that remains is: How do we get control over the instruction pointer with system calls?   And that's where signals come in handy!    If we manage to recrate the following code snippet we can get full code execution:```cvoid* shellcode = mmap(NULL, 0x1337, PROT_READ | PROT_WRITE | PROT_EXECUTE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);read(0, shellcode, 0x1337);signal(SIGHUP, shellcode);raise(SIGHUP);```Note that SIGHUP is chosen arbitrarily. We can use any other signal.
### Installing a Signal HandlerLet's recreate```csignal(SIGHUP, shellcode)```with some system calls.   The system call that installs a signal handler is ```sys_rt_sigaction``` (number 13). It takes the following arguments:![](./img/rt_sigaction.png)The ```struct sigaction``` looks like this:```cstruct kernel_sigaction{    __sighandler_t k_sa_handler;    unsigned long sa_flags;    void (*sa_restorer) (void);    sigset_t sa_mask;};``````k_sa_handler``` is the handler function for the signal. This will be the address of our shellcode. ```sa_flags``` and ```sa_mask``` will be 0 since we don't want any special behaviour. ```sa_restorer``` normally contains a pointer to a function that restores the state of the process right before the signal handler was executed. This is where sigreturn normally comes into play. In our case this field doesn't matter becauseexecve will replace the process anyway but in the exploit script I set this to the address of our shellcode.    
```oact``` also doesn't matter and can be NULL and ```sigsetsize``` is 8.
### Delivering a signalI chose to deliver a signal with the ```sys_tgkill``` system call (number 234). This system call just takes a process id and a signal and delivers that signal to the process. Nothing special.
### Crafting the exploitWe can now combine everything into following exploit:1. mmap() a region for our shellcode (must be executable)2. Write our shellcode into the region3. mmap() a region for the ```struct sigaction```4. Write the following values into it:    - ```k_sa_handler``` = shellcode  - ```sa_flags``` = 0  - ```sa_restorer``` = shellcode (but doesn't matter really)  - ```sa_mask``` = 05. Install the signal handler6. Deliver the signal7. ???8. Profit
See [exploit.py](./exploit.py) for a concrete implementation.