avatar
Cyscom
Cybersecurity Student Community of VIT Chennai
  • CTF EVENTS
  • CATEGORIES
  • TAGS
  • ARCHIVES
  • POSTS
  • ABOUT
Home FinalTrace 2025 Do you know XOR well enough?
Writeup
Cancel

Do you know XOR well enough?

Do you know XOR well enough?

  • Category: Cryptography
  • Author: P C Guhan

Description

Random numbers, AES encryption, SHA 256, HMAC, constant-time hash checking… what more do you want? All are imported functions, hence highly secure Or is it??

Solution

AES CBC Encryption AES CBC Decryption

This method uses the previous block to encrypt the next block. The same follows for decryption also. Hence, a bit flip will alter the plaintext.

Each hex requires two characters. The length of “admin=0” is 7. The hex output consists of the 16 bit IV and the 16 bit padded ciphertext. The IV is XOred with the decrypted ciphertext.

To get admin=1, we XOR the 6th character block with 1. i.e. IV[6] ^ decrypted(message[6]) ^ 1 = 0 ^ 1 since 0 ^ 1 = 1,

IV[6] ^ decrypted(message[6]) ^ 1 = 1 giving us admin=1

A corresponding hash can be generated as the hashing algorithm is open source.

To mitigate this vulnerability while still using AES CBC mode, AEAD (Authenticated Encryption and Additional Data) must be used i.e. hashing with a secret key.

Script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import hashlib
import hmac
import random

# --- setup (same as challenge) ---
key = get_random_bytes(16)
iv = get_random_bytes(16)

part1 = "AES"
part2 = ''.join(random.choices(string.ascii_uppercase, k=5))
part3 = "AEAD"
part4 = f"{random.randint(0, 999999):06d}"
part5 = ''.join(random.choices(string.ascii_uppercase, k=3))
flag = "CYS{" + f"{part1}_{part2}_{part3}_{part4}_{part5}" + "}"

def encrypt_data(data):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    enc = cipher.encrypt(pad(data.encode(), 16, style='pkcs7'))
    return enc.hex()

def decrypt_data(encryptedParams):
    data = bytes.fromhex(encryptedParams)
    if len(data) < 16:
        raise ValueError("Ciphertext too short")
    iv_in = data[:16]
    ciphertext = data[16:]
    cipher = AES.new(key, AES.MODE_CBC, iv_in)
    paddedParams = cipher.decrypt(ciphertext)
    plaintext = unpad(paddedParams, 16, style='pkcs7')
    return plaintext.decode(errors='ignore')


print("Just copy and paste? Hash is also given...")
msg = "admin=0"
print("\nCurrent authentication message is : " + msg)
print("Turn it to admin=1")

cipher_hex = encrypt_data(msg)
iv_cipher = iv.hex() + cipher_hex
print("\nEncryption of authentication message in hex : " + iv_cipher)


hashed_value = hashlib.sha256(iv_cipher.encode('utf-8')).hexdigest()
print("SHA-256: ", hashed_value)

# -----------------------------
# Solution
# Reliable CBC bit-flip to change admin=0 -> admin=1
# -----------------------------
orig_msg = "admin=0"
target_msg = "admin=1"

p0 = pad(orig_msg.encode(), 16, style='pkcs7')[:16]
p1 = pad(target_msg.encode(), 16, style='pkcs7')[:16]

delta = bytes(a ^ b for a, b in zip(p0, p1))

iv_prime = bytes(a ^ b for a, b in zip(iv, delta))

enc_msg = iv_prime.hex() + cipher_hex
enc_hash = hashlib.sha256(enc_msg.encode('utf-8')).hexdigest()


# --- setup (same as challenge) ---
try:
    if hmac.compare_digest(hashlib.sha256(enc_msg.encode('utf-8')).hexdigest(), enc_hash):
        final_dec_msg = decrypt_data(enc_msg)
        print(final_dec_msg)

        if "admin=1" == final_dec_msg:
            print(flag)
        else:
            print('\nTry again you can do it!!')
    else:
        print("\nHashing failed")
        print(hashlib.sha256(enc_msg.encode('utf-8')).hexdigest() + "\n\n")
        print(enc_hash)
except Exception as e:
    print('\nbye bye!!', e)

Flag

Dynamic Flag
Edit on GitHub
Trending Tags
authentication idor sql-injection ssti xss

© 2025 Cyscom. Some rights reserved.

Using the Jekyll theme Chirpy.

A new version of content is available.