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

LOB 7번 풀이 (darkelf) 본문

wargame 풀이/LOB

LOB 7번 풀이 (darkelf)

yehey 2020. 11. 10. 12:19
id: darkelf
pw: kernel crashed
/*
        The Lord of the BOF : The Fellowship of the BOF
        - orge
        - check argv[0]
*/

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

        // here is changed!
        if(strlen(argv[0]) != 77){
                printf("argv[0] 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보다 길어서는 안됨
  • argv[0]의 strlen이 77이어야 함 (argv[0]은 실행파일 명)

orge 디스어셈블

스택 구조는 이전 문제들과 같으므로 생략

이번에도 buffer를 초기화하기 때문에 쉘 코드를 저장할 다른 공간을 찾아주어야 한다.

wolfman에서는 argv[2]를 사용했으나, 이번에는 exploit 코드로 전달이 잘 되지 않아서 다른 방법을 찾아야 했다.

그래서 일단 orge gdb에서 main에 breakpoint를 걸고 argv[1]에 인자로 "\x90"을 48바이트 전달해보았다.

 

그리고 esp를 확인해보았더니 buffer로 추정되는 부분은 0으로 초기화 되어있었고 (0xbffffbf9 부터 40바이트)

더 아래를 보면 "\x90"이 48바이트 만큼 (내가 입력한 만큼) 특정 공간에 남아있었다.

즉, buffer는 초기화해도 argv[1]은 초기화 되지 않고 남아있다.

따라서 이전처럼 argv[1]에 NOP와 쉘 코드를 넣어 전달해주고 ret 주소에는 buffer 시작주소가 아닌 argv[1]의 주소를 넣어주자.

 

그러면 argv[1]의 주소를 알아내기 위해 orge.c를 복사해서 코드를 살짝 수정한 후 컴파일해서 실행해보자

/*
        orge2의 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);
        }
        printf("argv[1] addr: %x\n",argv[1]);	//argv[0] 체크 전에 argv[1]의 주소 출력
        
        // here is changed!
        if(strlen(argv[0]) != 77){
                printf("argv[0] 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", buffer);

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

 

실행할 때는 exploit 코드와 최대한 동일하게 작성하는 것이 좋다. 전달하는 argv[1]가 달라지면 주소도 달라질 수 있기 때문이다.

 

앞서 코드를 분석했을 때 argv[0] 즉, 실행파일 명이 77이어야 정상적으로 실행되기 때문에 실행파일명의 길이를 77바이트로 늘려주어야한다. "/"는 여러개를 사용해도 1개로 인식하기 때문에 "/"을 이용해 77을 맞춰주자. 

 

실행한 결과 0xbffff9e0이 argv[1]의 주소이다.

따라서 orge에 NOP와 쉘 코드를 전달해주고 ret에는 argv[1]의 주소인 0xbffff9e0을 넣어주자

 

orge 권한으로 bash 쉘이 실행되었다.

 

orge의 pw: "timewalker"

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

LOB 9번 풀이 (troll)  (0) 2020.11.21
LOB 8번 풀이 (orge)  (0) 2020.11.19
LOB 6번 풀이 (wolfman)  (0) 2020.11.07
LOB 5번 풀이 (orc)  (0) 2020.11.06
LOB 4번 풀이 (goblin)  (0) 2020.11.02
Comments