pwnable.kr - mistake

2 minute read

Lets view the source code of the binary,

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

Lets try running the program,

mistake@pwnable:~$ ./mistake 
do not bruteforce...
aaaaabbbbb
input password : aaaaabbbbb
Wrong Password

Its asking input twice, but on the code we are using scanf only one time

Lets take a deep look into this,

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

On this condition d=open("/home/mistake/password",O_RDONLY,0400) < 0 it tries to open this file /home/mistake/password, if this file is present then the value of open("/home/mistake/password",O_RDONLY,0400) will be 1

If the file gives error while reading it, the value will be 0

If the file password is present, then d= 1 < 0 which is equal to d = 0

If the file password is not available, then d= 0 < 0 which is equal to d = 1 and it exits with return 0

Trying it without password file,

aidenpearce369@amun:~/mistake$ ./mistake 
can't open password 1

It is noted that there are two constants on the code,

#define PW_LEN 10
#define XORKEY 1

Speaking about our first input, this is where it gets its input

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

Here pw_buf of 11 bytes is created, and input is read here len=read(fd,pw_buf,PW_LEN)

If the length of pw_buf is not greater than zero, it exits with the error message

Now the actual input begins here,

    char pw_buf2[PW_LEN+1];
	printf("input password : ");
	scanf("%10s", pw_buf2);

And here XOR is done using xor(pw_buf2, 10), where the function is given as

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

So it does XOR with the char array of length equal to first 10 bytes with XOR key value of 1

Finally, it compares the encoded XOR input from pw_buf2 with our first input pw_buf

If its same, we can read our flag or it throws an error

Lets pass AAAAABBBBB as our first input

The XOR of A with key is @ and XOR of B with key is C

mistake@pwnable:~$ ./mistake 
do not bruteforce...
AAAAABBBBB
input password : @@@@@CCCCC
Password OK
Mommy, the operator priority always confuses me :(

Yay!! We got the flag Mommy, the operator priority always confuses me :(