서브웨이

pwnable.kr mistake 풀이 본문

Pwnable/pwnable.kr

pwnable.kr mistake 풀이

샌드위치메이커 2020. 8. 14. 15:47

자 읽어보니 뭔가 실수에 관한거랍니다. 힌트도 있습니다. 연산의 우선순위를 생각하라네요.

일단 접속해봅시다.

이렇게 4개의 파일이 있네요.

 

일단 소스코드부터 봅시다.

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

코드를 읽어보니 간단히 bruteforce 공격을 막기 위해 20초 이내의 랜덤한 시간을 기다린 후 사용자로 부터 10자리의 문자열을 입력받아서 xor 함수를 거치고 그 값을 패스워드 파일의 값과 비교하네요.

근데 잘 읽어보다보면 open하는 부분에서 괄호를 치는것을 깜빡한 것 같습니다.

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

정상적인 코드라면 이렇게 되어야합니다.

하지만 문제의 코드에선 실수를 했기 때문에 open이 성공하면 1이 반환되고, 1은 0보다 크기에 fd는 0이 되어버립니다.

en.cppreference.com/w/c/language/operator_precedence

 

C Operator Precedence - cppreference.com

The following table lists the precedence and associativity of C operators. Operators are listed top to bottom, in descending precedence. Precedence Operator Description Associativity 1 ++ -- Suffix/postfix increment and decrement Left-to-right () Function

en.cppreference.com

자세한 연산의 우선순위는 이곳을 참조하시면 됩니다.

 

자 그럼 이 이후로 fd를 사용하는 곳은 전부 stdin을 사용하게 됩니다.

if(!(len=read(fd,pw_buf,PW_LEN) > 0)){
	printf("read error\n");
	close(fd);
	return 0;
}

그럼 당연히 이곳에서도 문제가 생기겠죠? 그런데 여기서도 실수를 했네요. 또 괄호치는 것을 잊어버렸네요.

그럼 fd가 stdin이 되어버리니 사용자로부터 입력을 받아 pw_buf에 저장하고 read에 성공한 바이트만큼 반환합니다. 그 값은 0보다 크기때문에 참이 되어 len은 1이 되어버리고 !연산을 통해 false가 되어서 결국 if문은 들어가지 않고 정상적인 진행이 되어버립니다.

그 상태에서 사용자로부터 다시 패스워드를 입력받아 pw_buf2에 저장하고 pw_buf2의 값을 한 바이트씩 1과 비트 xor 시켜준 뒤 pw_buf의 값과 같은지 비교하게 됩니다.

 

그럼 이 문제를 풀려면 간단히 처음 입력에서 0을 10개 넣어주고 두번째 입력에서 1을 10개 넣어주면 됩니다.

정확히는 아스키 코드표를 보고 두번째 입력의 값에 한글자씩 1과 비트 xor을 시켜준 값이 첫번째 입력값과 같으면 됩니다.

짜잔

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

pwnable.kr coin1 풀이  (0) 2020.08.18
pwnable.kr shellshock 풀이  (0) 2020.08.17
pwnable.kr leg 풀이  (0) 2020.08.13
pwnable.kr input 풀이  (0) 2020.08.11
pwnable.kr random 풀이  (0) 2020.08.11
Comments