본문으로 바로가기

[pwnable.kr] blackjack 풀이, write-up

category Wargame/pwnable.kr 2018. 12. 27. 15:28

pwnable.kr --- blackjack



자신의 서버에 접속한 뒤 nc pwnable.kr 9009로 접속하면 blackjack 문제를 만날 수 있다. 


nc pwnable.kr 9009로 접속하면 바로 blackjack 파일이 실행되는 것을 확인할 수 있다.

blackjack에 관한 전체 소스는 아래의 경로로 접속 가능하다.


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



모든 소스를 설명하기는 길기 때문에 중요 소스만 부분 부분 보면서 write-up을 진행한다.


blackjack에서 제일 주목할 부분은 play()에서 사용된 함이다.

play() 함수는 blackjack을 실행하기 위한 핵심 함수이다.


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
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
cs




play() 함수에서 호출 하는 함수는 아래 4개의 함수이다.


cash_test()

randcard()

dealer()

betting()


위 4개의 함수를 자세히 들여다 보자.



cash_test() function



1
2
3
4
5
6
7
8
9
void cash_test() //Test for if user has cash remaining in purse
{
     if (cash <= 0//Once user has zero remaining cash, game ends and prompts user to play again
     {
        printf("You Are Bankrupt. Game Over");
        cash = 500;
        askover();
     }
// End Function
cs



유저(게임 참여자)가 betting 할 잔액이 남아 있는지 확인하는 함수이다. 

문제가 없음을 확인 할 수 있다.


randcard() function



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
int randcard() //Generates random card
{
      
                
     srand((unsigned) time(NULL)); //Generates random seed for rand() function
     random_card = rand()%4+1;
      
     if(random_card==1)
     {   
         clubcard();
         l=k;
     }
      
     if(random_card==2)
     {
         diamondcard();
         l=k;
     }
      
     if(random_card==3)
     {
         heartcard();
         l=k;
     }
          
     if(random_card==4)
     {
         spadecard();
         l=k;
     }    
     return l;
// End Function 
cs



srand() 함수에 의해 seed 값이 변경 되기 때문에 rand() 함수를 통한 카드의 종류를 예측할 수 없다.

randcard() 또한 문제가 없음을 확인할 수 있다.



dealer() function



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
void dealer() //Function to play for dealer AI
{
     int z;
      
     if(dealer_total<17)
     {
      srand((unsigned) time(NULL+ 1); //Generates random seed for rand() function
      z=rand()%13+1;
      if(z<=10//If random number generated is 10 or less, keep that value
      {
         d=z;
          
      }
      
      if(z>11//If random number generated is more than 11, change value to 10
      {
         d=10;
      }
      
      if(z==11//If random number is 11(Ace), change value to 11 or 1 depending on dealer total
      {
         if(dealer_total<=10)
         {
             d=11;
         }
          
         else
         {
             d=1;
         }
      }
     dealer_total = dealer_total + d;
     }
           
     printf("\nThe Dealer Has a Total of %d", dealer_total); //Prints dealer total
      
// End Function 
cs



dealer의 총 숫자의 합을 구하는 함수이다. srand() 함수를 통해 seed를 초기화하고, 딱히 잘못된 점이 없다.



betting() function



1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
cs



유저(게임의 참여자)가 betting 할 때 만일 유저가 가지고 있는 cash 보다 더 많은 cash를 betting 하면 다시 입력을 받고 bet를 return 하거나, 정상적으로 입력했을때, betting 값을 return 한다. 하지만 여기서 만일 잘못된 betting(cash보다 더 많은 betting)을 통해 다시 betting 값을 입력받을때, 예외 처리를 하지 않는다.

따라서 두 번째 입력을 받을때 임의의 betting 값 설정이 가능하다.



flag를 얻기 위해서 100만 달러 이상의 부자가 되어야 하니 100만 달러를 betting 후 게임에서 이겨보자.





betting() function 오류를 이용해서 $1000000를 betting 하였다.





dealer와의 게임에서 이기게 된다면, Cash에 $10000000가 추가되고 flag를 얻을 수 있다.


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

[pwnable.kr] lotto 풀이, write-up  (0) 2018.12.27
[pwnable.kr] blukat 풀이, write-up  (0) 2018.12.24
[pwnable.kr] leg 풀이, write-up  (0) 2018.12.24
[pwnable.kr] cmd1 풀이, write-up  (2) 2018.11.16
[pwnable.kr] mistake 풀이, write-up  (0) 2018.11.15