RPS — Binary Exploitation Challenge Writeup | PicoCTF 2022

RPS — Simple Binary Exploitation Program in PicoCTF | Approach by Karthikeyan Nagaraj

Karthikeyan Nagaraj
InfoSec Write-ups

--

Description:

  • Here’s a program that plays rock, paper, scissors against you.
  • I hear something good happens if you win 5 times in a row.
  • Connect to the program with netcat:
    $ nc saturn.picoctf.net 56981
  • The program's source code with the flag redacted can be downloaded here.

Task Files:

https://artifacts.picoctf.net/c/444/game-redacted.c

Analysis:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>


#define WAIT 60

static const char* flag = "[REDACTED]";

char* hands[3] = {"rock", "paper", "scissors"};
char* loses[3] = {"paper", "scissors", "rock"};
int wins = 0;


int tgetinput(char *input, unsigned int l)
{
fd_set input_set;
struct timeval timeout;
int ready_for_reading = 0;
int read_bytes = 0;

if( l <= 0 )
{
printf("'l' for tgetinput must be greater than 0\n");
return -2;
}


/* Empty the FD Set */
FD_ZERO(&input_set );
/* Listen to the input descriptor */
FD_SET(STDIN_FILENO, &input_set);

/* Waiting for some seconds */
timeout.tv_sec = WAIT; // WAIT seconds
timeout.tv_usec = 0; // 0 milliseconds

/* Listening for input stream for any activity */
ready_for_reading = select(1, &input_set, NULL, NULL, &timeout);
/* Here, first parameter is number of FDs in the set,
* second is our FD set for reading,
* third is the FD set in which any write activity needs to updated,
* which is not required in this case.
* Fourth is timeout
*/

if (ready_for_reading == -1) {
/* Some error has occured in input */
printf("Unable to read your input\n");
return -1;
}

if (ready_for_reading) {
read_bytes = read(0, input, l-1);
if(input[read_bytes-1]=='\n'){
--read_bytes;
input[read_bytes]='\0';
}
if(read_bytes==0){
printf("No data given.\n");
return -4;
} else {
return 0;
}
} else {
printf("Timed out waiting for user input. Press Ctrl-C to disconnect\n");
return -3;
}

return 0;
}


bool play () {
char player_turn[100];
srand(time(0));
int r;

printf("Please make your selection (rock/paper/scissors):\n");
r = tgetinput(player_turn, 100);
// Timeout on user input
if(r == -3)
{
printf("Goodbye!\n");
exit(0);
}

int computer_turn = rand() % 3;
printf("You played: %s\n", player_turn);
printf("The computer played: %s\n", hands[computer_turn]);

if (strstr(player_turn, loses[computer_turn])) {
puts("You win! Play again?");
return true;
} else {
puts("Seems like you didn't win this time. Play again?");
return false;
}
}


int main () {
char input[3] = {'\0'};
int command;
int r;

puts("Welcome challenger to the game of Rock, Paper, Scissors");
puts("For anyone that beats me 5 times in a row, I will offer up a flag I found");
puts("Are you ready?");

while (true) {
puts("Type '1' to play a game");
puts("Type '2' to exit the program");
r = tgetinput(input, 3);
// Timeout on user input
if(r == -3)
{
printf("Goodbye!\n");
exit(0);
}

if ((command = strtol(input, NULL, 10)) == 0) {
puts("Please put in a valid number");

} else if (command == 1) {
printf("\n\n");
if (play()) {
wins++;
} else {
wins = 0;
}

if (wins >= 5) {
puts("Congrats, here's the flag!");
puts(flag);
}
} else if (command == 2) {
return 0;
} else {
puts("Please type either 1 or 2");
}
}

return 0;
}

Notice the Below code

if (wins >= 5) {
puts("Congrats, here's the flag!");
puts(flag);
}

If the value of wins ≥ 5 then it will display the Flag.

Output:

In order to get the Flag, we have to continuously win 5 Times.
So Let’s Analyse the play() Function

if (strstr(player_turn, loses[computer_turn])) {
puts("You win! Play again?");
return true;
} else {
puts("Seems like you didn't win this time. Play again?");
return false;
}

Here the strstr()function is used to check whether the string loses[computer_turn] is in the string of player_turn .If present it will return true

Demonstration Example:

char* hands[3] = {"rock", "paper", "scissors"};
char* loses[3] = {"paper", "scissors", "rock"};

player_turn = rock
computer_turn = 2--> Means hand[2] -- scissors
loses[computer_turn] = rock

So, In this case, the stringloses[computer_turn]is inplayer_turn, Hence it will Return True and we will win

So the get the Flag, we have to use the stringrockpaperscissors as Input for 5 Times

rock is in rockpaperscissors
paper is in rockpaperscissors
scissors is in rockpaperscissors

All the conditions are true So we’ll get the Flag

Solution:

So do this in Netcat to get the Flag

nc saturn.picoctf.net 56981
Ans: picoCTF{50M3_3X7R3M3_1UCK_C85AF58A}

Feel Free to Ask Queries via LinkedIn and to Buy me a Cofee: )

Thank you for Reading!!

Happy Exploitation ~

Author: Karthikeyan Nagaraj ~ Cyberw1ng

ctf , binary exploitation , netcat , pico ctf , 2022 , capture the flag, challenge , writeup , flag , karthikeyan nagaraj , cyberw1ng

From Infosec Writeups: A lot is coming up in the Infosec every day that it’s hard to keep up with. Join our weekly newsletter to get all the latest Infosec trends in the form of 5 articles, 4 Threads, 3 videos, 2 GitHub Repos and tools, and 1 job alert for FREE!

--

--

Security Researcher | Bug Hunter | Web Pentester | CTF Player | TryHackme Top 1% | AI Researcher | Blockchain Developer