Challenge / Crypto

Noncesense Encryption

Noncesense Encryption 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-19Sanitized local writeup

Scenario

Noncesense Encryption attack path

Noncesense Encryption 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.

Noncesense Encryption 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 6 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/Noncesense-Encryption/writeup.md
  • htb-challenge/Crypto/Noncesense-Encryption/notes.md
  • htb-challenge/Crypto/Noncesense-Encryption/memory-summary.md
  • htb-challenge/Crypto/Noncesense-Encryption/hypothesis-board.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Crypto__Noncesense-Encryption__memory-summary.md.c8132c9fc8.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Crypto__Noncesense-Encryption__notes.md.698e728700.md

Technical Walkthrough

Writeup

Challenge

  • Name: Noncesense-Encryption
  • Category: Crypto
  • Difficulty: Medium
  • Mode: hybrid

Summary

The service exposes chosen-plaintext encryption for a custom stream-cipher-like

scheme. The keystream is not random: each query uses the flag integer reduced

modulo 0x13373 * (nonce + counter), then expands that small residue through an

invertible linear bit transform. Because the attacker controls plaintext, every

ciphertext reveals one expanded keystream value.

The solve inverts the key expansion to recover several modular residues of the

flag, searches the small timestamp nonce window, and uses CRT to reconstruct the

flag integer.

Artifact Inventory

Reference analysis/artifact-inventory.json and summarize the relevant files or remote surface.

  • files/a12c7366-3ed9-4c61-bdcf-b385e875b951.zip: original HTB ZIP.
  • analysis/extracted/crypto_noncesense_encryption/server.py: provided source

for the encryption service.

  • analysis/server-numbered.txt: numbered source view used during audit.
  • analysis/local-simulation.txt: local proof that the residue recovery and CRT

reconstruction work against fake flags.

  • analysis/remote-recovery-summary.json: sanitized remote recovery metadata.
  • analysis/remote-solve-run.txt: gated remote solve transcript without raw

flag output.

Analysis

The source initializes:

  • generator = bytes_to_long(FLAG.encode())
  • k = 0x13373
  • nonce = int(time())
  • counter = 0

For each encryption, the base key is:

text
base = FLAG_integer mod ((nonce + counter) * k)

Then counter increments. The base key is split into two 25-bit halves and run

through 250 total rounds of the state update:

text
kh, kl = kl, kh ^ kl

The resulting ten 50-bit states are concatenated into the final XOR key. This

update is invertible: given a later (kh, kl), the previous state is

(kh ^ kl, kh). Therefore the low 50 bits of the expanded key can be inverted

250 rounds to recover the original base key.

Since encryption is ciphertext = plaintext xor expanded_key, querying a known

plaintext reveals the expanded key. Repeating this for consecutive counters

gives residues:

text
FLAG_integer ≡ residue_i mod (0x13373 * (nonce + i))

The nonce is a Unix timestamp from service startup. The solver searches a small

window around the observed connection time and applies CRT for each candidate

nonce. With 14 residues, the combined modulus is large enough to recover the

full flag integer directly. The local simulation succeeded in 20/20 fake-flag

runs before remote execution.

Solve

The solver is solve/solve.py. It supports a local simulation and remote mode:

bash
cd <local workspace>
python3 Crypto/Noncesense-Encryption/solve/solve.py --simulate --simulate-runs 20
python3 Crypto/Noncesense-Encryption/solve/solve.py \
  --host <TARGET> \
  --port 31089 \
  --queries 14 \
  --window 1800 \
  --output Crypto/Noncesense-Encryption/loot/flag-candidate.txt

The candidate flag was captured through the harness:

bash
python3 scripts/challenge_harness.py capture-flag Crypto/Noncesense-Encryption --from loot/flag-candidate.txt

Flag

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

Lessons

Custom stream ciphers fail quickly when their keystream is deterministic and

recoverable under chosen plaintext. Nonces must be unique unpredictable inputs

to secure keystream generation; using int(time()) plus a counter around secret

material gave enough structured modular equations to reconstruct the secret.

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: Noncesense-Encryption
  • Category: Crypto
  • Difficulty: Medium
  • Mode: hybrid
  • Remote instance: <TARGET>:31089
  • Start time: 2026-06-11T08:22:29Z
  • 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/a12c7366-3ed9-4c61-bdcf-b385e875b951.zip1167<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-11T08:22:29Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-11T08:22:29Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-11T08:22:29Zsession bootstrapnotes.mdChallenge metadata, scenario, and prior context seeded into workspaceHighRecord initial hypothesis and research
2026-06-11T08:22:29Zhypothesis recordedhypothesis-board.mdinitial triage from supplied challenge metadataMediuminventory files / inspect app surface / map routes depending on category
2026-06-11T08:22:29Zresearch taskanalysis/research/task-20260611T082229965093Z-0b68d19e.mdResearch task created for advisory investigationMediumRecord research output
2026-06-11T08:23:45Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-11T08:23:45Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T082345625964Z-f9a88184.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T08:23:53ZRAG queryanalysis/rag/rag-query-20260611T082345679657Z-94bd202a.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-11T08:24:26ZRAG recordanalysis/rag-records.mdRetrieved memory tagged MISSINGMediumValidate or reject with live evidence
2026-06-11T08:24:26Zresearch recordanalysis/research/research-records.mdResearch tagged MATCHEDMediumValidate against current evidence
2026-06-11T08:24:26Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-11T08:24:26Zhypothesis recordedhypothesis-board.mdchosen-plaintext keystream inversion plus nonce-window CRTMediumSimulate fake server transcript, invert expanded keys to residues, brute-force nonce window, and CRT-recover a fake HTB flag.
2026-06-11T08:26:18Zinstrumentation plananalysis/instrumentation-plan.mdRecover the flag integer from chosen-plaintext keystream leaks by inverting the custom key expansion and solving FLAG mod k*(nonce+counter) residues with CRT.HighStop after two remote failures without new parse/timing facts; do not widen brute force beyond timestamp nonce window without a new checkpoint/evaluator.
2026-06-11T08:26:18Zevaluatoranalysis/evaluator-20260611T082618813057Z-4c2ec2cb.mdProceedHighRun gated remote solve and capture loot/flag-candidate.txt.
2026-06-11T08:26:48Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-11T08:26:48Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T082648294709Z-0dba5730.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T08:27:50Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

-

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.

Scenario

I've mastered Stream Ciphers, and i decided to create one myself!

Operator Question

HTB Crypto Medium Noncesense Encryption custom stream cipher nonce misuse source remote solve path

Memory Summary

Metadata

  • Platform: HackTheBox Challenges
  • Category: Crypto
  • Challenge: Noncesense-Encryption
  • 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
1initial triage from supplied challenge metadatachallenge name, category, difficulty, scenario, and remote target were provided by operatorinventory files / inspect app surface / map routes depending on categoryMediumActive
1chosen-plaintext keystream inversion plus nonce-window CRTencrypt(msg) returns msg xor __gen_key(); __gen_key is invertible; base key is FLAG_integer mod ((nonce+counter)*0x13373); nonce is int(time()).Simulate fake server transcript, invert expanded keys to residues, brute-force nonce window, and CRT-recover a fake HTB flag.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition

Memory Summary

approval_required: true

Sanitized Memory Summary

Metadata

  • Platform: HackTheBox Challenges
  • Category: Crypto
  • Challenge: Noncesense-Encryption
  • 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

Notes

Notes

Scope

  • Challenge: Noncesense-Encryption
  • Category: Crypto
  • Difficulty: Medium
  • Mode: hybrid
  • Remote instance: <TARGET>:31089
  • Start time: 2026-06-11T08:22:29Z
  • 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/a12c7366-3ed9-4c61-bdcf-b385e875b951.zip1167<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-11T08:22:29Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-11T08:22:29Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-11T08:22:29Zsession bootstrapnotes.mdChallenge metadata, scenario, and prior context seeded into workspaceHighRecord initial hypothesis and research
2026-06-11T08:22:29Zhypothesis recordedhypothesis-board.mdinitial triage from supplied challenge metadataMediuminventory files / inspect app surface / map routes depending on category
2026-06-11T08:22:29Zresearch taskanalysis/research/task-20260611T082229965093Z-0b68d19e.mdResearch task created for advisory investigationMediumRecord research output
2026-06-11T08:23:45Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-11T08:23:45Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T082345625964Z-f9a88184.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T08:23:53ZRAG queryanalysis/rag/rag-query-20260611T082345679657Z-94bd202a.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-11T08:24:26ZRAG recordanalysis/rag-records.mdRetrieved memory tagged MISSINGMediumValidate or reject with live evidence
2026-06-11T08:24:26Zresearch recordanalysis/research/research-records.mdResearch tagged MATCHEDMediumValidate against current evidence
2026-06-11T08:24:26Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-11T08: <REDACTED>, invert expanded keys to residues, brute-force nonce window, and CRT-recover a fake HTB flag.
2026-06-11T08: <REDACTED>
2026-06-11T08: <REDACTED>
2026-06-11T08: <REDACTED>
2026-06-11T08:26:48Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T082648294709Z-0dba5730.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T08:27:50Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

-

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.

Scenario

I've mastered Stream Ciphers, and i decided to create one myself!

Operator Question

HTB Crypto Medium Noncesense Encryption custom stream cipher nonce misuse source remote solve path

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 Noncesense Encryption, 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.