CTF: DefCamp CTF Finals 2016
Binary: dctf-2016-exp300
Libc: libc
Points: 300
Category: PWN

Description

ssh user@server
get flag

TL;DR

The program reads string from argv[1] and saves it in two structures on the heap. There is a buffer overflow vulnerability, which we use to gain control over the program and use ROP to read the flag file.

The research

The provided binary is 64-bit elf, dynamically linked and stripped. Let’s look at the entery point:

And main function:

We have interesting fragment at the begining: call to http://man7.org/linux/man-pages/man2/personality.2.html, which, with the given argument, disables ASLR. Since ASLR was disabled on server this did nothing.
Side note: ASLR was turned on at the begining. We think the idea behind personality, fork was to turn ASLR off just on this binary, but that could not possibly work since fork copies (on-write) whole memory mappings. Maybe there was an exec call missing?:)

There are two functions calls to inspect. First gets as its only argument freshly allocated memory and just sets some pointer at the begining of it.

Second gets pointer to heap as its first argument and argv[1] as second. This function copies argv[1] into our memory at offset 8.

It uses strcpy without any validation of source length. Main functions calls new(0x28) two times and due to overflow we can overwrite second allocated buffer by providing long enough string to overflow first.

After calling those functions we have a call to a pointer located in the first 8 bytes of allocated memory (note that there is 0x10 added to that pointer first).
Since we have previously mentioned memory overflow, we can gain control over the execution.

The pwn

We had ssh credentials and the binary had SGID bit set on. Our goal was to read file with flag inside it (this file was owned by same group as binary).
Because /bin/sh was pointing to /bin/dash on the server we had to either run it with -p option (do not reset euid/egid) or open the flag file with shellcode.
We have chosen to open the file, spawn shell and read from file descriptor no. 3 (exec saves file descriptors).
The server had ASLR turned off, which allowed to use fixed addresses on stack and in libc.
The plan was to:

  1. Use overflown address to lift stack pointer.
  2. Use return oriented programing to open the flag file and spawn shell.

Here is dump of gadgets in servers libc:
rop gadgets

Exploit:

Empty strings are used to get NULL byte on stack (stack and libc addresses have two NULL bytes as their most significant bytes).
This version works locally, we just had to change base_libc address and flag_addr (stack) on the server (LD_PRELOAD was ignored on the server since there was no libc_).

Run it:

To get the flag:
DCTF{a60354f3d3879d392df2e2da819d83e2}
Tagged with:

Leave a Reply