AliEnS Challenge Scenario
HackTheBox
Task: attack an AES-ECB oracle with custom string padding and a fresh random key for every request. Solution: exploit the Unicode-versus-UTF-8 length mismatch to shift byte alignment, then recover the appended flag with same-request ECB block equality matching against a dictionary of candidate blocks.
$ ls tags/ techniques/
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
AliEnS Challenge Scenario — HackTheBox
Description
In a groundbreaking discovery, a research lab uncovered alien technology utilizing AES encryption with custom padding. They engineered a user-friendly interface to interact with this enigmatic advancement. Now, a challenge is presented: Can you crack it?
We are given an encryption oracle that pads attacker input and the flag with a custom routine, concatenates them, UTF-8 encodes the result, and encrypts it with AES-ECB. The obvious defense is that the service generates a fresh random AES key for every request, so the intended solution is to notice that this still does not stop equality checks between blocks produced inside the same request.
Summary
The break comes from a subtle type mismatch. AAES.pad() computes padding length on a Python str, where len() counts Unicode code points, but the ciphertext is produced only after .encode() converts the string to UTF-8 bytes. By injecting multibyte characters such as é, we can move the flag bytes to arbitrary byte offsets while the padding logic still reasons in character counts.
Once the target flag byte is aligned at the end of a 16-byte block, we place a full dictionary of candidate blocks earlier in the same plaintext. ECB with a random key still deterministically maps equal plaintext blocks to equal ciphertext blocks within that single encryption, so the matching ciphertext block reveals the correct next flag byte.
Analysis
The core code is:
class AAES(): def __init__(self): self.padding = "CryptoHackTheBox" def pad(self, plaintext): return plaintext + self.padding[:(-len(plaintext) % 16)] + self.padding def encrypt(self, plaintext): cipher = AES.new(os.urandom(16), AES.MODE_ECB) return cipher.encrypt(pad(plaintext, 16)) plaintext = aaes.pad(message) + aaes.pad(FLAG) print(aaes.encrypt(plaintext.encode()).hex())
...
$ grep --similar
Similar writeups
- [crypto][free]xorxorxor— hackthebox
- [crypto][free]MadMath— hackthebox
- [crypto][free]Rhome— HackTheBox
- [crypto][Pro]Enigma— hackerlab
- [hardware][free]Project Power Challenge Scenario— hackthebox