HTB AI vs Human CTF Challenge — Crypto: Repeated Maleficence
After analyzing the source code, we discovered that the flag is XORed with a randomly generated key of length 5. Since the key is random…
HTB AI vs Human CTF Challenge — Crypto: Repeated Maleficence
After analyzing the source code, we discovered that the flag is XORed with a randomly generated key of length 5. Since the key is random, recovering the exact key directly would be quite challenging.
However, we know that all flags follow the format HTB{some_text}, meaning the first four bytes of the plaintext are always HTB{. This allows us to recover the first four bytes of the key by XORing them with the corresponding encrypted bytes.
For the remaining fifth byte of the key, we can brute-force all possible values. Here is the script to do it:
def recover_key(enc, known_plaintext):
key = bytearray(len(known_plaintext))
for i in range(len(known_plaintext)):
key[i] = enc[i] ^ known_plaintext[i] # XOR encrypted byte with known plaintext byte
return key
def brute_force_fifth_byte(enc, known_plaintext):
# Try all printable ASCII characters for the 5th byte of plaintext
for i in range(32, 127): # Printable ASCII characters range
# Create a candidate for the 5th byte of the plaintext
candidate_plaintext = known_plaintext + bytes([i])
# Recover key using the first 4 characters and this guess for the 5th byte
recovered_key_part = recover_key(enc[:5], candidate_plaintext)
# Here, you could check if the recovered key fits some condition (e.g., validity of decrypted message)
print(f"Trying plaintext with 5th byte {chr(i)}: Recovered Key: {recovered_key_part.hex()}")
known_plaintext = b'HTB{' # The first 4 characters of the original message
enc = bytes.fromhex("720c4103880a2a5c49a3652f304c9b652f324d9865336d488754077349c40b36364b880f25") # Replace with actual encrypted data
brute_force_fifth_byte(enc, known_plaintext)


Possible keys for flag
Using each potential key, we will decrypt the flag and obtain multiple possible outputs. Here is the script:
def xor_decrypt(ciphertext, key):
"""XOR the ciphertext with the given key."""
decrypted = bytearray()
for i in range(len(ciphertext)):
decrypted.append(ciphertext[i] ^ key[i % len(key)])
return bytes(decrypted)
def try_decrypt_with_keys(encrypted_hex, keys_hex):
"""Try to decrypt the encrypted text with all given keys."""
encrypted_data = bytes.fromhex(encrypted_hex)
for key_hex in keys_hex:
key = bytes.fromhex(key_hex)
decrypted_data = xor_decrypt(encrypted_data, key)
try:
# Attempt to decode the decrypted text as UTF-8 (this might fail if the text is not UTF-8)
decrypted_text = decrypted_data.decode('utf-8')
print(f"Decrypted with key {key_hex}: {decrypted_text}")
except UnicodeDecodeError:
# If decoding fails, print raw bytes
print(f"Decrypted with key {key_hex}: (binary output) {decrypted_data.hex()}")
if __name__ == '__main__':
# Encrypted data (replace with the actual encrypted text)
encrypted_hex = "720c4103880a2a5c49a3652f304c9b652f324d9865336d488754077349c40b36364b880f25"
# List of keys in hexadecimal
keys_hex = [
"3a580378a8", "3a580378a9", "3a580378aa", "3a580378ab", "3a580378ac",
"3a580378ad", "3a580378ae", "3a580378af", "3a580378a0", "3a580378a1",
"3a580378a2", "3a580378a3", "3a580378a4", "3a580378a5", "3a580378a6",
"3a580378a7", "3a580378b8", "3a580378b9", "3a580378ba", "3a580378bb",
"3a580378bc", "3a580378bd", "3a580378be", "3a580378bf", "3a580378b0",
"3a580378b1", "3a580378b2", "3a580378b3", "3a580378b4", "3a580378b5",
"3a580378b6", "3a580378b7", "3a580378c8", "3a580378c9", "3a580378ca",
"3a580378cb", "3a580378cc", "3a580378cd", "3a580378ce", "3a580378cf",
"3a580378c0", "3a580378c1", "3a580378c2", "3a580378c3", "3a580378c4",
"3a580378c5", "3a580378c6", "3a580378c7", "3a580378d8", "3a580378d9",
"3a580378da", "3a580378db", "3a580378dc", "3a580378dd", "3a580378de",
"3a580378df", "3a580378d0", "3a580378d1", "3a580378d2", "3a580378d3",
"3a580378d4", "3a580378d5", "3a580378d6", "3a580378d7", "3a580378e8",
"3a580378e9", "3a580378ea", "3a580378eb", "3a580378ec", "3a580378ed",
"3a580378ee", "3a580378ef", "3a580378e0", "3a580378e1", "3a580378e2",
"3a580378e3", "3a580378e4", "3a580378e5", "3a580378e6", "3a580378e7",
"3a580378f8", "3a580378f9", "3a580378fa", "3a580378fb", "3a580378fc",
"3a580378fd", "3a580378fe", "3a580378ff", "3a580378f0", "3a580378f1",
"3a580378f2", "3a580378f3", "3a580378f4", "3a580378f5", "3a580378f6"
]
# Try to decrypt using each key
try_decrypt_with_keys(encrypted_hex, keys_hex)
Since all valid flags follow the standard HTB{…} format, we can manually analyze the results to identify the correct flag.

flag is marked here
After analyzing we found the correct flag.
메타데이터
- post_id
- d0c0e096800f
- slug
- htb-ai-vs-human-ctf-challenge-crypto-repeated-maleficence-d0c0e096800f
- url
- https://medium.com/@MrX2025/htb-ai-vs-human-ctf-challenge-crypto-repeated-maleficence-d0c0e096800f
- canonical_url
- https://medium.com/@MrX2025/htb-ai-vs-human-ctf-challenge-crypto-repeated-maleficence-d0c0e096800f
- author_url
- https://medium.com/@MrX2025
- status
- ok
- fetched_at
- 2026-06-15 20:49:13