Tags: crypto
Rating:
No captcha required for preview. Please, do not write just a link to original writeup here.
```python
#!/usr/bin/env python
from pwn import *
import re
from Crypto.Hash import SHA256
from Crypto.Cipher import AES
# context.log_level = 'debug'
def enc(a):
f = {str: str.encode, int: int.__str__}.get(type(a))
return enc(f(a)) if f else a
def H(*args):
data = b'\0'.join(map(enc, args))
return SHA256.new(data).digest()
q = 0x3a05ce0b044dade60c9a52fb6a3035fc9117b307ca21ae1b6577fef7acd651c1f1c9c06a644fd82955694af6cd4e88f540010f2e8fdf037c769135dbe29bf16a154b62e614bb441f318a82ccd1e493ffa565e5ffd5a708251a50d145f3159a5
def brute_flag(fb):
for password in range(10**6):
key = H(password, 1)
aes = AES.new(key, AES.MODE_CTR, nonce=b'')
decrypt = aes.decrypt(fb)
if b'hxp{' in decrypt:
return decrypt
if password % 100000 == 0 and password > 0:
log.info('{}%'.format((password / 10**6) * 100))
pow_re = re.compile(r'^please give S such that sha256\(unhex\("(\w+)" \+ S\)\) ends with (\d+) zero bits \(see pow-solver\.cpp\)\.$')
def solve_pow(p):
line = p.recvline().decode().strip()
m = pow_re.match(line)
prefix, bits = m.groups()
log.info("Solving pow for prefix {} and {} bits.".format(prefix, bits))
solver = process(["./gipfel/pow-solver", bits, prefix])
suffix = solver.recvall().strip()
log.success("Got suffix: {}".format(suffix))
solver.close()
p.sendline(suffix)
def main():
# p = process(["python", "gipfel/vuln.py"])
p = remote("65.108.176.66", 1088)
solve_pow(p)
pubA_line = p.recvline().decode()
log.info(pubA_line)
p.sendline(hex(q - 1).encode())
verA_line = p.recvline().decode()
verA = verA_line.split("=")[1].strip()
log.info(verA_line)
p.sendline(verA.encode())
flag_line = p.recvline().decode()
flag_bytes = bytes.fromhex(flag_line.split(":")[1].strip())
log.success(flag_line)
log.info("Bruteforcing key...")
flag = brute_flag(flag_bytes)
log.success("Flag: {}".format(flag.decode()))
p.close()
if __name__ == '__main__':
main()
```
Running the exploit gives us the flag after awhile. The longest time bottlenecks were the
proof-of-work computation and the search for the right key.
```console
vagrant@ubuntu-xenial:/vagrant/hxp/gipfel$ python exploit.py
[+] Opening connection to 65.108.176.66 on port 1088: Done
[*] Solving pow for prefix 37f3d460d77c3dd6 and 32 bits.
[+] Starting local process './gipfel/pow-solver': pid 3117
[+] Receiving all data: Done (17B)
[*] Process './gipfel/pow-solver' stopped with exit code 0 (pid 3117)
[+] Got suffix: b'0200000003f2a41a'
[*] pubA = 0x74498994c446fb5673b5a941f0cda711ef22c8b228eeaec6c7a1c315c948aeebfd8cadd1c3352c05e751be139807389430649f1db4a3bc75edecb91706df5427719544344108ab2dbea513cf202fe70d8dae2636d4709b126aa727b4997d98
[*] verA = 0x18eeaff89770d1771299a47e45562162f0ebb60a0297a1f3c3ce4eb431e3cb70
[+] flag: 929bc92d8abb3528be57d2c237aab1ab241c91df6a48a65e79cc509fdabf771d3a07e9a48dacbfa5
[*] Bruteforcing key...
[+] Flag: hxp{ju5T_k1ddIn9_w3_aLl_kn0w_iT's_12345}
[*] Closed connection to 65.108.176.66 port 1088
vagrant@ubuntu-xenial:/vagrant/hxp/gipfel$
```
**Flag:** `hxp{ju5T_k1ddIn9_w3_aLl_kn0w_iT's_12345}`
Full writeup with details here: [https://nandynarwhals.org/hxp-ctf-2021-gipfel/](https://nandynarwhals.org/hxp-ctf-2021-gipfel/)