Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
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
Archives
Today
Total
관리 메뉴

White Security

Lotto 문제풀이 본문

Wargame Writeups/pwnable.kr

Lotto 문제풀이

POSIX 2019. 2. 10. 09:55
Mommy! I made a lotto program for my homework.
do you want to play?


ssh lotto@pwnable.kr -p2222 (pw:guest)


Toddler's Bottle 13번 문제


로또 프로그램에 관한 문제로

ssh 계정이 주어집니다.


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


소스코드를 열람할 수 있는데


6자리의 로또 프로그램으로

랜덤으로 생성된 데이터와

사용자가 입력한 데이터가 일치하면

플래그가 출력됩니다.


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


리눅스에서 의사난수를 생성하는

특수파일 /dev/urandom을 사용하여

1 ~ 45 범위의

6바이트를 구성하도록 되어 있습니다.


본래의 로또라면

사용자 입력을 받은 후

그 둘을 대조해 전체가 동일하면 

플래그를 출력하는것이 옳겠지만


코딩 오류로 인해

단 하나만 동일하면  2중 for 문 안에서

match 값이 6이 되어

플래그를 출력합니다.


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


따라서 1 ~ 45 범위의 아스키코드를

가지는 반복 문자열을 계속해서 등록하면

높은 확률로 플래그가 출력됩니다.


The random number generator gathers environmental noise from device drivers and other sources into an entropy pool. The generator also keeps an estimate of the number of bits of noise in the entropy pool. From this entropy pool random numbers are created.

When read, the /dev/random device will only return random bytes within the estimated number of bits of noise in the entropy pool. /dev/random should be suitable for uses that need very high quality randomness such as one-time pad or key generation. When the entropy pool is empty, reads from /dev/random will block until additional environmental noise is gathered.

A read from the /dev/urandom device will not block waiting for more entropy. As a result, if there is not sufficient entropy in the entropy pool, the returned values are theoretically vulnerable to a cryptographic attack on the algorithms used by the driver. Knowledge of how to do this is not available in the current unclassified literature, but it is theoretically possible that such an attack may exist. If this is a concern in your application, use /dev/random instead.


의사난수를 발생시키는 리눅스 파일 시스템에는

/dev/urandom 이외에도 /dev/random이 존재합니다.


둘은 모두 같은 엔트로피 풀에서 파생되는데요.

/dev/random이 더욱 안전하지만

/dev/urandom는 많은양의

난수를 생성해도 성능 저하가 덜하다고 합니다.


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

Cmd2 문제풀이  (0) 2019.02.11
Cmd1 문제풀이  (0) 2019.02.10
Blackjack 문제풀이  (0) 2019.02.10
Coin1 문제풀이  (0) 2019.02.09
Shellshock 문제풀이  (0) 2019.02.08
Comments