Challenge / Crypto

Neon Core

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

MediumPublished 2024-04-16Sanitized local writeup

Scenario

Neon Core attack path

Neon Core 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.

Neon Core sanitized attack graph

Walkthrough flow

01

Extracted the HTB ZIP and audited server.py.

02

Identified encryption as C = K S(M) L + T over...

03

Reframed the block cipher as a 16-dimensional affine...

04

Used 17 chosen plaintext blocks in one keyed remote...

05

Inverted the transform, applied S_inv(x)=x^171,...

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.

100% 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/Neon-Core/writeup.md
  • htb-challenge/Crypto/Neon-Core/notes.md
  • htb-challenge/Crypto/Neon-Core/memory-summary.md
  • htb-challenge/Crypto/Neon-Core/hypothesis-board.md

Technical Walkthrough

Writeup

Challenge

  • Name: Neon-Core
  • Category: Crypto
  • Difficulty: Medium
  • Mode: hybrid

Summary

Neon Core is a source-backed remote crypto challenge. The provided server.py encrypts a padded 16-byte block by applying a known byte-wise S-box and then a fixed affine matrix transformation over GF(257). Because the same keyed transform is used for attacker-chosen messages and the encrypted blueprint, the transform can be learned and inverted.

Artifact Inventory

The artifact is a <password redacted> HTB ZIP:

  • files/a12c7356-7a56-47fb-b6e7-ed9b1812452c.zip
  • extracted source: files/extracted/crypto_neon_core/server.py

The remote service is <TARGET>:31023. The source audit is recorded in analysis/source-audit.md.

Analysis

The source defines:

text
C = K * S(M) * L + T
S(x) = x^3 over GF(257)
S_inv(x) = x^171

Flattened into a 16-element vector, this is an affine map:

text
vec(C) = A * vec(S(M)) + vec(T)

The chosen-plaintext oracle gives enough equations to recover A and the offset. The solver uses a one-block calibration strategy:

  • baseline: 15 A characters, so the final byte is PKCS#7 padding 0x01
  • positions 0-14: replace one A with B to recover each column
  • position 15: compare a 14-byte message, where the last two bytes become padding 0x02, then subtract the known position-14 contribution

The deployed service had a protocol quirk: repeated interactive queries on the same connection closed unexpectedly, but pre-sending all menu choices in one connection worked and kept the same random matrices for all calibration queries and the blueprint request.

The ciphertext encoder also has an edge case: field element 256 is serialized as 100, while normal byte-sized values are two hex characters. The solver parses mixed-width candidates and accepts the candidate that decrypts to valid PKCS#7 and the expected HTB flag format.

Solve

The reproducible solver is:

bash
python3 Crypto/Neon-Core/solve/solve.py --host <TARGET> --port 31023 --workspace Crypto/Neon-Core

It records redacted run metadata in analysis/solve-run-redacted.json and stores the raw flag in loot/flag.txt.

Flag

Raw flag is stored in loot/flag.txt and intentionally not reproduced here.

Lessons

  • A known nonlinear layer followed by a fixed affine layer is still vulnerable to chosen-plaintext linearization.
  • Source-provided finite-field ciphers should be modeled exactly; no floating-point math is needed.
  • Remote service behavior may differ from the source loop. If keys are per process, batching menu inputs can preserve one keyed session.
  • Encoding field elements as variable-width hex needs explicit parsing.

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: Neon-Core
  • Category: Crypto
  • Difficulty: Medium
  • Mode: hybrid
  • Remote instance: <TARGET>:31023
  • Start time: 2026-06-11T12:45:17Z
  • 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/a12c7356-7a56-47fb-b6e7-ed9b1812452c.zip1190<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 2 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-11T12:45:17Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-11T12:45:28Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-11T12:45:43Zhypothesis recordedhypothesis-board.mdAudit server.py for a flawed custom cipher or oracle interaction, then reproduce locally before remote queriesMediumRead server.py, identify primitive/oracle/flag flow, and build a local solver against the same functions before connecting to <TARGET>:31023
2026-06-11T12:45:43Zresearch taskanalysis/research/task-20260611T124543649041Z-0265298b.mdResearch task created for advisory investigationMediumRecord research output
2026-06-11T12:47:53Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-11T12:47:53Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T124753522929Z-d414d7f2.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T12:47:53Zinstrumentation plananalysis/instrumentation-plan.mdRecover and invert the Neon Core affine encryption map with minimal remote oracle calls.HighStop if ciphertext parsing is ambiguous without a valid HTB plaintext, if the affine matrix is singular, or if the remote service protocol differs from server.py.
2026-06-11T12:48:02ZRAG queryanalysis/rag/rag-query-20260611T124753558509Z-5ba305d8.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-11T12:48:25ZRAG recordanalysis/rag-records.mdRetrieved memory tagged MISSINGMediumValidate or reject with live evidence
2026-06-11T12:48:45Zlocal memory searchanalysis/research/local-memory-search-20260611T124845602120Z-c679c2bc.mdFound 5 safe prior-note result(s)MediumRecord useful result or skip
2026-06-11T12:49:28Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-11T12:49:37Zevaluatoranalysis/evaluator-20260611T124937807273Z-d2a79da2.mdProceedHighRun the finite-field solver against <TARGET>:31023, capture only the resulting HTB flag into loot/flag.txt, and stop if protocol or parsing assumptions fail.
2026-06-11T12:56:07Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-11T12:57:50Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • The archive is the standard HTB <password redacted> ZIP and extracts to crypto_neon_core/server.py.
  • server.py uses Sage-style GF(257) matrices. Each plaintext block is transformed as C = K S(M) L + T, where S(x)=x^3.
  • Since gcd(3, 256)=1, the S-box is invertible over GF(257) with S_inv(x)=x^171.
  • The block transform is affine in the vector of S-box outputs. Chosen plaintext encryption lets us recover the full 16x16 affine map.
  • The deployed service closes when used interactively for repeated follow-up actions, but it processes a pre-sent batch of menu inputs in one keyed process. The final solver uses this batch behavior.
  • solve/solve.py sends 17 calibration encryption requests plus the blueprint request in one connection, learns the affine map, handles 256 -> "100" mixed-width ciphertext encoding, decrypts the blueprint, and writes the raw flag to loot/flag.txt.
  • RAG had no matching Neon Core guidance. The solve is based on direct source audit plus local fallback notes about exact algebraic inversion.

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: Neon-Core
  • 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. Extracted the HTB ZIP and audited server.py.
  2. Identified encryption as C = K S(M) L + T over GF(257), with S(x)=x^3.
  3. Reframed the block cipher as a 16-dimensional affine map after an invertible S-box.
  4. Used 17 chosen plaintext blocks in one keyed remote session to recover the affine transform.
  5. Inverted the transform, applied S_inv(x)=x^171, removed PKCS#7 padding, and recovered the HTB-format flag.

Reusable Lessons

  • For source-backed custom ciphers, flatten matrix operations and look for affine structure.
  • Chosen plaintext often turns nonlinear-looking constructions into exact linear algebra if the nonlinear layer is known and invertible.
  • If a service uses per-process random keys and closes after one interactive action, test pre-sending all menu inputs in one connection.
  • When GF(257) values are serialized as hex, handle the 256 -> "100" variable-width token.

Dead Ends

  • Initial interactive solver assumed the service loop allowed repeated live prompts. The deployed wrapper closed after a single action, so the solver was changed to batch all inputs.
  • RAG did not contain useful Neon Core-specific guidance.

Tool Quirks

  • sage and sympy were unavailable locally, but pure Python modular arithmetic and Gauss-Jordan inversion over modulus 257 were enough.
  • The remote output marker differed slightly from the provided source: deployed service used Encrypted configuration (hex):.

Evidence Paths

  • analysis/source-audit.md
  • analysis/instrumentation-plan.md
  • analysis/solve-run-redacted.json
  • solve/solve.py
  • loot/flag.txt

Ingestion Decision

  • Proposed for LightRAG: yes, sanitized only
  • 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
1Audit server.py for a flawed custom cipher or oracle interaction, then reproduce locally before remote queriesArchive contains a single crypto_neon_core/server.py source file and the challenge provides a remote serviceRead server.py, identify primitive/oracle/flag flow, and build a local solver against the same functions before connecting to <TARGET>:31023MediumActive

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 Neon Core, 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.