본문으로 바로가기

[pwnable.kr] blukat 풀이, write-up

category Wargame/pwnable.kr 2018. 12. 24. 19:12

pwnable.kr --- blukat



ssh blukat@pwnable.kr 2222 (pw: guest)로 접속하면 blukat 문제를 만날 수 있다.


windows 환경의 cmd로 접속한것이 아니라 xshell5로 접속했다.


windows 환경의 cmd로 접속하려면 ssh blukat@pwnable.kr -p2222 (pw: guest)로 접속해야한다.



우선 현재 디렉터리에 어떤 파일이 존재하는지 확인해보자.





우리가 공격해야할 대상인 blukat과 blukat을 만들었을 source로 예상되는 blukat.c가 존재한다.


blukat에 setgid가 blukat_pwn 권한으로 걸려있고, password 파일 또한 blukat_pwn의 gid를 가지고 있다.


이로 미루어보아, blukat이 password를 사용할 것으로 짐작할 수 있다.


blukat을 분석하기 위해 blukat.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
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
 
char flag[100];
char password[100];
char* key = "3\rG[S/%\x1c\x1d#0?\rIS\x0f\x1c\x1d\x18;,4\x1b\x00\x1bp;5\x0b\x1b\x08\x45+";
 
void calc_flag(char* s){
    int i;
    for(i=0; i<strlen(s); i++){
        flag[i] = s[i] ^ key[i];
    }
    printf("%s\n", flag);
}
 
int main(){
    FILE* fp = fopen("/home/blukat/password""r");
    fgets(password, 100, fp);
    char buf[100];
    printf("guess the password!\n");
    fgets(buf, 128, stdin);
    if(!strcmp(password, buf)){
        printf("congrats! here is your flag: ");
        calc_flag(password);
    }
    else{
        printf("wrong guess!\n");
        exit(0);
    }
    return 0;
}
cs



fopen() 함수를 이용해 "/home/blukat/password" 경로의 파일을 read 권한으로 읽어 File pointer fp에 저장한다.

fgets() 함수를 이용해 password 배열에 100 byte 만큼 fp가 가리키는 파일의 내용을 저장한다.



1
2
3
int main(){
    FILE* fp = fopen("/home/blukat/password""r");                                
    fgets(password, 100, fp);
cs



100 byte char 배열 buf를 선언한다.

"guess the password!\n"를 출력한다.

사용자로부터 buf에 128 byte 입력을 받는다.



1
2
3
    char buf[100];
    printf("guess the password!\n");                                            
    fgets(buf, 128, stdin);
cs



만일 사용자가 입력한 문자열과, "/home/blukat/password"의 문자열이 일치한다면

"congrats! here is your flag: "를 출력하고, calc_flag()를 출력한다.


만일 일치하지 않는다면 "wrong guess!\n"를 출력하고 프로그램을 종료한다.



1
2
3
4
5
6
7
8
9
    if(!strcmp(password, buf)){
        printf("congrats! here is your flag: ");                                
        calc_flag(password);
    }
    else{
        printf("wrong guess!\n");
        exit(0);
    }
    return 0;
cs



calc_flag() 함수의 내용은 다음과 같다.


char *key 가 전역 변수로 선언되어 있고, parameter로 전달된 s의 길이만큼 parameter의 1byte와 key의 1byte를 xor 연산해 결과값을 flag에 배열에 저장하고 flag 배열을 출력한다.



1
2
3
4
5
6
7
8
9
char* key = "3\rG[S/%\x1c\x1d#0?\rIS\x0f\x1c\x1d\x18;,4\x1b\x00\x1bp;5\x0b\x1b\x08\x45+";
 
void calc_flag(char* s){
    int i;
    for(i=0; i<strlen(s); i++){
        flag[i] = s[i] ^ key[i];
    }
    printf("%s\n", flag);
}
cs




우리가 원하는 flag를 획득하기 위해서 password 파일은 권한 없어 볼 수 없고, password를 모르는 상태로, password의 내용을 맞춰야한다. 왜냐하면 반드시 strcmp(password, buf)가 성공하기 위해서는 buf를 입력하는 사용자가 password의 내용을 알아야하기 때문이다.


즉, 문제 제작자는 어떤 방식으로 password 파일에 접근하거나 볼 수 있도록 했다는것인데...


권한의 문제였다는것을 확인했다. ㅋㅋㅋㅋㅋㅋㅋㅋ





현재 uid는1104(blukat)이고, gid가 1105(blukat_pwn)으로 걸려있다.

즉, 우리는 password에 접근할 수 있고, pasword의 내용이 "cat: password: Permission denied"이다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ





현재 사용자의 권한을 자세히 확인하자는 의도의 문제이다. 9reat!!!