Rating:

We can control ECC pubkey. So we can modify both the message and the signature. With the server-side AES-CTR decrypt oracle, we just do not change the encrypted AES key and nonce. Each time we add one byte to the message. Let server decrypt all zero hex bytes to get the XOR key of AES-CTR. Because we add one byte a time. We can bruteforce each byte. Then with the XOR key, we get the flag.

```
#!/usr/bin/env python3
from Crypto.PublicKey import RSA, ECC
import json
from hashlib import sha256
from Crypto.Cipher import AES, PKCS1_OAEP
import base64
from Crypto.Signature import DSS
from Crypto.Hash import SHA256
from pwn import *

def xor(a, b):
return bytearray([a[i] ^ b[i % len(b)] for i in range(len(a))])

def main():
message = {"aeskey": "nwmHkXTN/EjnoO5IzhpNwE3nXEUMHsNWFI7dcHnpxIIiXCO+dLCjR6TfqYfbL9Z6a7SNCKbeTFBLnipXcRoN6o56urZMWwCioVTsV7PHrlCU42cKX+c/ShcVFrA5aOTTjaO9rxTMxB1PxJqYyxlpNaUpRFslzj9LKH+g8hVEuP9lVMm7q4aniyOUgPrAxyn044mbuxPu6Kh+JHSt5dkmnPZGNfUDKCwvMKeilb5ZkLaW/EaoXXsJLh/wUinMROIqmD2dkiWnk10633sJIu1lEOUsiykYXtJcd3o/B2dfTx2/85C2J6IsIp3+jJne76AYryAONPSxuh+M0h1xCzNeQg==", "message": "6VCnnSOU1DBImyhlqt7SoEjRtmBxjmABFVmXYhlKDyc+NBlnZ3Hpj4EkLwydPGpHiAvr4R0zTXSyUnMk5N6fi0/BFZE=", "nonce": "Cems9uHF6mk=", "signature": "uhLCnBvGfdC1fVkGUKQ8zNp/fOXNnFxNuDEc7CDGEYSxnuZMoGqbEqMLguJqDdvHFSHoUrq2R9/+mfk8LHndhw==", "eccpubkey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGww+NA3xHj4kCyztekLhmJVB62Hhq/oGDWwo4fxgZCgbODqD3vrMFFTGCWfO8ZyHtstuW+Yztpq94CnSNpJoug=="}
ecckey = ECC.generate(curve='p256')
eccpubkey = ecckey.public_key()
message["eccpubkey"] = "".join(eccpubkey.export_key(format="PEM").split("\n")[1:-1])
ciphertext = base64.b64decode(message["message"])
aeskey = base64.b64decode(message["aeskey"])
nonce = base64.b64decode(message["nonce"])
l = len(ciphertext)
#print(l)
signer = DSS.new(ecckey, "fips-186-3")
keystream = b""
for i in range(l):
text = b"\x00" * (i + 1)
h = SHA256.new(aeskey + nonce + text)
signature = signer.sign(h)
message["signature"] = base64.b64encode(signature).decode()
message["message"] = base64.b64encode(text).decode()
to_send = json.dumps(message)
print(i, to_send)
r = remote("crypto1.ctf.nullcon.net", 5001)
print(r.recvuntil("Enter message in json format: "))
r.send(to_send + "\n")
print(r.recvuntil("Here is your read receipt:\n"))
hm = r.recvuntil("\n").strip().decode()
print(hm)
for j in range(256):
digest = sha256(keystream + bytes([j])).hexdigest()
# print(j, digest, hm)
if digest == hm:
keystream += bytes([j])
print("keystream: ", [keystream], i, j)
break
r.close()
#exit()
flag = xor(ciphertext, keystream)
print("flag: ", flag)

'''
flag: bytearray(b'hackim20{digital_singatures_does_not_always_imply_authenticitaaayyy}')
'''

if __name__ == "__main__":
main()

```