Challenge / Mobile

Cryptohorrific

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

MediumPublished 2025-02-06Sanitized local writeup

Scenario

Cryptohorrific attack path

Cryptohorrific 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 Mobile evidence, validation, and reusable operator lessons.

Cryptohorrific sanitized attack graph

Walkthrough flow

01

Extracted an iOS Simulator .app bundle from the...

02

Found challenge.plist containing a Base64-encoded...

03

Used Mach-O Objective-C metadata and otool...

04

Verified the app reads the plist proof,...

05

Reconstructed CCCrypt parameters from register/stack...

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.

  • Mobile/Cryptohorrific/writeup.md
  • htb-challenge/Mobile/Cryptohorrific/notes.md
  • htb-challenge/Mobile/Cryptohorrific/memory-summary.md
  • htb-challenge/Mobile/Cryptohorrific/hypothesis-board.md

Technical Walkthrough

Writeup

Challenge

  • Name: Cryptohorrific
  • Category: Mobile
  • Difficulty: Medium
  • Mode: file

Summary

The archive contains an iOS Simulator .app bundle. The app stores a Base64 ciphertext in challenge.plist and decrypts it at launch with CommonCrypto.

Static Mach-O analysis showed the decrypt routine uses AES with PKCS7 padding and ECB mode. The hardcoded key is stored as a constant NSString in the binary. Replaying the same decrypt operation against the plist ciphertext recovers the flag.

Artifact Inventory

  • files/a12c7373-8d1f-4cf7-94d7-f895d8927018.zip: original HTB archive.
  • analysis/extracted/hackthebox.app/: extracted iOS app bundle.
  • analysis/extracted/hackthebox.app/hackthebox: Mach-O 64-bit x86_64 executable.
  • analysis/extracted/hackthebox.app/challenge.plist: plist containing the encrypted flag value.
  • analysis/otool-disasm.txt: Objective-C and CommonCrypto call flow evidence.
  • analysis/crypto-params.txt: reconstructed crypto parameters.

Analysis

file identified the executable as a 64-bit Mach-O for x86_64. This matched the bundle metadata in analysis/info-plist.txt, which marks the supported platform as iPhoneSimulator.

challenge.plist contains one dictionary with a Base64-encoded flag field. The binary imports _CCCrypt, and Objective-C metadata exposes a method named SecretManager:key:iv:data:.

The viewDidLoad disassembly in analysis/otool-disasm.txt shows the app:

  1. opens challenge.plist;
  2. reads index 0;
  3. extracts the flag key;
  4. Base64-decodes the string into NSData;
  5. calls SecretManager:key:iv:data:.

The SecretManager:key:iv:data: disassembly then sets up CCCrypt as:

  • operation: decrypt;
  • algorithm: AES;
  • options: PKCS7 padding plus ECB mode;
  • key length: 16 bytes;
  • input: Base64-decoded plist ciphertext.

The two constant NSStrings used as key and IV are in __cfstring. The IV is still passed to CCCrypt, but ECB mode does not use it.

Solve

solve/solve.py reproduces the app behavior:

  1. loads analysis/extracted/hackthebox.app/challenge.plist;
  2. Base64-decodes the flag value;
  3. decrypts with <secret redacted> and PKCS7 unpadding;
  4. writes the candidate to loot/flag-candidate.txt.

The harness captured the candidate into loot/flag.txt.

Flag

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

Lessons

  • Mobile challenges are not always APKs; inspect the archive before assuming Android tooling.
  • CommonCrypto calls can be reconstructed directly from x86_64 Mach-O register setup.
  • kCCOptionECBMode makes an IV parameter irrelevant even if the application passes one.
  • Treat RAG as advisory only; the decisive proof was the current binary’s CCCrypt call setup.

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: Cryptohorrific
  • Category: Mobile
  • Difficulty: Medium
  • Mode: file
  • Remote instance: none
  • Start time: 2026-06-15T04:39:28Z
  • 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/a12c7373-8d1f-4cf7-94d7-f895d8927018.zip26184<hash redacted>Zip archive data, at least v2.0 to extract, compression method=storezip entries: 17 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-15T04:39:28Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-15T04:39:28Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-15T04:39:28Zhypothesis recordedhypothesis-board.mdReverse the mobile artifact, identify insecure cryptography or hardcoded material, and recover the HTB flag from app resources/code.MediumExtract APK/source, inspect manifest/resources/classes, and search for crypto APIs, embedded ciphertext, keys, and flag validation logic.
2026-06-15T04:39:39Zcheckpoint recordedanalysis/checkpoint-triage-20260615T043939369546Z-ce3714a1.mdCheckpoint for TRIAGEHighUse checkpoint to drive next decision
2026-06-15T04:41:24ZRAG queryanalysis/rag/rag-query-20260615T044111117094Z-ed89c336.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-15T04:42:20Zinstrumentation plananalysis/instrumentation-plan.mdRecover the encrypted flag from the iOS Mach-O app by validating CommonCrypto parameters statically.HighIf static CCCrypt parameter reconstruction fails or decrypted output is not HTB-formatted, request apktool/class-dump/Ghidra-style tooling instead of guessing alternate modes.
2026-06-15T04:42:36ZRAG recordanalysis/rag-records.mdRetrieved memory tagged MATCHEDMediumValidate or reject with live evidence
2026-06-15T04:42:36Zresearch recordanalysis/research/research-records.mdResearch tagged MATCHEDMediumValidate against current evidence
2026-06-15T04:42:44Zevaluatoranalysis/evaluator-20260615T044244753271Z-3e17e633.mdProceedHighGate before exploit and capture the locally recovered flag candidate.
2026-06-15T04:42:50Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-15T04:43:41Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-15T04:43:49Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • The archive contains an iPhone Simulator .app bundle, not an Android APK.
  • Main binary: analysis/extracted/hackthebox.app/hackthebox, Mach-O 64-bit x86_64.
  • challenge.plist stores a Base64-encoded flag value.
  • ViewController viewDidLoad loads challenge.plist, reads flag, Base64-decodes it, and passes the bytes into SecretManager:key:iv:data:.
  • SecretManager:key:iv:data: wraps CCCrypt with decrypt operation, AES, 16-byte key, PKCS7 padding, and ECB mode.
  • The IV string is passed but ignored because ECB mode is set.
  • Reproducible solver: solve/solve.py.
  • Raw captured flag: loot/flag.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: Mobile
  • Challenge: Cryptohorrific
  • 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 an iOS Simulator .app bundle from the challenge archive.
  2. Found challenge.plist containing a Base64-encoded encrypted flag field.
  3. Used Mach-O Objective-C metadata and otool disassembly to locate ViewController viewDidLoad and SecretManager:key:iv:data:.
  4. Verified the app reads the plist flag, Base64-decodes it, then passes it to CommonCrypto.
  5. Reconstructed CCCrypt parameters from register/stack setup: decrypt, AES, PKCS7 padding, ECB mode, 16-byte key.
  6. Decrypted the plist ciphertext with a reproducible Python solver.
  7. Captured the recovered HTB flag through the harness.

Reusable Lessons

  • Do not assume Mobile means Android; this was an iPhone Simulator Mach-O app.
  • otool -ov and otool -tvV can be enough for small Objective-C iOS Simulator binaries.
  • In CommonCrypto, options value 3 means PKCS7 padding plus ECB mode.
  • In ECB mode, an IV argument can be present but unused.

Dead Ends

  • APK/JADX path was not applicable after ZIP inventory showed an iOS .app.
  • Runtime/emulator tooling was unnecessary because the static CommonCrypto parameters were complete.

Tool Quirks

  • apktool, adb, frida, and class-dump were unavailable, but did not block the solve.
  • otool -tvV produced usable disassembly; otool -tV alone initially produced no useful output.
  • Python crypto libraries were available locally; solver supports both pycryptodome and cryptography.

Evidence Paths

  • analysis/challenge-plist.txt
  • analysis/otool-objc.txt
  • analysis/otool-disasm.txt
  • analysis/crypto-params.txt
  • solve/solve.py
  • loot/flag.txt

Ingestion Decision

  • Proposed for LightRAG: yes
  • 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
1Reverse the mobile artifact, identify insecure cryptography or hardcoded material, and recover the HTB flag from app resources/code.Challenge is Mobile/Medium named Cryptohorrific; prompt emphasizes secure coding and application security.Extract APK/source, inspect manifest/resources/classes, and search for crypto APIs, embedded ciphertext, keys, and flag validation logic.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition

Technical analogy

How to remember this solve

Think of the app like a packed suitcase. You unpack it, inspect the labels and hidden pockets, then trace which local file or network call contains the useful clue.

For Cryptohorrific, 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.