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}