Yozzang의 해킹일기 💻
article thumbnail
Published 2022. 7. 7. 00:16
Pwnable (9. mistake) Wargame/Pwnable
728x90

이번 포스트에서는 Pwnable의 mistake 문제에 대해 다루겠다.

 


문제 코드는 다음과 같다.

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

## 문제 해석 :

pw_buf의 값과 pw_buf2의 값이 같으면 flag를 획득할 수 있는 것으로 보인다.

## 문제 풀이 :

코드를 전체적으로 살펴보았을 때 pw_buf2의 값이 XORKEY(1)로 인해 XOR연산하여 그 값이 pw_buf와 같게 하면 된다는 것을 알 수 있다. 그럼 pw_buf의 값을 알아내보겠다.

코드의 초반부분을 살펴보면 if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0)라는 줄이 보인다. open("/home/mistake/password",O_RDONLY,0400) 라는 함수는 true를 반환하므로 0이 아닌 양수값이 반환될 것입니다. 또한 여기서 중요한 것이 바로 연산자 "<"는 연산자 "="보다 빨리 실행된다는 사실이다. 즉, if(fd=(양수<0))이 되고 이는 곧 if(fd=0)이다.(양수가 0보다 클 수 없으니 0을 반환)

 

파일 디스크립터 중 0은 stdin, 즉 표준 입력이다.

 

이어서 코드를 살펴보면 다음 부분이 보인다.

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

 pw_buf와 len이 선언되고, len은 read() 함수를 통해 실행되었으며 이때의 파일 디스크립터가 fd(0, stdin)이기 때문에 입력을 받을 수 있고 그 값이 len에 저장된다. 즉, 우리의 입력에 의해 pw_buf의 값이 결정된다.

 

여기서 정리하자면, pw_buf와 pw_buf2의 값을 다 우리가 결정할 수 있고, pw_buf2의 XOR한 값이 pw_buf이며 해당 문제를 해결할 수 있다.

 

그럼 pw_buf를 임의의 값인 "AAAAAAAAAA"로 정의한 다음에 테스트 해보겠다. (pw_buf2의 버퍼 길이가 10이기때문에)

## XOR 코드 : 

#include <stdio.h>

#define XORKEY 1

void xor(char* s, int len)
{
        int i;
        for(i=0;i<len;i++) {
                s[i] ^= XORKEY;
        }
}

int main()
{
        char pw_buf2[11] = "AAAAAAAAAA";
        xor(pw_buf2, 10);

        printf("%s\n", pw_buf2);
}

## 실행 결과 : 

xor("A") = "@"

"A" 는 0x41이므로 0x41을 1로 XOR 하면 "@"이 나온 것을 확인할 수 있다.

 

## 최종 결과 : 

### 공격문 : "AAAAAAAAAA", "@@@@@@@@@@"

### 실행 결과 :

공격 실행

 

Flag = Mommy, the operator priority always confuses me :(

'Wargame > Pwnable' 카테고리의 다른 글

Pwnable (11. coin1)  (0) 2022.07.09
Pwnable (10. shellshock)  (0) 2022.07.08
Pwnable (8. leg)  (0) 2022.07.06
Pwnable (7. input)  (0) 2022.07.05
Pwnable (6. random)  (0) 2022.07.04
profile

Yozzang의 해킹일기 💻

@요짱

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!