CSAW 2016 Reverse 100 -- Rock

When you first run rock you just get a blank prompt. Input a couple of characters and you get a couple of quotes from the talented Dwayne “The Rock” Johnson, and a message saying “Too short or too long” unless you guessed (or checked) the right length.

'derp' wasn't the flag :(

Checking the code shows that the input length is supposed to be 30 characters long (notice the comparison against 0x1e, 30 in hex).


If you input 30 * ‘A’ you get a message telling you that you did not pass 0. Checking the code shows that each of the thirty characters is checked against some value, and rock will tell you if that character has passed or not.
Looking around the code you can find a string “FLAG23456912365453475897834567” which appears to be what our characters are checked against. However if you input this you still don’t pass.

This is the test resulting in the pass or fail of our characters.
We can place a breakpoint at 0x40183c from the code seen above, just as rock is about to compare our characters, and check the RCX register to see what is being checked against the FLAG string. Turns out our input has been transformed, as can be seen below.

C)>D doesn't spell FLAG
So, we have two options now: We can do this manually, or just bruteforce it. I did it both ways, because why not. To test it manually I input all printable ASCII characters, 30 at a time, as input, checked the transformed string in gdb, and made a key of the corresponding characters:
F L A G 0 1 2 3 4 5 6 7 8 9
I o D J s t u v w x y z { \
Which, replacing the 30 character string, gives you the flag: Flag{IoDJuvwxy\tuvyxwxvwzx{\z{vwxyz}
That, or you can python it away like in the gif (and code snippet) below.


#!/usr/bin/python

from subprocess import Popen , PIPE
import string

charset = string.printable
ans = []
for l in range(0,30):
 ans.append('A')

num = 0

while num < 30:
 for j in charset:
 
  proc = Popen('/root/csaw/rock', bufsize=1 ,stdin=PIPE, stdout=PIPE )
  text = ''
  ans[num] = j
  print ''.join(ans)
  proc.stdin.write("".join(ans)+'\n')
  for line in iter(proc.stdout.readline,b''):
   if ("Pass %d"%num in line):
    text = line
   if num == 29 and 'Flag' in line: 
    print line
    
  if("Pass %d"%num in text and "did not pass %d"%num not in text):
   num +=1
   proc.stdin.close()
   proc.stdout.close()
   break
  proc.stdin.close()
  proc.stdout.close()
Happy Hacking!