[pwnable.kr] lotto - 2 pt
lotto다 로또!
이번에는 토끼처럼 생긴 카드에 적혀잇다. 문제를 보자
로또 프로그램을 숙제로 만들었는데 한번 플레이해보겠냐는것 같다.
보면 알겠지만 lotto파일에 setuid가 걸려있고, 읽을 수 있는 파일은 lotto.c밖에 없다.
내용을 한번 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #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; } | cs |
이렇게 돌아가는 소스코드이다. /dev/urandom 을 이용하여 0~45의 값을 가지는 6바이트의 랜덤값을 가져오고
사용자에게 6바이트를 입력받아 비교한 후 6개의 값이 같다면 /bin/cat flag를 실행하여 플래그를 출력해준다.
처음에는 urandom에 취약점이 있는가 싶었지만...
사용자한테 입력받은 값과 랜덤6바이트를 비교하는 과정에서 취약점이 있었다.
1 2 3 4 5 6 7 8 9 | // 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++; } } } | cs |
위에 보면 알겠지만 2중 for문을 사용하고 있는데, lotto[i]를 고정해두고 submit의 모든 값과 비교해서 1개라도 일치하면 match값을 증가시킨다.
이렇게 할 경우 만약 submit에 같은 값만 들어있을 경우 lotto[i]와 submit[j] 중 일치하는 값이 하나만 존재하여도 match의 값은 6으로 바로 증가할 수 잇을 것이다.
그러므로 submit의 값 6개를 모두 같은 값(0~45)을 입력하고 랜덤한 lotto값 6바이트중에 우리가 입력한 값이 포함된다면 플래그를 얻을 수 있을 것이다.
아스키코드표를 보면 32~45까지는 표현할 수 있는 아스키값이므로 임의로 '!'=33을 선택하여
성공할 때까지 프로그램을 돌려보기로 하였다.
잉? 한번에 성공해서 당황했다. 적어도 6/46이니까 7~8정도 돌릴줄 알았는데....ㅋㅋ
운이 좋았다... 진짜 로또였으면 대박이였을텐데.... 큭;
어쨋든 클리어..ㅋㅋ
'Wargame > Pwnable.kr' 카테고리의 다른 글
[pwnable.kr] flag - 7 pt (0) | 2018.05.14 |
---|---|
[pwnable.kr] input - 4 pt (0) | 2018.05.10 |
[pwnable.kr] bof- 5 pt (0) | 2018.05.09 |
[pwnable.kr] collision - 3 pt (0) | 2018.05.02 |
[pwnable.kr] blackjack - 1 pt (0) | 2018.05.01 |