Challenge / Crypto

AliEnS

AliEnS is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator

MediumPublished 2024-03-15Sanitized local writeup

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.

AliEnS sanitized attack graph

Walkthrough flow

01

Challenge parameters

02

Weak assumption

03

Recovered secret state

04

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.

93% coverage
Evidence verdict

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:

bash
python3 solve/solve.py --host <TARGET> --port 30318 --output loot/flag.txt

The 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

FileSizeSHA256TypeNotes
files/a12c7338-23e5-4751-b074-87923e5d55d5.zip720<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 2 shown in artifact inventory JSON
files/extracted/crypto_aliens/server.py684<hash redacted>Python script text executable, ASCII text

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-12T22:57:14Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-12T22:57:33Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-12T22:57:44Zartifact inventoryanalysis/artifact-inventory.json2 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-12T22:59:37Zhypothesis recordedhypothesis-board.mdExploit 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.MediumLocal reproduction with dummy flag, then gated remote solver against <TARGET>:30318.
2026-06-12T22:59:37Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-12T23:00:45Zinstrumentation plananalysis/instrumentation-plan.mdRecover the remote AliEnS flag by exploiting UTF-8 character-length padding mismatch in AES-ECB.HighStop on flag capture, missing candidate match for any byte, remote timeout, or invalid HTB flag format.
2026-06-12T23:01:02ZRAG queryanalysis/rag/rag-query-20260612T230045790056Z-bed66d68.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-12T23:01:46ZRAG recordanalysis/rag-records.mdRetrieved memory tagged PARTIALMediumValidate or reject with live evidence
2026-06-12T23:01:46Zresearch recordanalysis/research/research-records.mdResearch tagged MATCHEDMediumValidate against current evidence
2026-06-12T23:02:13Zcheckpoint recordedanalysis/checkpoint-analysis-20260612T230213438366Z-932533f1.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-12T23:02:22Zevaluatoranalysis/evaluator-20260612T230222748397Z-9f84a4fb.mdProceedHighGated remote solver execution and flag capture.
2026-06-12T23:03:20Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-12T23:03:59Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • server.py encrypts 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.py builds 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:

bash
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.

RankPathEvidenceMissing ProofCheapest ValidationConfidenceStatus
1Exploit 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.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit 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.