LoginSignup
0
0

More than 1 year has passed since last update.

picoCTF 2022 RSP Writeup

Last updated at Posted at 2022-03-30

条件反射的にブルートフォースしてしまったが。。。

Here's a program that plays rock, paper, scissors against you. I hear something good happens if you win 5 times in a row.

問題

image.png

ソースコード

game-redacted.c
#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;
}

じゃんけんで5回連続で勝てば, flag がとれそうだ。

動きの確認

$ nc saturn.picoctf.net 51420
Welcome challenger to the game of Rock, Paper, Scissors
For anyone that beats me 5 times in a row, I will offer up a flag I found
Are you ready?
Type '1' to play a game
Type '2' to exit the program

じゃんけんするので, 1 を入力

1
1


Please make your selection (rock/paper/scissors):

ここでグーを出す。

rock
rock
You played: rock
The computer played: rock
Seems like you didn't win this time. Play again?
Type '1' to play a game
Type '2' to exit the program

勝てなかった。

1
1


Please make your selection (rock/paper/scissors):
scissors
scissors
You played: scissors
The computer played: paper
You win! Play again?
Type '1' to play a game
Type '2' to exit the program

勝った。

5連勝するまで,無限じゃんけんプログラム

仕様1
Type '2' to exit the program に対して 1 を入力する

仕様2
勝っても負けても結果表示の末尾は Play again? と出る

仕様3
勝った時は, You win! が表示される

仕様4
5連勝したときフラグ picoCTF{xxxxxx} が表示される。

solver.py
# coding: UTF-8
# python 2.7

import socket
import string
import time

start = time.time()

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('saturn.picoctf.net',51420))

win = 0

# ブルートフォース
while True:

    # Type '2' to exit the programまでを受信,出力
    data = recvuntil(s, 'to exit the program')
    print(data)

    # 1を送信
    s.sendall('1\n')

    # じゃんけんの準備
    data = recvuntil(s, 'Please make your selection (rock/paper/scissors):')
    print(data)

    # グーを送信
    s.sendall('rock\n')
    
    # 終了判定 "You win! Play again?" か"Seems like you didn't win this time. Play again?" を受信したら
    data = recvuntil(s, 'again?')

    # 勝敗は?
    if data.find('win!') > 0:
        # 勝利数加算
        win=win+1
    else:
        # 勝利数クリア
        win=0

    print(data)
    
    # 5連勝ならフラグを受け取って終了
    if win==5:
        data = recvuntil(s, '}')
        print(data)
        break
        

elapsed_time = time.time() - start
print ("speed:{0}".format(elapsed_time) + "[sec]")

実行結果

(略)

Please make your selection (rock/paper/scissors):

rock
You played: rock
The computer played: scissors
You win! Play again?

Congrats, here's the flag!
picoCTF{50M3_3X7R3M3_1UCK_58F0F41B}
speed:171.631999969[sec]

もし,6連勝を求められていたら,この方法でフラグ取れただろうか?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0