우리는 모두 실수를 한다. 화려한 해킹기술은 전혀 필요없으니까 심각하게 여기지 말라고 한다. 그리고 아래 나와있는 힌트를 보면 연산자 우선순위라고 나와있다.


일단 xshell을 통해 접속해보자.



이렇게 나와있다. mistake에는 setuid가 걸려있고 mistake.c파일을 확인해보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
#include <fcntl.h>
 
#define PW_LEN 10
#define XORKEY 1
 
void xor(char* s, int len){
    int i;
    for(i=0; i<len; i++){
        s[i] ^= XORKEY;
    }
}
 
int main(int argc, char* argv[]){
    
    int fd;
    if(fd=open("/home/mistake/password",O_RDONLY,0400< 0){
        printf("can't open password %d\n", fd);
        return 0;
    }
 
    printf("do not bruteforce...\n");
    sleep(time(0)%20);
 
    char pw_buf[PW_LEN+1];
    int len;
    if(!(len=read(fd,pw_buf,PW_LEN) > 0)){
        printf("read error\n");
        close(fd);
        return 0;        
    }
 
    char pw_buf2[PW_LEN+1];
    printf("input password : ");
    scanf("%10s", pw_buf2);
 
    // xor your input
    xor(pw_buf2, 10);
 
    if(!strncmp(pw_buf, pw_buf2, PW_LEN)){
        printf("Password OK\n");
        system("/bin/cat flag\n");
    }
    else{
        printf("Wrong Password\n");
    }
 
    close(fd);
    return 0;
}
 
cs


소스코드를 확인했고 이제 연산자 우선순위를 위주로 코드를 분석해보자.


전체적인 코드를 먼저 확인해보면 open함수로 패스워드 파일을 열어서 저장한 다음에 입력받은 값을 xor함수에 넣고 결과값과 패스워드를 비교해서 같으면 플래그가 읽히는 형식이다. 이 코드의 취약점은 바로 찾을 수 있었다. 먼저 아래코드를 보자.


1
2
3
4
 if(fd=open("/home/mistake/password",O_RDONLY,0400< 0){
        printf("can't open password %d\n", fd);
        return 0;
    }
cs



if조건문에 괄호가 하나 빠진 것을 확인 할 수 있다. 비교연산자 < 가 산술연산자 = 보다 우선순위가 높기 때문에 open함수의 리턴값을 fd에 저장하고 이것이 0보다 작은지 비교하려는 원래의 의도에서 벗어나 open함수의 리턴값이 0보다 작은지 비교하고 이 결과가 fd값에 들어가는 것이다.


아래 코드 또한 위 코드와 비슷하다.


1
2
3
4
5
  if(!(len=read(fd,pw_buf,PW_LEN) > 0)){
        printf("read error\n");
        close(fd);
        return 0;        
    }
cs


이 코드또한 괄호 하나가 빠져서 read함수의 리턴값이 0보다 큰지 비교하고 이 결과값이 len에 들어가게 된다.


여기서 아까 전에 봤던 fd가 들어간 if문을 생각해보자. open함수에서 파일이 정상적으로 열렸으므로 open함수는 파일디스크립터 번호인 음이 아닌 정수를 리턴하게 된다. 그러면 open("/home/mistake/password", O_RDONLY, 0400) < 0이 거짓이고 fd는 0이 된다.


fd가 0이므로 read(0, pw_buf, PW_LEN)이 실행되었을 때 pw_buf에 우리가 원하는 값을 넣을 수 있게 된다!


pw_buf와 pw_buf2모두 우리가 우너하는대로 값 설정이 가능하니까 플래그 얻기는 식은죽먹기다~!~!


scanf("%10s", pw_buf2); 를 통해 pw_buf2에 1111111111을 넣고 xor함수에서 각 배열의 값을 1과 xor시키니까 pw_buf를 0000000000으로 세팅하면 플래그가 얻어질 것이다! 직접 해보자~!



성공이다!

'pwnable > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] coin1  (0) 2019.06.25
[pwnable.kr] shellshock  (0) 2019.02.27
[pwnable.kr] leg  (0) 2019.02.20
[pwnable.kr] input  (0) 2019.02.18
[pwnable.kr] random  (0) 2019.01.15

+ Recent posts