0x02 Study :)/Pwnable
[pwnable.kr][Toddler] lotto 문제풀이
eli_ez3r
2018. 8. 18. 15:40
lotto
#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; }
lotto.c 의 코드를 보면 위와 같다.
여기서 봐야 할 함수는 play()함수이다.
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"); } }
사용자로 부터 6자리의 값을 submit에 저장한다. 그리고 /dev/urandom에서 6바이트를 베이스로 랜덤값 6자리를 만들어 낸다. 중요한 부분은 다음 for문이다.
for문을 살펴보면 의아하게 느껴질 것이다.
사용자가 입력한 6자리 값과, 랜덤으로 뽑아낸 6자리 값을 비교해서 match값을 증가시키고 match값이 6이면 flag가 읽어지는데, 개발자가 원하는 바는 알겠지만 잘못된 로직으로 프로그래밍을 하였다.
for문을 보면 총 36번 돌아가게 되어 있다.
따라서 사용자가 '111111'을 입력하였을 때, 랜덤값에 '1'이라는 값이 있으면 match는 6이되어 flag가 출력되게 된다.
여기서 사용자 입력한 값은 char형으로 인식하기 때문에 ascii값이 1~45사이인 값을 6번 넣으면 된다.
'*'을 넣어보았다.
랜덤 값중 42값(*의 ascii값)이 들어 갈때 까지 계속 하다보면 flag가 출력된다.
flag : sorry mom... I FORGOT to check duplicate numbers... :(