[Writeup] Asis 2019 Quals - Flag collision

This challenge starts with a similar hash anti-robot check.
After you clear that the main task of finding two valid flags of specified length that have the same CRC32 checksum.
Bruteforcing for the the first task to find length = 15 flags

from string import ascii_lowercase,ascii_uppercase,digits
from itertools import product
import binascii

def c32_find_words(search):
        flag_prefix = "ASIS{"
        word_generator = (''.join(i) for i in product(ascii_lowercase+ascii_uppercase+digits,repeat=9))
        for word in word_generator:
                flag = flag_prefix + word + "}"
                c32hash = binascii.crc32(flag)
                if c32hash == search:
                        print(flag)

def c32_find_hash():
        flag_prefix = "ASIS{"
        word_generator = (''.join(i) for i in product(ascii_lowercase+ascii_uppercase+digits,repeat=9))
        counter = 1
        c32table = set()
        for word in word_generator:
                if counter % 1000000 == 0:
                        print(counter)
                flag = flag_prefix + word + "}"
                c32hash = binascii.crc32(flag)
                if c32hash in c32table:
                        return c32hash
                else:
                        c32table.add(c32hash)
                counter += 1

c32_find_words(c32_find_hash())


Using set() for O(1) search lead to the program consuming 16GB ram just before printing the result.

ASIS{aaaal98cu} ASIS{aaaapvdba}

Running it for the next length lead to similar flags but with more 'a's at the start. Turns out you can pad same characters to both words and the new words will have the same checksum as well

Complete solution

import hashlib
import hashlib
from string import ascii_lowercase
from itertools import product
from pwn import *
import re

def multi_hash(hash_type,search):
        word_generator = (''.join(i) for i in product(ascii_lowercase,repeat=6))
        for word in word_generator:
                if getattr(hashlib,hash_type)(word).hexdigest()[-6:] == search:
                        return word

host = '37.139.9.232'
port = 19199
r = remote(host,port)

msg = r.recvuntil('\n')
msg = msg.split(' ')

hex_partial = msg[-1].strip()
hash_type = msg[-3]
hash_type = hash_type[:hash_type.find("(X)")]

plain_text = multi_hash(hash_type,hex_partial)
r.sendline(plain_text)
r.recvuntil('flag! |\n')


word1,word2 = "l98cu","pvdba"
flag_prefix = "ASIS{"

c = 0
while (c != 15):
        msg = r.recvuntil(':|\n')
        length = int(re.search("len = (\d\d)",msg).group(1))
        prefix = 'a' * (length - 11)
        flag1 = flag_prefix + prefix + word1 + "}"
        flag2 = flag_prefix + prefix + word2 + "}"
        solution = flag1 + ',' + flag2
        r.sendline(solution)
        c += 1

print(r.recv(1024))



Comments