Arno
Arno is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
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.
Walkthrough flow
Artifact review
Hypothesis
Validated solve path
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.
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.apkanalysis/apk/lib/arm64-v8a/libil2cpp.soanalysis/apk/assets/bin/Data/Managed/Metadata/global-metadata.datanalysis/apk/assets/bin/Data/data.unity3danalysis/il2cppdump/dump.csanalysis/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:
cd <local workspace>
python3 Mobile/Arno/solve/solve.pyThe solver:
- Parses
analysis/il2cppdump/dump.csto locate theFlagControl-adjacentPrivateImplementationDetailsblock. - Extracts the 16-byte IV, 48-byte ciphertext, and 32-byte key offsets.
- Reads those blobs from
analysis/apk/assets/bin/Data/Managed/Metadata/global-metadata.dat. - Decrypts the ciphertext with <secret redacted>.
- 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.
PrivateImplementationDetailsblocks are worth checking wheneverGetKey/GetIV/GetFlagstyle 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
| File | Size | SHA256 | Type | Notes |
|---|---|---|---|---|
files/a12c738d-1cab-4f7b-9647-a7dd9eab580a.zip | 31810095 | <hash redacted> | Zip archive data, at least v2.0 to extract, compression method=deflate | zip entries: 1 shown in artifact inventory JSON |
files/extracted/Arno.apk | 7405568 | <hash redacted> | Zip archive data, at least v0.0 to extract, compression method=deflate |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-07T19:07:37Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-07T19:08:01Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T19:08:11Z | artifact inventory | analysis/artifact-inventory.json | 2 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T19:11:22Z | hypothesis recorded | hypothesis-board.md | Reverse 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. | High | 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. |
| 2026-06-07T19:11:22Z | research task | analysis/research/task-20260607T191122247620Z-fbcd8da4.md | Research task created for advisory investigation | Medium | Record research output |
| 2026-06-07T19:11:22Z | checkpoint recorded | analysis/checkpoint-hypothesis_ready-20260607T191122270477Z-29a741c1.md | Checkpoint for <secret redacted> | High | Use checkpoint to drive next decision |
| 2026-06-07T19:11:38Z | source audit | analysis/source-audit.md | Source audit recorded | High | Gate before exploit |
| 2026-06-07T19:11:38Z | local memory search | analysis/research/local-memory-search-20260607T191138509565Z-84445443.md | Found 8 safe prior-note result(s) | Medium | Record useful result or skip |
| 2026-06-07T19:11:47Z | RAG query | analysis/rag/rag-query-20260607T191138511063Z-1a374d4a.txt | RAG helper exited 0; output saved | Medium | Record retrieval tag and validation |
| 2026-06-07T19:12:16Z | RAG record | analysis/rag-records.md | Retrieved memory tagged MISSING | Medium | Validate or reject with live evidence |
| 2026-06-07T19:12:16Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-07T19:12:16Z | evaluator | analysis/evaluator-20260607T191216154987Z-fcb61a7f.md | Validate first | High | Recover AppControl and scene object data with Unity IL2CPP/asset tooling before attempting a flag candidate. |
| 2026-06-07T19:28:36Z | evaluator | analysis/evaluator-20260607T192836540477Z-442b0caa.md | Proceed | High | capture the offline decrypted flag candidate from loot/flag-candidate.txt |
| 2026-06-07T19:28:44Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-07T19:29:02Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
Arno.apkis a Unity IL2CPP release build, so the real app logic lives inanalysis/apk/lib/arm64-v8a/libil2cpp.soandanalysis/apk/assets/bin/Data/Managed/Metadata/global-metadata.dat, not in Java wrapper code.Il2CppDumperrecoveredFlagControlwith methodsGetKey(),GetIV(),GetFlag(), andDecryptFlag(...)inanalysis/il2cppdump/dump.cs.- The
Assembly-CSharpPrivateImplementationDetailsblock immediately afterFlagControlcontains 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.datand decrypting them offline with <secret redacted> and PKCS#7 produced a valid HTB flag candidate; seeanalysis/local-validation/offline-decryption.mdandsolve/solve.py.
RAG / Advisory Memory
RAG output is advisory only. Record evaluated retrievals with:
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.
| Rank | Path | Evidence | Missing Proof | Cheapest Validation | Confidence | Status |
|---|---|---|---|---|---|---|
| 1 | Reverse 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. | High | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit 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
| File | Size | SHA256 | Type | Notes |
|---|---|---|---|---|
files/a12c738d-1cab-4f7b-9647-a7dd9eab580a.zip | 31810095 | <hash redacted> | Zip archive data, at least v2.0 to extract, compression method=deflate | zip entries: 1 shown in artifact inventory JSON |
files/extracted/Arno.apk | 7405568 | <hash redacted> | Zip archive data, at least v0.0 to extract, compression method=deflate |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-07T19:07:37Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-07T19:08:01Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T19:08:11Z | artifact inventory | analysis/artifact-inventory.json | 2 artifact(s) inventoried | High | Build 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. | High | 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. | |||
| 2026-06-07T19:11:22Z | research task | analysis/research/task-20260607T191122247620Z-fbcd8da4.md | Research task created for advisory investigation | Medium | Record research output |
| 2026-06-07T19:11:22Z | checkpoint recorded | analysis/checkpoint-hypothesis_ready-20260607T191122270477Z-29a741c1.md | Checkpoint for <secret redacted> | High | Use checkpoint to drive next decision |
| 2026-06-07T19:11:38Z | source audit | analysis/source-audit.md | Source audit recorded | High | Gate before exploit |
| 2026-06-07T19:11:38Z | local memory search | analysis/research/local-memory-search-20260607T191138509565Z-84445443.md | Found 8 safe prior-note result(s) | Medium | Record useful result or skip |
| 2026-06-07T19:11:47Z | RAG query | analysis/rag/rag-query-20260607T191138511063Z-1a374d4a.txt | RAG helper exited 0; output saved | Medium | Record retrieval tag and validation |
| 2026-06-07T19:12:16Z | RAG record | analysis/rag-records.md | Retrieved memory tagged MISSING | Medium | Validate or reject with live evidence |
| 2026-06-07T19:12:16Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-07T19: <REDACTED> | |||||
| 2026-06-07T19: <REDACTED> | |||||
| 2026-06-07T19: <REDACTED> | |||||
| 2026-06-07T19:29:02Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
Arno.apkis a Unity IL2CPP release build, so the real app logic lives inanalysis/apk/lib/arm64-v8a/libil2cpp.soandanalysis/apk/assets/bin/Data/Managed/Metadata/global-metadata.dat, not in Java wrapper code.Il2CppDumperrecoveredFlagControlwith methodsGetKey(),GetIV(),GetFlag(), andDecryptFlag(...)inanalysis/il2cppdump/dump.cs.- The
Assembly-CSharpPrivateImplementationDetailsblock immediately afterFlagControlcontains 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.datand decrypting them offline with <secret redacted> and PKCS#7 produced a valid HTB flag candidate; seeanalysis/local-validation/offline-decryption.mdandsolve/solve.py.
RAG / Advisory Memory
RAG output is advisory only. Record evaluated retrievals with:
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.