The gameplan for this exploit is to send an initial payload which will call read() into the RWX memory region. From here, we send the actual /bin/sh payload which will continue executing after our stage 1 payload.

We can call read via syscall to make this shellcode small. The following must be setup for this to work:

rax - 0

rdi - file descriptor to read from, i.e. stdin

rsi - destination buffer

rdx - 0x30 : Arbitrary length to read

The rax register is already set to 0 for our read syscall, so no modification needs to happen there. The rdi register needs to be a 0 in order to read from stdin, so a simple xor rdi, rdi will accomplish this for us. The destination buffer is already stored in the rdx register when our shellcode is run, which means we only need to execute a mov rsi, rdx in order to setup our destination buffer location. Lastly, we need to set a read length, and a simple mov rdx, 0x30 will work.

Cory Duplantis

I am a senior security researcher for Cisco Talos and play on Samurai for CTFs. Being happily married, CTFs, tool development, and singing barbershop take up the majority of my time. This blog is the home for my CTF writeups, development tricks, and other random hacker tips.