IO Smash the stack level 10

Level10 I had a lot of issues with this level. At first I did not understand how I could exploit it so I tried several things until I finally got it. I started looking at the source code but still could not see the problem. I connected to the irc channel for help and got a few pointers on how to debug this. But the thing that helped me most I guess was this link.


IO Smash the stack level 09

Level09 level9@io:/levels$ ls -latr level09* -r-------- 1 level9 level9 182 Jan 9 2010 level09.c -r-sr-x--- 1 level10 level9 6294 Jan 9 2010 level09 level9@io:/levels$ cat level09.c #include <stdio.h> #include <string.h> int main(int argc, char **argv) { int pad = 0xbabe; char buf[1024]; strncpy(buf, argv[1], sizeof(buf) - 1); printf(buf); return 0; } A nice string format bug. Alright this should be a walk in the park using short writes when overwriting the .dtors.


IO Smash the stack level 08

Level08 level8@io:/levels$ ls -latr level08* -r-sr-x--- 1 level9 level8 14343 Sep 17 2010 level08_alt -r-------- 1 level8 level8 1927 Jan 3 2012 level08_alt.cpp -r-sr-x--- 1 level9 level8 6662 Jan 26 2012 level08 -r-------- 1 level8 level8 666 May 27 2014 level08.cpp // writen by bla for io.smashthestack.org #include <iostream> #include <cstring> #include <unistd.h> class Number { public: Number(int x) : number(x) {} void setAnnotation(char *a) {memcpy(annotation, a, strlen(a));} virtual int operator+(Number &r) {return number + r.number;} private: char annotation[100]; int number; }; int main(int argc, char **argv) { if(argc < 2) _exit(1); Number *x = new Number(5); Number *y = new Number(6); Number &five = *x, &six = *y; five.setAnnotation(argv[1]); return six + five; } I actually tried to do a overflow but couldn’t really understand why I had issues getting the return address overwritten.


IO Smash the stack level 07

Level07 level7@io:/levels$ cat level07.c //written by bla #include <stdio.h> #include <string.h> #include <unistd.h> int main(int argc, char **argv) { int count = atoi(argv[1]); int buf[10]; if(count >= 10 ) return 1; memcpy(buf, argv[2], count * sizeof(int)); if(count == 0x574f4c46) { printf("WIN!\n"); execl("/bin/sh", "sh" ,NULL); } else printf("Not today son\n"); return 0; } Oki so count has to be 10 or less to invoke the memcpy but in order to get a shell count has to be 0x574f4c46 (1464814662).


IO Smash the stack level 06

Level06 level6@io:/levels$ ls -la level06* -r-sr-x--- 1 level7 level6 5849 Dec 18 2013 level06 -r-sr-x--- 1 level7 level6 7293 Aug 11 2010 level06_alt -r-------- 1 level6 level6 487 Nov 14 2011 level06_alt.c -r-------- 1 level7 level7 22 Sep 14 03:31 level06_alt.pass -r-------- 1 level6 level6 1034 May 7 2015 level06.c level6@io:/levels$ cat level06.c //written by bla //inspired by nnp #include <stdio.h> #include <stdlib.h> #include <string.h> enum{ LANG_ENGLISH, LANG_FRANCAIS, LANG_DEUTSCH, }; int language = LANG_ENGLISH; struct UserRecord{ char name[40]; char password[32]; int id; }; void greetuser(struct UserRecord user){ char greeting[64]; switch(language){ case LANG_ENGLISH: strcpy(greeting, "Hi "); break; case LANG_FRANCAIS: strcpy(greeting, "Bienvenue "); break; case LANG_DEUTSCH: strcpy(greeting, "Willkommen "); break; } strcat(greeting, user.name); printf("%s\n", greeting); } int main(int argc, char **argv, char **env){ if(argc != 3) { printf("USAGE: %s [name] [password]\n", argv[0]); return 1; } struct UserRecord user = {0}; strncpy(user.name, argv[1], sizeof(user.name)); strncpy(user.password, argv[2], sizeof(user.password)); char *envlang = getenv("LANG"); if(envlang) if(!memcmp(envlang, "fr", 2)) language = LANG_FRANCAIS; else if(!memcmp(envlang, "de", 2)) language = LANG_DEUTSCH; greetuser(user); } Oki the insecure function here is strcat and the overflow occurs when adding to greeting.


IO Smash the stack level 05

Level05 level5@io:/levels$ ls -latr level05* -r-------- 1 level5 level5 178 Oct 4 2007 level05.c -r-sr-x--- 1 level6 level5 7140 Nov 16 2007 level05 -r-sr-x--- 1 level6 level5 8752 Feb 22 2010 level05_alt -r-------- 1 level5 level5 2954 Feb 24 2010 level05_alt.c level5@io:/levels$ cat level05.c #include <stdio.h> #include <string.h> int main(int argc, char **argv) { char buf[128]; if(argc < 2) return 1; strcpy(buf, argv[1]); printf("%s\n", buf); return 0; } Ahh a classic bufferoverflow :) First I create a pattern on my kali to find how many bytes I can do before overflowing kgn@kali:~$ /usr/share/metasploit-framework/tools/exploit/pattern_create.rb 200 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag Then we do a bufferoverflow in GDB to get the length of the buffer level5@io:/levels$ gdb -q ./level05 Reading symbols from /levels/level05...done.


IO Smash the stack level 04

Level04 level4@io:/levels$ ls -latr level04* -r-sr-x--- 1 level5 level4 5159 Dec 18 2013 level04 -r-------- 1 level4 level4 245 Dec 18 2013 level04.c -r-sr-x--- 1 level5 level4 5105 Sep 24 2014 level04_alt -r-------- 1 level4 level4 120 Jan 27 2015 level04_alt.c level4@io:/levels$ cat level04.c //writen by bla #include <stdlib.h> #include <stdio.h> int main() { char username[1024]; FILE* f = popen("whoami","r"); fgets(username, sizeof(username), f); printf("Welcome %s", username); return 0; } So it runs whoami without full path ..


IO Smash the stack level 03

Level03 level3@io:~$ cd /levels/ level3@io:/levels$ ls -latr level03* -r-------- 1 level3 level3 658 Sep 22 2012 level03.c -r-sr-x--- 1 level4 level3 5238 Sep 22 2012 level03 level3@io:/levels$ cat level03.c //bla, based on work by beach #include <stdio.h> #include <string.h> void good() { puts("Win."); execl("/bin/sh", "sh", NULL); } void bad() { printf("I'm so sorry, you're at %p and you want to be at %p\n", bad, good); } int main(int argc, char **argv, char **envp) { void (*functionpointer)(void) = bad; char buffer[50]; if(argc != 2 || strlen(argv[1]) < 4) return 0; memcpy(buffer, argv[1], strlen(argv[1])); memset(buffer, 0, strlen(argv[1]) - 4); printf("This is exciting we're going to %p\n", functionpointer); functionpointer(); return 0; } Oki so in order for us to get the shell we need to change the function pointer from bad to good.


IO Smash the stack level 02

Level02 level2@io:~$ cd /levels/ level2@io:/levels$ ls -latr level02* -r-------- 1 level2 level2 437 May 26 2011 level02_alt.c -r-sr-x--- 1 level3 level2 6940 May 26 2011 level02_alt -r-sr-x--- 1 level3 level2 5329 Oct 4 2011 level02 -r-------- 1 level2 level2 495 Apr 13 2015 level02.c This time we got source code so lets look at it level2@io:/levels$ cat level02.c //a little fun brought to you by bla #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> void catcher(int a) { setresuid(geteuid(),geteuid(),geteuid()); printf("WIN!\n"); system("/bin/sh"); exit(0); } int main(int argc, char **argv) { puts("source code is available in level02.c\n"); if (argc != 3 || !atoi(argv[2])) return 1; signal(SIGFPE, catcher); return abs(atoi(argv[1])) / atoi(argv[2]); } So in order to get the cacher function to run we need to get provide 2 arguments (argv[0] is the program itself) and the last argument must not be 0.


IO Smash the stack level 01

A colleague of mine recommended playing wargames so I started on io.smashthestack.org and will write my findings. Please notice that I do not write the passwords for levels and you should really not just try to copy but understand the challanges yourself. You will only be cheating yourself of fun :) Level01 level1@io:~$ cd /levels/ level1@io:/levels$ ls -latr level01* -r-sr-x--- 1 level2 level1 1184 Jan 13 2014 level01 No source provided so lets try to start it level1@io:/levels$ ./level01 Enter the 3 digit passcode to enter: 123 Its a passcode and I cleary didn’t get 123 right.