Challenge / Mobile

Arno

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

EasyPublished 2025-01-18Sanitized local writeup

Scenario

Arno attack path

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

Arno sanitized attack graph

Walkthrough flow

01

Artifact review

02

Hypothesis

03

Validated solve path

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.

  • Mobile/Arno/writeup.md
  • htb-challenge/Mobile/Arno/notes.md
  • htb-challenge/Mobile/Arno/memory-summary.md
  • htb-challenge/Mobile/Arno/hypothesis-board.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Mobile__Arno__memory-summary.md.99e271c8eb.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Mobile__Arno__notes.md.ae7d87ee3a.md

Technical Walkthrough

Writeup

Challenge

  • Name: Arno
  • Category: Mobile
  • Difficulty: Easy
  • Mode: file

Summary

This APK is a Unity IL2CPP build, so the flag path is in native IL2CPP metadata rather than Android Java code. Recovering FlagControl from libil2cpp.so plus global-metadata.dat shows dedicated GetKey(), GetIV(), GetFlag(), and DecryptFlag(...) methods. The class-local Assembly-CSharp PrivateImplementationDetails block holds matching 32-byte, 16-byte, and 48-byte blobs. Extracting those bytes from global-metadata.dat and decrypting them as <secret redacted> with PKCS#7 yields the flag offline.

Artifact Inventory

The relevant artifacts were:

  • files/extracted/Arno.apk
  • analysis/apk/lib/arm64-v8a/libil2cpp.so
  • analysis/apk/assets/bin/Data/Managed/Metadata/global-metadata.dat
  • analysis/apk/assets/bin/Data/data.unity3d
  • analysis/il2cppdump/dump.cs
  • analysis/local-validation/offline-decryption.md

Analysis

data.unity3d and related scene strings confirm this is a Unity UI with AppControl, QuoteButton, InputField, and Flag objects, but that only gives the surface. The decisive step is recovering the IL2CPP metadata.

Running Il2CppDumper against libil2cpp.so and global-metadata.dat produces analysis/il2cppdump/dump.cs. In that dump, FlagControl exposes:

  • GetKey()
  • GetIV()
  • GetFlag()
  • DecryptFlag(byte[] key, byte[] iv, byte[] encryptedData)

Those method names, plus the recovered AArch64 disassembly, show that the class reads fixed-length byte arrays for the key, IV, and ciphertext.

Immediately after the FlagControl class definition in dump.cs, the Assembly-CSharp PrivateImplementationDetails block contains exactly the matching blob sizes:

  • 16-byte entry for the IV
  • 48-byte entry for the encrypted flag
  • 32-byte entry for the AES key

The corresponding metadata offsets are extracted from that same block and then read directly from global-metadata.dat. The sanitized proof is recorded in analysis/local-validation/offline-decryption.md.

Solve

Run:

bash
cd <local workspace>
python3 Mobile/Arno/solve/solve.py

The solver:

  1. Parses analysis/il2cppdump/dump.cs to locate the FlagControl-adjacent PrivateImplementationDetails block.
  2. Extracts the 16-byte IV, 48-byte ciphertext, and 32-byte key offsets.
  3. Reads those blobs from analysis/apk/assets/bin/Data/Managed/Metadata/global-metadata.dat.
  4. Decrypts the ciphertext with <secret redacted>.
  5. Removes PKCS#7 padding and writes the recovered flag candidate to loot/flag-candidate.txt.

Flag

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

Lessons

  • Unity IL2CPP mobile challenges often hide the real solve in metadata-backed native code, even when the scene strings suggest an input-validation puzzle.
  • PrivateImplementationDetails blocks are worth checking whenever GetKey/GetIV/GetFlag style methods appear near compiler-generated metadata blobs.

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: Arno
  • Category: Mobile
  • Difficulty: Easy
  • Mode: file
  • Remote instance: none
  • Start time: 2026-06-07T19:07:37Z
  • 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/a12c738d-1cab-4f7b-9647-a7dd9eab580a.zip31810095<hash redacted>Zip archive data, at least v2.0 to extract, compression method=deflatezip entries: 1 shown in artifact inventory JSON
files/extracted/Arno.apk7405568<hash redacted>Zip archive data, at least v0.0 to extract, compression method=deflate

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-07T19:07:37Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-07T19:08:01Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T19:08:11Zartifact inventoryanalysis/artifact-inventory.json2 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T19:11:22Zhypothesis recordedhypothesis-board.mdReverse the Unity IL2CPP app logic behind AppControl/QuoteButton/InputField. The scene strings show an input field, a quote button, a Flag object, and a 'quotereversed' asset/name; likely the app checks whether the user enters a transformed Arno Dorian quote, possibly the reverse of a quote string, then reveals/builds the flag.HighUse Il2CppDumper/Cpp2IL/AssetRipper/UABEA/UnityPy to map Assembly-CSharp methods and scene objects, then identify AppControl button handler and any validation/flag construction routine.
2026-06-07T19:11:22Zresearch taskanalysis/research/task-20260607T191122247620Z-fbcd8da4.mdResearch task created for advisory investigationMediumRecord research output
2026-06-07T19:11:22Zcheckpoint recordedanalysis/checkpoint-hypothesis_ready-20260607T191122270477Z-29a741c1.mdCheckpoint for <secret redacted>HighUse checkpoint to drive next decision
2026-06-07T19:11:38Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-07T19:11:38Zlocal memory searchanalysis/research/local-memory-search-20260607T191138509565Z-84445443.mdFound 8 safe prior-note result(s)MediumRecord useful result or skip
2026-06-07T19:11:47ZRAG queryanalysis/rag/rag-query-20260607T191138511063Z-1a374d4a.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-07T19:12:16ZRAG recordanalysis/rag-records.mdRetrieved memory tagged MISSINGMediumValidate or reject with live evidence
2026-06-07T19:12:16Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-07T19:12:16Zevaluatoranalysis/evaluator-20260607T191216154987Z-fcb61a7f.mdValidate firstHighRecover AppControl and scene object data with Unity IL2CPP/asset tooling before attempting a flag candidate.
2026-06-07T19:28:36Zevaluatoranalysis/evaluator-20260607T192836540477Z-442b0caa.mdProceedHighcapture the offline decrypted flag candidate from loot/flag-candidate.txt
2026-06-07T19:28:44Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-07T19:29:02Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • Arno.apk is a Unity IL2CPP release build, so the real app logic lives in analysis/apk/lib/arm64-v8a/libil2cpp.so and analysis/apk/assets/bin/Data/Managed/Metadata/global-metadata.dat, not in Java wrapper code.
  • Il2CppDumper recovered FlagControl with methods GetKey(), GetIV(), GetFlag(), and DecryptFlag(...) in analysis/il2cppdump/dump.cs.
  • The Assembly-CSharp PrivateImplementationDetails block immediately after FlagControl contains exactly the three blob sizes used by those methods: 16-byte IV, 48-byte ciphertext, and 32-byte key.
  • Extracting those blobs from global-metadata.dat and decrypting them offline with <secret redacted> and PKCS#7 produced a valid HTB flag candidate; see analysis/local-validation/offline-decryption.md and solve/solve.py.

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: Arno
  • Difficulty: Easy
  • 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
1Reverse the Unity IL2CPP app logic behind AppControl/QuoteButton/InputField. The scene strings show an input field, a quote button, a Flag object, and a 'quotereversed' asset/name; likely the app checks whether the user enters a transformed Arno Dorian quote, possibly the reverse of a quote string, then reveals/builds the flag.APK is Unity 6000.0.25f1 IL2CPP. data.unity3d strings include AppControl, QuoteButton, InputField, Enter text..., Arno Dorian once said:, Flag, and quotereversed. global-metadata strings include quote-like challenge strings such as 'In a world without gold, we might have been heroes.' and 'A single spark of truth can burn down entire kingdoms.'Use Il2CppDumper/Cpp2IL/AssetRipper/UABEA/UnityPy to map Assembly-CSharp methods and scene objects, then identify AppControl button handler and any validation/flag construction routine.HighActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition

Memory Summary

approval_required: true

Sanitized Memory Summary

Metadata

  • Platform: HackTheBox Challenges
  • Category: Mobile
  • Challenge: Arno
  • Difficulty: Easy
  • 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: Arno
  • Category: Mobile
  • Difficulty: Easy
  • Mode: file
  • Remote instance: none
  • Start time: 2026-06-07T19:07:37Z
  • 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/a12c738d-1cab-4f7b-9647-a7dd9eab580a.zip31810095<hash redacted>Zip archive data, at least v2.0 to extract, compression method=deflatezip entries: 1 shown in artifact inventory JSON
files/extracted/Arno.apk7405568<hash redacted>Zip archive data, at least v0.0 to extract, compression method=deflate

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-07T19:07:37Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-07T19:08:01Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T19:08:11Zartifact inventoryanalysis/artifact-inventory.json2 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T19: <REDACTED>, a quote button, a Flag object, and a 'quotereversed' asset/name; likely the app checks whether the user enters a transformed Arno Dorian quote, possibly the reverse of a quote string, then reveals/builds the flag.HighUse Il2CppDumper/Cpp2IL/AssetRipper/UABEA/UnityPy to map Assembly-CSharp methods and scene objects, then identify AppControl button handler and any validation/flag construction routine.
2026-06-07T19:11:22Zresearch taskanalysis/research/task-20260607T191122247620Z-fbcd8da4.mdResearch task created for advisory investigationMediumRecord research output
2026-06-07T19:11:22Zcheckpoint recordedanalysis/checkpoint-hypothesis_ready-20260607T191122270477Z-29a741c1.mdCheckpoint for <secret redacted>HighUse checkpoint to drive next decision
2026-06-07T19:11:38Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-07T19:11:38Zlocal memory searchanalysis/research/local-memory-search-20260607T191138509565Z-84445443.mdFound 8 safe prior-note result(s)MediumRecord useful result or skip
2026-06-07T19:11:47ZRAG queryanalysis/rag/rag-query-20260607T191138511063Z-1a374d4a.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-07T19:12:16ZRAG recordanalysis/rag-records.mdRetrieved memory tagged MISSINGMediumValidate or reject with live evidence
2026-06-07T19:12:16Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-07T19: <REDACTED>
2026-06-07T19: <REDACTED>
2026-06-07T19: <REDACTED>
2026-06-07T19:29:02Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • Arno.apk is a Unity IL2CPP release build, so the real app logic lives in analysis/apk/lib/arm64-v8a/libil2cpp.so and analysis/apk/assets/bin/Data/Managed/Metadata/global-metadata.dat, not in Java wrapper code.
  • Il2CppDumper recovered FlagControl with methods GetKey(), GetIV(), GetFlag(), and DecryptFlag(...) in analysis/il2cppdump/dump.cs.
  • The Assembly-CSharp PrivateImplementationDetails block immediately after FlagControl contains exactly the three blob sizes used by those methods: 16-byte IV, 48-byte ciphertext, and 32-byte key.
  • Extracting those blobs from global-metadata.dat and decrypting them offline with <secret redacted> and PKCS#7 produced a valid HTB flag candidate; see analysis/local-validation/offline-decryption.md and solve/solve.py.

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.

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 Arno, 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.