当前位置: 代码迷 >> 综合 >> pwnable.kr --- blackjack题解
  详细解决方案

pwnable.kr --- blackjack题解

热度:32   发布时间:2023-11-13 14:28:39.0

题目很有意思。是我们所熟悉的21点游戏。题目的意思是,当我们赢得100万的时候,我们就会get到flag,游戏代码较长放在文末:

其实这个游戏还是很好玩的,一拿到代码,我就首先怀疑会不会还是rand函数用同一个种子的问题,但是阅读了源代码发现并不是这个问题。

于是我就尝试输入了一些非法数据,发现程序对金钱的上限有限制,对下限没有限制。另外我们还注意到,在第二次输入的时候没有了前面的$符号,也就是说,这两个输入可能是分别来写的~oh,interesting~

我们故意输一下,想赢是需要运气,但是输的话这个还是很容易,我们发现,虽然我们输了,但是我们的钱增加了

让我们来阅读源码,看看bet和cash到底是如何存储和比较的。
在这里插入图片描述
在int betting函数中,它只对输入的金额做了一次判断,当第二次输入的时候,就直接返回bet了。

所以我们就可以很轻松的通过nc pwnable.kr 9009连接到服务器后得到flag了

// Programmer: Vladislav Shulman
// Final Project
// Blackjack// Feel free to use any and all parts of this program and claim it as your own work//FINAL DRAFT#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>                //Used for srand((unsigned) time(NULL)) command
//#include <process.h>             //Used for system("clear") command#define spade 06                 //Used to print spade symbol
#define club 05                  //Used to print club symbol
#define diamond 04               //Used to print diamond symbol
#define heart 03                 //Used to print heart symbol
#define RESULTS "Blackjack.txt"  //File name is Blackjack//Global Variables
int k;
int l;
int d;
int won;
int loss;
int cash = 500;
int bet;
int random_card;
int player_total=0;
int dealer_total;//Function Prototypes
int clubcard();      //Displays Club Card Image
int diamondcard();   //Displays Diamond Card Image
int heartcard();     //Displays Heart Card Image
int spadecard();     //Displays Spade Card Image
int randcard();      //Generates random card
int betting();       //Asks user amount to bet
void asktitle();     //Asks user to continue
void rules();        //Prints "Rules of Vlad's Blackjack" menu
void play();         //Plays game
void dealer();       //Function to play for dealer AI
void stay();         //Function for when user selects 'Stay'
void cash_test();    //Test for if user has cash remaining in purse
void askover();      //Asks if user wants to continue playing
void fileresults();  //Prints results into Blackjack.txt file in program directory//Main Function
int main(void)
{int choice1;printf("\n");printf("\n");printf("\n");printf("\n              222                111                            ");printf("\n            222 222            11111                              ");printf("\n           222   222          11 111                            "); printf("\n                222              111                               "); printf("\n               222               111                           ");   printf("\n");printf("\n%c%c%c%c%c     %c%c            %c%c         %c%c%c%c%c    %c    %c                ", club, club, club, club, club, spade, spade, diamond, diamond, heart, heart, heart, heart, heart, club, club);  printf("\n%c    %c    %c%c           %c  %c       %c     %c   %c   %c              ", club, club, spade, spade, diamond, diamond, heart, heart, club, club);            printf("\n%c    %c    %c%c          %c    %c     %c          %c  %c               ", club, club, spade, spade, diamond, diamond, heart, club, club);                        printf("\n%c%c%c%c%c     %c%c          %c %c%c %c     %c          %c %c              ", club, club, club, club, club, spade, spade, diamond, diamond, diamond, diamond, heart, club, club);      printf("\n%c    %c    %c%c         %c %c%c%c%c %c    %c          %c%c %c             ", club, club, spade, spade, diamond, diamond, diamond, diamond, diamond, diamond, heart, club, club, club);                       printf("\n%c     %c   %c%c         %c      %c    %c          %c   %c               ", club, club, spade, spade, diamond, diamond, heart, club, club);                                         printf("\n%c     %c   %c%c        %c        %c    %c     %c   %c    %c             ", club, club, spade, spade, diamond, diamond, heart, heart, club, club);                                                            printf("\n%c%c%c%c%c%c    %c%c%c%c%c%c%c   %c        %c     %c%c%c%c%c    %c     %c            ", club, club, club, club, club, club, spade, spade, spade, spade, spade, spade, spade, diamond, diamond, heart, heart, heart, heart, heart, club, club);                                                                                     printf("\n");     printf("\n                        21                                   ");printf("\n     %c%c%c%c%c%c%c%c      %c%c         %c%c%c%c%c    %c    %c                ", diamond, diamond, diamond, diamond, diamond, diamond, diamond, diamond, heart, heart, club, club, club, club, club, spade, spade);                     printf("\n        %c%c        %c  %c       %c     %c   %c   %c              ", diamond, diamond, heart, heart, club, club, spade, spade);                                      printf("\n        %c%c       %c    %c     %c          %c  %c               ", diamond, diamond, heart, heart, club, spade, spade);                                           printf("\n        %c%c       %c %c%c %c     %c          %c %c              ", diamond, diamond, heart, heart, heart, heart, club, spade, spade);                                     printf("\n        %c%c      %c %c%c%c%c %c    %c          %c%c %c             ", diamond, diamond, heart, heart, heart, heart, heart, heart, club, spade, spade, spade);                                                printf("\n        %c%c      %c      %c    %c          %c   %c               ", diamond, diamond, heart, heart, club, spade, spade);                                                                               printf("\n     %c  %c%c     %c        %c    %c     %c   %c    %c             ", diamond, diamond, diamond, heart, heart, club, spade, spade);                                                                                                               printf("\n      %c%c%c      %c        %c     %c%c%c%c%c    %c     %c            ", diamond, diamond, diamond, heart, heart, club, club, club, club, club, spade, spade);                                                                                                                                        printf("\n");  printf("\n         222                     111                         ");printf("\n        222                      111                         ");printf("\n       222                       111                         ");printf("\n      222222222222222      111111111111111                       ");printf("\n      2222222222222222    11111111111111111                         ");printf("\n");printf("\n");asktitle();printf("\n");printf("\n");system("pause");return(0);
} //end programvoid asktitle() // Function for asking player if they want to continue
{char choice1;int choice2;printf("\n                 Are You Ready?");printf("\n                ----------------");printf("\n                      (Y/N)\n                        ");scanf("\n%c",&choice1);while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')) // If invalid choice entered{                                                                           printf("\n");printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");scanf("%c",&choice1);}if((choice1 == 'Y') || (choice1 == 'y')) // If yes, continue. Prints menu.{ system("clear");printf("\nEnter 1 to Begin the Greatest Game Ever Played.");printf("\nEnter 2 to See a Complete Listing of Rules.");printf("\nEnter 3 to Exit Game. (Not Recommended)");printf("\nChoice: ");scanf("%d", &choice2); // Prompts user for choiceif((choice2<1) || (choice2>3)) // If invalid choice entered{printf("\nIncorrect Choice. Please enter 1, 2 or 3\n");scanf("%d", &choice2);}switch(choice2) // Switch case for different choices{   case 1: // Case to begin gamesystem("clear");play();break;case 2: // Case to see rulessystem("clear");rules();break;case 3: // Case to exit gameprintf("\nYour day could have been perfect.");printf("\nHave an almost perfect day!\n\n");system("pause");exit(0);break;default:printf("\nInvalid Input");} // End switch case} // End if loopelse if((choice1 == 'N') || (choice1 == 'n')) // If no, exit program{printf("\nYour day could have been perfect.");printf("\nHave an almost perfect day!\n\n");system("pause");exit(0);}return;
} // End functionvoid rules() //Prints "Rules of Vlad's Blackjack" list
{char choice1;int choice2;printf("\n           RULES of VLAD's BLACKJACK");printf("\n          ---------------------------");printf("\nI.");printf("\n     Thou shalt not question the odds of this game.");printf("\n      %c This program generates cards at random.", spade);printf("\n      %c If you keep losing, you are very unlucky!\n", diamond);printf("\nII.");printf("\n     Each card has a value.");printf("\n      %c Number cards 1 to 10 hold a value of their number.", spade);printf("\n      %c J, Q, and K cards hold a value of 10.", diamond);printf("\n      %c Ace cards hold a value of 11", club);printf("\n     The goal of this game is to reach a card value total of 21.\n");printf("\nIII.");printf("\n     After the dealing of the first two cards, YOU must decide whether to HIT or STAY.");printf("\n      %c Staying will keep you safe, hitting will add a card.", spade);printf("\n     Because you are competing against the dealer, you must beat his hand.");printf("\n     BUT BEWARE!.");printf("\n      %c If your total goes over 21, you will LOSE!.", diamond);printf("\n     But the world is not over, because you can always play again.\n");printf("\n%c%c%c YOUR RESULTS ARE RECORDED AND FOUND IN SAME FOLDER AS PROGRAM %c%c%c\n", spade, heart, club, club, heart, spade);printf("\nWould you like to go the previous screen? (I will not take NO for an answer)");printf("\n                  (Y/N)\n                    ");scanf("\n%c",&choice1);while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')) // If invalid choice entered{                                                                           printf("\n");printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");scanf("%c",&choice1);}if((choice1 == 'Y') || (choice1 == 'y')) // If yes, continue. Prints menu.{ system("clear");asktitle();} // End if loopelse if((choice1 == 'N') || (choice1 == 'n')) // If no, convinces user to enter yes{system("clear");printf("\n                 I told you so.\n");asktitle();}return;
} // End functionint clubcard() //Displays Club Card Image
{srand((unsigned) time(NULL)); //Generates random seed for rand() functionk=rand()%13+1;if(k<=9) //If random number is 9 or less, print card with that number{//Club Cardprintf("-------\n");printf("|%c    |\n", club);printf("|  %d  |\n", k);printf("|    %c|\n", club);printf("-------\n");}if(k==10) //If random number is 10, print card with J (Jack) on face{//Club Cardprintf("-------\n");printf("|%c    |\n", club);printf("|  J  |\n");printf("|    %c|\n", club);printf("-------\n");}if(k==11) //If random number is 11, print card with A (Ace) on face{//Club Cardprintf("-------\n");printf("|%c    |\n", club);printf("|  A  |\n");printf("|    %c|\n", club);printf("-------\n");if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total{k=11;}else{k=1;}}if(k==12) //If random number is 12, print card with Q (Queen) on face{//Club Cardprintf("-------\n");printf("|%c    |\n", club);printf("|  Q  |\n");printf("|    %c|\n", club);printf("-------\n");k=10; //Set card value to 10}if(k==13) //If random number is 13, print card with K (King) on face{//Club Cardprintf("-------\n");printf("|%c    |\n", club);printf("|  K  |\n");printf("|    %c|\n", club);printf("-------\n");k=10; //Set card value to 10}return k;           
}// End functionint diamondcard() //Displays Diamond Card Image
{srand((unsigned) time(NULL)); //Generates random seed for rand() functionk=rand()%13+1;if(k<=9) //If random number is 9 or less, print card with that number{//Diamond Cardprintf("-------\n");printf("|%c    |\n", diamond);printf("|  %d  |\n", k);printf("|    %c|\n", diamond);printf("-------\n");}if(k==10) //If random number is 10, print card with J (Jack) on face{//Diamond Cardprintf("-------\n");printf("|%c    |\n", diamond);printf("|  J  |\n");printf("|    %c|\n", diamond);printf("-------\n");}if(k==11) //If random number is 11, print card with A (Ace) on face{//Diamond Cardprintf("-------\n");printf("|%c    |\n", diamond);printf("|  A  |\n");printf("|    %c|\n", diamond);printf("-------\n");if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total{k=11;}else{k=1;}}if(k==12) //If random number is 12, print card with Q (Queen) on face{//Diamond Cardprintf("-------\n");printf("|%c    |\n", diamond);printf("|  Q  |\n");printf("|    %c|\n", diamond);printf("-------\n");k=10; //Set card value to 10}if(k==13) //If random number is 13, print card with K (King) on face{//Diamond Cardprintf("-------\n");printf("|%c    |\n", diamond);printf("|  K  |\n");printf("|    %c|\n", diamond);printf("-------\n");k=10; //Set card value to 10}return k;
}// End functionint heartcard() //Displays Heart Card Image
{srand((unsigned) time(NULL)); //Generates random seed for rand() functionk=rand()%13+1;if(k<=9) //If random number is 9 or less, print card with that number{//Heart Cardprintf("-------\n");printf("|%c    |\n", heart); printf("|  %d  |\n", k);printf("|    %c|\n", heart);printf("-------\n");}if(k==10) //If random number is 10, print card with J (Jack) on face{//Heart Cardprintf("-------\n");printf("|%c    |\n", heart);printf("|  J  |\n");printf("|    %c|\n", heart);printf("-------\n");}if(k==11) //If random number is 11, print card with A (Ace) on face{//Heart Cardprintf("-------\n");printf("|%c    |\n", heart);printf("|  A  |\n");printf("|    %c|\n", heart);printf("-------\n");if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total{k=11;}else{k=1;}}if(k==12) //If random number is 12, print card with Q (Queen) on face{//Heart Cardprintf("-------\n");printf("|%c    |\n", heart);printf("|  Q  |\n");printf("|    %c|\n", heart);printf("-------\n");k=10; //Set card value to 10}if(k==13) //If random number is 13, print card with K (King) on face{//Heart Cardprintf("-------\n");printf("|%c    |\n", heart);printf("|  K  |\n");printf("|    %c|\n", heart);printf("-------\n");k=10; //Set card value to 10}return k;
} // End Functionint spadecard() //Displays Spade Card Image
{srand((unsigned) time(NULL)); //Generates random seed for rand() functionk=rand()%13+1;if(k<=9) //If random number is 9 or less, print card with that number{//Spade Cardprintf("-------\n");printf("|%c    |\n", spade);printf("|  %d  |\n", k);printf("|    %c|\n", spade);printf("-------\n");}if(k==10) //If random number is 10, print card with J (Jack) on face{//Spade Cardprintf("-------\n");printf("|%c    |\n", spade);printf("|  J  |\n");printf("|    %c|\n", spade);printf("-------\n");}if(k==11) //If random number is 11, print card with A (Ace) on face{//Spade Cardprintf("-------\n");printf("|%c    |\n", spade);printf("|  A  |\n");printf("|    %c|\n", spade);printf("-------\n");if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total{k=11;}else{k=1;}}if(k==12) //If random number is 12, print card with Q (Queen) on face{//Spade Cardprintf("-------\n");printf("|%c    |\n", spade);printf("|  Q  |\n");printf("|    %c|\n", spade);printf("-------\n");k=10; //Set card value to 10}if(k==13) //If random number is 13, print card with K (King) on face{//Spade Cardprintf("-------\n");printf("|%c    |\n", spade);printf("|  K  |\n");printf("|    %c|\n", spade);printf("-------\n");k=10; //Set card value to 10}return k;
} // End Functionint randcard() //Generates random card
{srand((unsigned) time(NULL)); //Generates random seed for rand() functionrandom_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   void play() //Plays game
{int p=0; // holds value of player_totalint 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 hasrandcard(); //Generates random cardplayer_total = p + l; //Computes player totalp = player_total;printf("\nYour Total is %d\n", p); //Prints player totaldealer(); //Computes and prints dealer totalbetting(); //Prompts user to enter bet amountwhile(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 Functionvoid dealer() //Function to play for dealer AI
{int z;if(dealer_total<17){srand((unsigned) time(NULL) + 1); //Generates random seed for rand() functionz=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 void stay() //Function for when user selects 'Stay'
{dealer(); //If stay selected, dealer continues goingif(dealer_total>=17){if(player_total>=dealer_total) //If player's total is more than dealer's total, 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(player_total<dealer_total) //If player's total is less than dealer's total, 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's total is more than 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();}}else{stay();}} // End Functionvoid 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 Functionint 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 Functionvoid askover() // Function for asking player if they want to play again
{char choice1;printf("\nWould You Like To Play Again?");printf("\nPlease Enter Y for Yes or N for No\n");scanf("\n%c",&choice1);while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')) // If invalid choice entered{                                                                           printf("\n");printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");scanf("%c",&choice1);}if((choice1 == 'Y') || (choice1 == 'y')) // If yes, continue.{ system("clear");play();}else if((choice1 == 'N') || (choice1 == 'n')) // If no, exit program{fileresults();printf("\nBYE!!!!\n\n");system("pause");exit(0);}return;
} // End functionvoid fileresults() //Prints results into Blackjack.txt file in program directory
{FILE *fpresults; //File pointer is fpresultsfpresults = fopen(RESULTS, "w"); //Creates file and writes into itif(fpresults == NULL) // what to do if file missing from directory{printf("\nError: File Missing\n");system("pause");exit(1);}else{     fprintf(fpresults,"\n\t RESULTS");fprintf(fpresults,"\n\t---------\n");fprintf(fpresults,"\nYou Have Won %d Times\n", won);fprintf(fpresults,"\nYou Have Lost %d Times\n", loss);fprintf(fpresults,"\nKeep Playing and Set an All-Time Record!");} fclose(fpresults);return;
} // End Function