2015年のrpsは解けなかったがこれはまあ取れた。

solution

The program tries to predict our hands with simple algorithm. We can predict the prediction.

The initial value of table is unknown, our prediction cannot be complete one. But, we can try many times, and sometimes win $40$ times. So it’s ok.

implementation

#!/usr/bin/env python2
import copy
from pwn import * # https://pypi.python.org/pypi/pwntools
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('host', nargs='?', default='ppc1.chal.ctf.westerns.tokyo')
parser.add_argument('port', nargs='?', default=15376, type=int)
args = parser.parse_args()

def init_table():
    return [ [ random.randint(0, 2) for j in range(3) ] for i in range(3) ], 0
def update_table(table, last, c):
    table = copy.deepcopy(table)
    table[last][c] += 1
    return table, c
def next_hand(table, last):
    m = max(table[last])
    ret = table[last].index(m)
    return (ret + 1) % 3

p = remote(args.host, args.port)
table, last = init_table()
for _ in range(50):
    p.recvuntil('Rock? Paper? Scissors? [RPS]')
    c = (next_hand(table, last) + 1) % 3
    p.sendline('RPS'[c])
    p.recvline()
    result = p.recvline().strip()
    if result == 'You lose':
        table[last][c] = max(table[last])
        if next_hand(table, last) != c:
            table[last][c] += 1
    elif result == 'Draw':
        table[last][(c-1)%3] = max(table[last])
        if next_hand(table, last) != (c-1)%3:
            table[last][(c-1)%3] += 1
    elif result == 'You win!!':
        pass
    table, last = update_table(table, last, c)
    log.info(p.recvline())
log.info(p.recvall()) # TWCTF{The_hand_is_determined_by_mien}