HKCERT CTF 2022 Writeup - Official

Crypto

Official (125 points)

crypto

Description

Modified from the official tutorial to use AES-256-GCM as it sounds more secure:
https://nodejs.org/en/knowledge/cryptography/how-to-use-crypto-module/
Attachment: official_747dd25c05a3dca034e7161dec5b1e0f.zip

After download the attachment, there is an official.js file

Click to view the source of official.js

#!/usr/bin/env node

/*

Modified from the official tutorial to use AES-256-GCM as it sounds more secure:
https://nodejs.org/en/knowledge/cryptography/how-to-use-crypto-module/


> AES-GCM is included in the NSA Suite B Cryptography and its latest replacement in 
> 2018 Commercial National Security Algorithm (CNSA) suite. GCM mode is used in the 
> SoftEther VPN server and client, as well as OpenVPN since version 2.4.
> -- https://en.wikipedia.org/wiki/Galois/Counter_Mode#Use


Usage:

$ node official.js -e --key="<<REDACTED>>" "My treasure is buried behind Carl's Jr. on Telegraph."
31b9e00aafcd3f7edbd394dc2cb05e7aca8b6bf01fae094a15979062bf190f4d8b0f32ca1a1a6aace3a6efc64b4f15f64a02d9b128

$ node official.js -e --key="<<REDACTED>>" "hkcert22{<<REDACTED>>}"
14aba31bafdc6c3fd5ce979a2ca0172cd3d471a10eed0e5c508d8a32eb3f0a128e5c6c8323452abcf8e5bcf74d5602f445


MIT License

*/

const crypto = require('crypto');
const argv = require('yargs').argv;
const resizedIV = Buffer.allocUnsafe(16);
const iv = crypto.createHash('sha256').update('myHashedIV').digest();

iv.copy(resizedIV);

if (argv.e && argv.key) {
  const key = crypto.createHash('sha256').update(argv.key).digest();
  const cipher = crypto.createCipheriv("aes-256-gcm", key, resizedIV);
  const msg = [];

  argv._.forEach(function (phrase) {
    msg.push(cipher.update(phrase, 'binary', 'hex'));
  });

  msg.push(cipher.final('hex'));
  console.log(msg.join(''));
} else if (argv.d && argv.key) {
  const key = crypto.createHash('sha256').update(argv.key).digest();
  const decipher = crypto.createDecipheriv("aes-256-gcm", key, resizedIV);
  const msg = [];

  argv._.forEach(function (phrase) {
    msg.push(decipher.update(phrase, 'hex', 'binary'));
  });

  msg.push(decipher.final('binary'));
  console.log(msg.join(''));
}

The app uses aes-256-gcm to encrypt the flag, and the first thing I do is google ctf aes-256-gcm reverse key, which shows the result of https://meowmeowxw.gitlab.io/ctf/utctf-2020-crypto/

From the Exploit section, we can find that the solution is to apply xor(xor(flag_enc, ciphertext), payload), which used the code to create my own exploit

def xor(s1, s2):
    if (len(s1) == 1 and len(s1) == 1):
        return bytes([ord(s1) ^ ord(s2)])
    else:
        return bytes(x ^ y for x, y in zip(s1, s2))


def main():
    payload = b"My treasure is buried behind Carl's Jr. on Telegraph."
    flag_enc = bytes.fromhex(
        "14aba31bafdc6c3fd5ce979a2ca0172cd3d471a10eed0e5c508d8a32eb3f0a128e5c6c8323452abcf8e5bcf74d5602f445")
    ciphertext = bytes.fromhex(
        "31b9e00aafcd3f7edbd394dc2cb05e7aca8b6bf01fae094a15979062bf190f4d8b0f32ca1a1a6aace3a6efc64b4f15f64a02d9b128")
    flag = xor(xor(flag_enc, ciphertext), payload)
    print(flag.decode())


if __name__ == '__main__':
    main()

After running the exploit, the flag will be printed to the console

Click to view the flag

hkcert22{offici4l-s4uces-st4ted-it-is-n0t-secure}

SunnyLo
SunnyLo
HK Student