AliEnS
AliEnS is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
AliEnS attack path
AliEnS is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Objective
Challenge walkthrough focused on Crypto evidence, validation, and reusable operator lessons.
Walkthrough flow
Challenge parameters
Weak assumption
Recovered secret state
Proof captured
Source coverage
High source coverage
Status: complete. This article is generated from 4 sanitized Markdown sources and keeps raw flags, credentials, keys, cookies, and reusable secrets out of the rendered blog.
High confidence: the page is reconstructed from a primary walkthrough plus multiple supporting notes or evidence sources. Treat the chain as source-backed, while still checking the listed source files for sensitive values.
- Crypto/AliEnS/writeup.md
- htb-challenge/Crypto/AliEnS/notes.md
- htb-challenge/Crypto/AliEnS/memory-summary.md
- htb-challenge/Crypto/AliEnS/hypothesis-board.md
Technical Walkthrough
Writeup
Challenge
- Name: AliEnS
- Category: Crypto
- Difficulty: Medium
- Mode: hybrid
Summary
AliEnS is an AES-ECB oracle with a fresh random key per request. Cross-request codebooks do not work, but ECB equality still works inside a single response. The custom padding computes length on Python characters and then encrypts UTF-8 bytes, so multibyte input shifts the flag alignment. The solve uses that mismatch to place each flag byte at the end of a block and compares it against same-response candidate blocks.
Artifact Inventory
files/a12c7338-23e5-4751-b074-87923e5d55d5.zip: original challenge archive.files/extracted/crypto_aliens/server.py: source for the remote encryption service.- Remote service:
<TARGET>:30318.
Analysis
The key source facts are recorded in analysis/source-audit.md.
AAES.pad() uses len(plaintext) before encoding, while encrypt() uses plaintext.encode() before AES encryption. ASCII input has equal character and byte lengths, so the flag remains block-aligned. The alien emoji has character length 1 and UTF-8 byte length 4, creating a 3-byte shift modulo 16. Since 3 is invertible modulo 16, repeated emoji input can create any desired flag alignment.
The AES key is randomized for every request, so the solver cannot compare ciphertext across requests. Instead, for each unknown byte, it sends one message containing candidate plaintext blocks and the shifted flag block in the same encryption. Matching ciphertext blocks identify the candidate byte.
Local validation is in analysis/local-self-test.txt; direct source research is in analysis/research/direct-source.md.
Solve
Run:
python3 solve/solve.py --host <TARGET> --port 30318 --output loot/flag.txtThe harness run used scripts/challenge_exec.py so the exploit gate was checked first. The final solver no longer prints partial flag material during verbose progress.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- When a service uses a random key per request, ECB codebooks must be built inside the same encryption response.
- Length checks on Unicode strings are not equivalent to byte lengths after UTF-8 encoding.
- A small modular shift primitive can be enough for byte-at-a-time ECB recovery if the shift value is invertible modulo the block size.
Source-Backed Dossier
The sections below are merged from companion Markdown notes for the same case. They are rendered after sanitization so the article stays precise without publishing raw flags, credentials, or target-specific secrets.
Notes
Scope
- Challenge: AliEnS
- Category: Crypto
- Difficulty: Medium
- Mode: hybrid
- Remote instance: none
- Start time: 2026-06-12T22:57:14Z
- Operator: harness
- State file:
challenge-state.json
Harness Status
- Current phase: see
challenge-state.json - Next allowed actions: see
next-action.json - Raw flags and sensitive material stay in
loot/only. Do not paste them here.
Artifact Inventory
| File | Size | SHA256 | Type | Notes |
|---|---|---|---|---|
files/a12c7338-23e5-4751-b074-87923e5d55d5.zip | 720 | <hash redacted> | Zip archive data, at least v1.0 to extract, compression method=store | zip entries: 2 shown in artifact inventory JSON |
files/extracted/crypto_aliens/server.py | 684 | <hash redacted> | Python script text executable, ASCII text |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-12T22:57:14Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-12T22:57:33Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-12T22:57:44Z | artifact inventory | analysis/artifact-inventory.json | 2 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-12T22:59:37Z | hypothesis recorded | hypothesis-board.md | Exploit character-length custom padding with multibyte UTF-8 input to shift the flag inside AES-ECB blocks; build same-query candidate blocks because the key is randomized per request. | Medium | Local reproduction with dummy flag, then gated remote solver against <TARGET>:30318. |
| 2026-06-12T22:59:37Z | source audit | analysis/source-audit.md | Source audit recorded | High | Gate before exploit |
| 2026-06-12T23:00:45Z | instrumentation plan | analysis/instrumentation-plan.md | Recover the remote AliEnS flag by exploiting UTF-8 character-length padding mismatch in AES-ECB. | High | Stop on flag capture, missing candidate match for any byte, remote timeout, or invalid HTB flag format. |
| 2026-06-12T23:01:02Z | RAG query | analysis/rag/rag-query-20260612T230045790056Z-bed66d68.txt | RAG helper exited 0; output saved | Medium | Record retrieval tag and validation |
| 2026-06-12T23:01:46Z | RAG record | analysis/rag-records.md | Retrieved memory tagged PARTIAL | Medium | Validate or reject with live evidence |
| 2026-06-12T23:01:46Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-12T23:02:13Z | checkpoint recorded | analysis/checkpoint-analysis-20260612T230213438366Z-932533f1.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-12T23:02:22Z | evaluator | analysis/evaluator-20260612T230222748397Z-9f84a4fb.md | Proceed | High | Gated remote solver execution and flag capture. |
| 2026-06-12T23:03:20Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-12T23:03:59Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
server.pyencrypts with AES-ECB and a fresh random key per request, so ciphertext comparisons must happen within one response.- The custom padding uses Python character length, but encryption uses UTF-8 bytes. A multibyte character shifts the flag byte offset by
len(char.encode()) - len(char)modulo 16. - The alien emoji shifts by 3 bytes, and 3 is invertible modulo 16, so repeated emoji input can place each target flag byte at a chosen block position.
solve/solve.pybuilds same-response candidate blocks and compares them against the shifted flag block to recover the flag byte by byte.- Local self-test passed with a dummy non-HTB secret in
analysis/local-self-test.txt.
RAG / Advisory Memory
RAG output is advisory only. Record evaluated retrievals with:
scripts/challenge_harness.py rag-record <workspace> --query "..." --tag MATCHED|PARTIAL|MISSING|<secret redacted>|GENERIC --validation "..."Secrets/Flags
Raw flags and sensitive material stay in loot/ only. Use scripts/challenge_harness.py capture-flag to validate and record flag capture without printing the value.
Memory Summary
Metadata
- Platform: HackTheBox Challenges
- Category: Crypto
- Challenge: AliEnS
- Difficulty: Medium
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
1.
Reusable Lessons
-
Dead Ends
-
Tool Quirks
-
Evidence Paths
-
Ingestion Decision
- Proposed for LightRAG: yes/no
- Requires user approval before ingestion: yes
Hypothesis Board
Keep no more than 3 active hypotheses on Easy/Medium and 5 on Hard unless the user explicitly asks for breadth.
| Rank | Path | Evidence | Missing Proof | Cheapest Validation | Confidence | Status |
|---|---|---|---|---|---|---|
| 1 | Exploit character-length custom padding with multibyte UTF-8 input to shift the flag inside AES-ECB blocks; build same-query candidate blocks because the key is randomized per request. | server.py pads with len(message) characters in AAES.pad(), then encrypts plaintext.encode() under AES-ECB with a fresh random key; ECB block equality still holds within each response. | Local reproduction with dummy flag, then gated remote solver against <TARGET>:30318. | Medium | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit Condition |
|---|
Technical analogy
How to remember this solve
Think of the challenge like a locked box where the lock is mathematical but slightly flawed. The goal is not to smash the box; it is to notice which part of the lock repeats, leaks, or trusts the wrong assumption.
For AliEnS, keep the mental model simple: identify the trusted assumption, prove it with the smallest safe test, then automate or repeat only the part that directly leads to the flag.