Pwnablekr_Toddlers Bottle_lotto

ssh로 접속하여 풀어야하는 문제이다. sftp로 소스코드와 프로그램을 다운받아 살펴보았다.

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

코드를 보면 play 함수의 체크 루틴이 이상하게 구현되었다. match++; 후에도 for(j=0; j<6; j++) 반복문을 종료하지 않는다. 따라서 입력한 글자가 6글자 모두 같을 경우, 실제 로또 숫자와 한 글자만 맞더라도 match가 6이 된다. 즉, 로또 숫자 중 하나만 맞추면 된다.

for(i=0; i<6; i++){
    for(j=0; j<6; j++){
        if(lotto[i] == submit[j]){
            match++;
        }
    }
}

플래그는 sorry mom... I FORGOT to check duplicate numbers... :( 이다.


tags: writeup, pwnable, elf file, linux, c lang, logic flaw