CryptoHack

The first time I discovered CryptoHack I did all the tasks that were 100 points or more, since those were the only ones that looked interesting.

It’s a bit sad that doing the most difficult tasks net little reward, as all that matters is your “total score,” which is completely dominated by the countless trivial problems. So it’s more of a measure of stamina than anything else.

I went back later and completed everything though, all the riff-raff. That was the most painful part. The tasks in the 30-80 range are the worst, since they often require some work, yet the problems themselves are often trivial and/or not interesting. Felt endless.

CryptoHack is not a fan of putting solutions online, but I’ll share with anyone who wants to contact me.

I heavily employed flagmining during my solve run. I wrote all the solutions as self-contained scripts in an Org file. E.g. this was the prelude:

#+begin_src python :session ch :cache false
from flagmining.all import *
from pwn import remote, context
from flagrs import *

context.encoding = 'utf-8'

class jsremote(remote):
  def recvjson(self):
    return json.loads(self.recvuntil(b'}\n'), object_pairs_hook=jsdict)
  def sendjson(self, d):
    return self.sendline(json.dumps(d).encode())

json_get = lambda *args: requests.get(*args).json(object_pairs_hook=jsdict)
#+end_src

And then a solution would typically look like this:

#+begin_src python :session ch :results output :cache yes
def enc(data):
  url = f'https://aes.cryptohack.org/lazy_cbc/encrypt/{data.hex()}/'
  return bytes.fromhex(json_get(url).ciphertext)

def test(ct):
  url = f'https://aes.cryptohack.org/lazy_cbc/receive/{ct.hex()}/'
  res = json_get(url)
  if 'error' in res:
    return bytes.fromhex(res.error[len('Invalid plaintext: '):])
  return None

null_block = enc(bytes(32))
key = xor_bytes(null_block[:16], test(null_block[16:]))

url = f'https://aes.cryptohack.org/lazy_cbc/get_flag/{key.hex()}/'
res = json_get(url)
print(bytes.fromhex(res.plaintext).decode())
#+end_src