[pwnable.kr] blackjack(1 pts) :: Write-Up

두비니

·

2020. 7. 13. 00:37

 

 

 

Hey! check out this C implementation of blackjack game!
I found it online

* cboard.cprogramming.com/c-programming/114023-simple-blackjack-program.html

 

I  like to give my flags to millionares.
how much money you got?


Running at : nc pwnable.kr 9009

 

 

 

https://cboard.cprogramming.com/c-programming/114023-simple-blackjack-program.html

 

Simple Blackjack Program

Replies: 5 Last Post: 12-19-2006, 06:06 PM

cboard.cprogramming.com

코드는 위 링크에 있고, 너무 길어서 문제가 되는 부분만 가져올 것이다. 돈이 일정 금액을 넘어가면 플래그를 준다고 하니, 베팅을 하는 부분이나 게임 후 돈을 정리하는 부분의 코드를 중점적으로 보면 될 것 같다.

 

void play() //Plays game
{
      
     int p=0; // holds value of player_total
     int i=1; // counter for asking user to hold or stay (aka game turns)
     char choice3;
      
     cash = cash;
     cash_test();
     printf("\nCash: $%d\n",cash); //Prints amount of cash user has
     randcard(); //Generates random card
     player_total = p + l; //Computes player total
     p = player_total;
     printf("\nYour Total is %d\n", p); //Prints player total
     dealer(); //Computes and prints dealer total
     betting(); //Prompts user to enter bet amount
        
     while(i<=21) //While loop used to keep asking user to hit or stay at most twenty-one times
                  //  because there is a chance user can generate twenty-one consecutive 1's
     {
         if(p==21) //If user total is 21, win
         {
             printf("\nUnbelievable! You Win!\n");
             won = won+1;
             cash = cash+bet;
             printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
             dealer_total=0;
             askover();
         }
      
         if(p>21) //If player total is over 21, loss
         {
             printf("\nWoah Buddy, You Went WAY over.\n");
             loss = loss+1;
             cash = cash - bet;
             printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
             dealer_total=0;
             askover();
         }
      
         if(p<=21) //If player total is less than 21, ask to hit or stay
         {         
             printf("\n\nWould You Like to Hit or Stay?");
              
             scanf("%c", &choice3);
             while((choice3!='H') && (choice3!='h') && (choice3!='S') && (choice3!='s')) // If invalid choice entered
             {                                                                           
                 printf("\n");
                 printf("Please Enter H to Hit or S to Stay.\n");
                 scanf("%c",&choice3);
             }
 
 
             if((choice3=='H') || (choice3=='h')) // If Hit, continues
             { 
                 randcard();
                 player_total = p + l;
                 p = player_total;
                 printf("\nYour Total is %d\n", p);
                 dealer();
                  if(dealer_total==21) //Is dealer total is 21, loss
                  {
                      printf("\nDealer Has the Better Hand. You Lose.\n");
                      loss = loss+1;
                      cash = cash - bet;
                      printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
                      dealer_total=0;
                      askover();
                  } 
      
                  if(dealer_total>21) //If dealer total is over 21, win
                  {                      
                      printf("\nDealer Has Went Over!. You Win!\n");
                      won = won+1;
                      cash = cash+bet;
                      printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
                      dealer_total=0;
                      askover();
                  }
             }
             if((choice3=='S') || (choice3=='s')) // If Stay, does not continue
             {
                printf("\nYou Have Chosen to Stay at %d. Wise Decision!\n", player_total);
                stay();
             }
          }
             i++; //While player total and dealer total are less than 21, re-do while loop 
     } // End While Loop
} // End Function

 

int betting() //Asks user amount to bet
{
 printf("\n\nEnter Bet: $");
 scanf("%d", &bet);
 
 if (bet > cash) //If player tries to bet more money than player has
 {
        printf("\nYou cannot bet more money than you have.");
        printf("\nEnter Bet: ");
        scanf("%d", &bet);
        return bet;
 }
 else return bet;
} // End Function

이 문제를 풀 때 중점적으로 바줘야 할 코드들이다. 우선 if문에서 베팅금액이 소유액을 넘어가지 못하도록 한다. 그러나 if문 안을 보면, 다시 베팅을 받을때 검사를 하지 않는다.... 그냥 두번치면 되는듯.

그리고 다시 if문의 조건문을 보자.

 

if (bet > cash)

 

당연히 맞는 말이지만, 그렇다면 베팅이 0보다 작은 음수가 되어도 상관없게된다.

그럼 어떤일이 발생하게 되냐,

 

         if(p>21) //If player total is over 21, loss
         {
             printf("\nWoah Buddy, You Went WAY over.\n");
             loss = loss+1;
             cash = cash - bet;
             printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
             dealer_total=0;
             askover();
         }

다음은 play함수 중에서도 졌을 때 코드 일부를 가져왔다. 졌을 때는 cash에서 bet를 빼게 되는데, 이때 아까전에 말했던 음수를 입력하게 되면 오히려 덧셈이 된다는 것이다.

 

 

그래서

1. 음수활용

2. if문 안에서 베팅하기

두가지 정도 시나리오가 나오는 것 같다.

 

1. 음수

 

베팅을 0보다 작게해도 if문에서 자신이 가지고 있는 금액과의 대소관계만 비교하기 때문에 아무런 문제없이 게임이 진행된다.

 

 

그렇게 게임을 하다보면 진다. 랜덤함수다보니까 이길수도 있다. 그땐 그냥 다시해보기ㄱㄱ

 

 

그렇게 다시 하고싶다고하면?

플래그를 얻었다. 내가 가진 돈도 보면 -1000000을 베팅한 덕에 -(-1000000)이 되어 돈이 1000500을 가지게 되었다.

 

 

2. 코드상 결함

 

두 번째 취약점은 베팅을 할 때, 내가 가진 돈과 비교를 하긴 하지만 if문 안에 들어가서는 비교를 하지 않는다는 것이다. 따라서 두번째 입력할 때 그냥 무시하고 내가 원하는 값을 넣으면 그냥 그 값이 베팅이 되어버린다.

 

아무튼 다음과 같이 진행하면

1번과 똑같은 결과가 나온다. 결과창은 똑같아서 생략.

 

 

폰툴로 작성해도 물론 되겠지만 굳이..?

그리고 다 쓰고보니 이겼을 때를 노리고 integer overflow를 노려도 될 것 같다.

아무리 1점이라지만 너무 쉽긴 했다. 아무튼 다음!