Another challenge, another mistake in code. Lotto challenge from pwnable.kr.

Mommy! I made a lotto program for my homework.
do you want to play?


ssh [email protected] -p2222 (pw:guest)

Solution

Let’s log in into provided ssh server and as we have the executable, run the file.

main:~ > ssh [email protected] -p2222
[email protected] password:
 ____  __    __  ____    ____  ____   _        ___      __  _  ____  
|    \|  |__|  ||    \  /    ||    \ | |      /  _]    |  |/ ]|    \
|  o  )  |  |  ||  _  ||  o  ||  o  )| |     /  [_     |  ' / |  D  )
|   _/|  |  |  ||  |  ||     ||     || |___ |    _]    |    \ |    /
|  |  |  `  '  ||  |  ||  _  ||  O  ||     ||   [_  __ |     \|    \
|  |   \      / |  |  ||  |  ||     ||     ||     ||  ||  .  ||  .  \
|__|    \_/\_/  |__|__||__|__||_____||_____||_____||__||__|\_||__|\_|

- Site admin : [email protected]
- IRC : irc.netgarage.org:6667 / #pwnable.kr
- Simply type "irssi" command to join IRC now
- files under /tmp can be erased anytime. make your directory under /tmp
- to use peda, issue `source /usr/share/peda/peda.py` in gdb terminal
Last login: Wed Feb  7 11:36:50 2018 from 217.209.225.118
[email protected]:~$ ls -la
total 44
drwxr-x---  5 root      lotto  4096 Oct 23  2016 .
drwxr-xr-x 87 root      root   4096 Dec 27 23:17 ..
d---------  2 root      root   4096 Feb 18  2015 .bash_history
-r--r-----  1 lotto_pwn root     55 Feb 18  2015 flag
dr-xr-xr-x  2 root      root   4096 Feb 18  2015 .irssi
-r-sr-x---  1 lotto_pwn lotto 13081 Feb 18  2015 lotto
-r--r--r--  1 root      root   1713 Feb 18  2015 lotto.c
drwxr-xr-x  2 root      root   4096 Oct 23  2016 .pwntools-cache
[email protected]:~$ ./lotto
- Select Menu -
1. Play Lotto
2. Help
3. Exit
1
Submit your 6 lotto bytes : 123456
Lotto Start!
bad luck...
- Select Menu -
1. Play Lotto
2. Help
3. Exit
3
bye
[email protected]:~$

So that’s another guessing game. We can look at help option to look for hints.

[email protected]:~$ ./lotto
- Select Menu -
1. Play Lotto
2. Help
3. Exit
2
- nLotto Rule -
nlotto is consisted with 6 random natural numbers less than 46
your goal is to match lotto numbers as many as you can
if you win lottery for *1st place*, you will get reward
for more details, follow the link below
http://www.nlotto.co.kr/counsel.do?method=playerGuide#buying_guide01

mathematical chance to win this game is known to be 1/8145060.

To be honest, that’s not much here so let’s get into the code.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

unsigned char submit[6];

void play(){

	int i;
	printf("Submit your 6 lotto bytes : ");
	fflush(stdout);

	int r;
	r = read(0, submit, 6);

	printf("Lotto Start!\n");
	//sleep(1);

	// generate lotto numbers
	int fd = open("/dev/urandom", O_RDONLY);
	if(fd==-1){
		printf("error. tell admin\n");
		exit(-1);
	}
	unsigned char lotto[6];
	if(read(fd, lotto, 6) != 6){
		printf("error2. tell admin\n");
		exit(-1);
	}
	for(i=0; i<6; i++){
		lotto[i] = (lotto[i] % 45) + 1;		// 1 ~ 45
	}
	close(fd);

	// calculate lotto score
	int match = 0, j = 0;
	for(i=0; i<6; i++){
		for(j=0; j<6; j++){
			if(lotto[i] == submit[j]){
				match++;
			}
		}
	}

	// win!
	if(match == 6){
		system("/bin/cat flag");
	}
	else{
		printf("bad luck...\n");
	}

}

void help(){
	printf("- nLotto Rule -\n");
	printf("nlotto is consisted with 6 random natural numbers less than 46\n");
	printf("your goal is to match lotto numbers as many as you can\n");
	printf("if you win lottery for *1st place*, you will get reward\n");
	printf("for more details, follow the link below\n");
	printf("http://www.nlotto.co.kr/counsel.do?method=playerGuide#buying_guide01\n\n");
	printf("mathematical chance to win this game is known to be 1/8145060.\n");
}

int main(int argc, char* argv[]){

	// menu
	unsigned int menu;

	while(1){

		printf("- Select Menu -\n");
		printf("1. Play Lotto\n");
		printf("2. Help\n");
		printf("3. Exit\n");

		scanf("%d", &menu);

		switch(menu){
			case 1:
				play();
				break;
			case 2:
				help();
				break;
			case 3:
				printf("bye\n");
				return 0;
			default:
				printf("invalid menu\n");
				break;
		}
	}
	return 0;
}

Firstly, we notice that unsigned char lotto[6]; is a char variable, so only printable characters. As this lotto takes only numbers in range 1-45, it leaves us with the range of 33 - 45. Looking at the ASCII table, characters with these codes are !"#$%&'()*+,-.

But after that, we can also notice another bug.

// calculate lotto score
int match = 0, j = 0;
for(i=0; i<6; i++){
  for(j=0; j<6; j++){
    if(lotto[i] == submit[j]){
      match++;
    }
  }
}

These piece of code means that for each character in the lotto, it will iterate every character in the input. So we can just enter any possible character six times, and with a little bit of luck, we’ll get the match and win the game.

Submit your 6 lotto bytes : $$$$$$
Lotto Start!
sorry mom... I FORGOT to check duplicate numbers... :(
- Select Menu -
1. Play Lotto
2. Help
3. Exit
3
bye