[pwnable.kr] mistake(1 pts) :: Write-Up

두비니

·

2020. 7. 7. 23:56

 

 

 

We all make mistakes, let's move on.
(don't take this too seriously, no fancy hacking skill is required at all)

This task is based on real event
Thanks to dhmonkey

hint : operator priority

ssh mistake@pwnable.kr -p2222 (pw: guest)

 

 

mistake@ubuntu:~$ cat mistake.c
#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;
}

 

일단 실행을 시켜보면

mistake@ubuntu:~$ ./mistake
do not bruteforce...

input password:가 안뜨는 것을 볼 수 있다. 일단 코드를 분석해보자.

 

 

연산자 우선순위를 잘 보라고 했기 때문에 if문 2개를 각각 보자.

	if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0)

아마 코드의 의도는 open의 리턴값을 fd에 저장한 후, 이가 0보다 큰지 확인하는 것같다.

그러나 연산자의 우선순위는 =(대입연산자)보다 <(비교연산자)가 우선이기 때문에 open값과 0을 먼저 비교한다.

이때 성공적으로 열리면 파일 디스크립터가 반환되기때문에 open("/home/mistake/password",O_RDONLY,0400) < 0의 값은 FALSE일 것이고, 이 값이 fd에 입력되게 된다. false이기때문에 당연히 if문도 실행이 안된다.

 

 

	if(!(len=read(fd,pw_buf,PW_LEN) > 0))

두 번째 if문이다. 원래대로라면 /home/mistake/password에서 실제 비밀번호를 읽어와서 pw_buf에 입력해줬을 것이다. 하지만 fd가 0이므로, read함수는 사용자에게 입력받게된다.(stdin) 즉 우리가 비밀번호를 설정할 수 있게 되는 것이다. 실행시켰을 때 input password:가 뜨지 않았던 이유도 이때문이다.

 

 

이때 비밀번호를 비교할때는 각 자리를 xor을 해준 후 비교하므로 pw_buf는 아무거나, pw_buf2는 우리가 설정해준 pw_buf에서 xor한 값을 넣어주면 되기때문에 1111111111, 0000000000를 넣어주었다.

 

 

해킹이라기보다는 코딩실수문제 :>