APKey
APKey
Platform: HackTheBox | Category: Mobile | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2026-02-03 | Status: Solved Techniques: aes_ecb_decryption, apk_decompilation, code_deobfuscation, string_reconstruction
Summary
Android reverse engineering challenge involving an APK file with obfuscated code protecting a flag. The application implements a login screen with hardcoded credentials, and upon successful authentication, decrypts and displays the flag.
Recon
Port scan
nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
HackTheBox| ID:20260203_hackthebox_apkey - Tags: reverse_engineering, java, deobfuscation, android, apk, aes
- Indicators: APK file, obfuscated class names (single letters), AES encryption, Base64 encoded data, array index lookups for string building
- Source:
20260203_hackthebox_apkey.md
Foothold
Vulnerability / Misconfiguration
- Aes_ecb_decryption
- Apk_decompilation
- Code_deobfuscation
- String_reconstruction
<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
sudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- aes_ecb_decryption
- apk_decompilation
- code_deobfuscation
- string_reconstruction
- Tags: reverse_engineering, java, deobfuscation, android, apk, aes
Original Writeup
<details><summary>Click to expand original content</summary>Description
Android reverse engineering challenge involving an APK file with obfuscated code protecting a flag. The application implements a login screen with hardcoded credentials, and upon successful authentication, decrypts and displays the flag.
Analysis
Initial Reconnaissance
- Extracted APK (password: hackthebox)
- Standard Android application package
- Contains obfuscated Java code
- Decompiled with jadx to obtain Java source:
- Main logic in
com.example.apkey.MainActivity - Obfuscated helper classes in
c.b.a.*package (single-letter class names)
Authentication Flow
The MainActivity implements a simple authentication check:
- Username must equal "admin"
- Password MD5 hash must equal
a2a3d412e92d896134d9c9126d756f - On success, calls
c.b.a.g.a()to get encrypted data andc.b.a.b.a()to decrypt
Obfuscation Pattern
The obfuscation uses multiple helper classes, each returning a string from an array at a specific index:
| Class | Method | Returns | Array Index |
|---|---|---|---|
h | a() | "kHtZuV" | 6 |
i | a() | "rSE6qY" | 4 |
f | a() | "6HxWkw" | 1 |
e | a() | "HyeaX9" | 7 |
c | a() | "FlEGyL" | 4 |
d | a() | "wAxcoc" | 0 |
a | a() | "85S94kFpV1" | 3 |
Key Functions
g.a()- Builds Base64-encoded encrypted string by concatenating values from multiple arraysg.b()- Returns "AES" (cipher algorithm) built fromd.a()[1] + i.a()[2] + i.a()[1]b.a()- Decrypts using AES-ECB with key built from character positions across helper functions
Reconstructed Values
Encrypted string (Base64):
1UlBm2kHtZuVrSE6qY6HxWkwHyeaX92DabnRFlEGyLWod2bkwAxcoc85S94kFpV1
AES Key (16 bytes):
kV9qhuzZkvvrgW6F
Key construction uses specific character positions from helper functions with some lowercase transformations.
Solution
#!/usr/bin/env python3
"""
APKey - HackTheBox Mobile Challenge
Android APK reverse engineering with AES decryption
"""
import base64
from Crypto.Cipher import AES
# Helper functions returning values from obfuscated arrays
def h_a(): return "kHtZuV" # arrayList.get(6)
def i_a(): return "rSE6qY" # arrayList.get(4)
def f_a(): return "6HxWkw" # arrayList.get(1)
def e_a(): return "HyeaX9" # arrayList.get(7)
def c_a(): return "FlEGyL" # arrayList.get(4)
def d_a(): return "wAxcoc" # arrayList.get(0)
def a_a(): return "85S94kFpV1" # arrayList.get(3)
# g.a() - builds the encrypted string from multiple array lookups
def g_a():
sb = ""
sb += "1UlBm2" # arrayList[8]
sb += h_a() # kHtZuV
sb += i_a() # rSE6qY
sb += f_a() # 6HxWkw
sb += e_a() # HyeaX9
sb += "2DabnR" # arrayList2[9]
sb += c_a() # FlEGyL
sb += "Wod2bk" # arrayList3[5]
sb += d_a() # wAxcoc
sb += a_a() # 85S94kFpV1
return sb
# Build AES key from character positions across helper functions
# Each character is extracted from specific index with optional .lower()
key = (
h_a()[0] + # k
a_a()[8] + # V
e_a()[5] + # 9
i_a()[4] + # q
h_a()[1].lower() + # h -> h
h_a()[4] + # u
h_a()[3].lower() + # z -> z
h_a()[3] + # Z
h_a()[0] + # k
a_a()[8].lower() + # V -> v
a_a()[8].lower() + # V -> v
i_a()[0] + # r
c_a()[3].lower() + # G -> g
f_a()[3] + # W
f_a()[0] + # 6
c_a()[0] # F
)
# key = "kV9qhuzZkvvrgW6F"
# Get encrypted data and decrypt
encrypted_b64 = g_a()
print(f"Encrypted (Base64): {encrypted_b64}")
print(f"AES Key: {key}")
# Decrypt using AES-ECB
cipher = AES.new(key.encode(), AES.MODE_ECB)
decrypted = cipher.decrypt(base64.b64decode(encrypted_b64))
flag = decrypted.decode('utf-8').rstrip('\x00').rstrip()
print(f"Flag: {flag}")
Lessons Learned
- jadx is essential for Android reverse engineering - produces readable Java from DEX
- Obfuscation through array indirection is common but easily reversible
- Trace all helper function calls to reconstruct the full logic
- AES-ECB mode is weak but still used in CTF challenges
- Character-by-character key construction is a common obfuscation pattern
References
</details>Auto-tracked: saved to WriteUps; run
/xesor-reviseto fold lessons into XESXor_Methodology.md.
signed by XESXOR