$ cat writeup.md…
$ cat writeup.md…
HackTheBox
Unity IL2CPP Mario-like 2D platformer game. The goal is to find the hidden flag by analyzing game assets.
Within the enigmatic corridors of StayInTheBoxCorp, a company operating on a shoestring budget at the frontier of digital innovation, an challenge awaits. Only those who can dance on the edge of shadows shall pierce the veil of the unhackable.
Unity IL2CPP Mario-like 2D platformer game. The goal is to find the hidden flag by analyzing game assets.
GameAssembly.dll (14MB) + global-metadata.dat in il2cpp_data/Metadata/StayInTheBoxCorp_project.dll with XOR-encoded debugger names (key: 0x37)Using UnityPy to extract Texture2D assets revealed ~80 textures:
The randomly-named textures were individual green letter/number sprites forming the flag:
| Texture | Character |
|---|---|
ewfg | HTB{ |
htrh | 0 |
f202 | v |
g09 | 3 |
gi3 | r |
gmoe | c |
09t | 0 |
f4g2 | m |
rgeh4 | 1 |
f221 | n |
l32 | g |
gh9 | W |
g3 | 3 |
g3 | 4 |
pi8o | k |
32g3 | U |
04g | s |
qwq | e |
gi3 | r |
4ge | M |
09t | 0 |
gj9 | d |
qwq | e |
gej4 | _ (bar) |
g3 | 4 |
f221 | n |
5235 | t |
rgeh4 | 1 |
hre | C |
h43 | h |
g09 | 3 |
g3 | 4 |
5235 | t |
90f2g | } |
The flag characters were placed far outside the playable game area:
Sorting sprites by X coordinate and analyzing gaps:
gej4) placed between word groupsStayInTheBoxCorp_project.dll contained:
A, DB, GH, RG, TDIsDebuggerPresent API import7777777777777777#!/usr/bin/env python3 import UnityPy import os env = UnityPy.load("gamepwn_stayintheboxcorp/StayInTheBoxCorp_1_Data") os.makedirs("extracted", exist_ok=True) for obj in env.objects: if obj.type.name == "Texture2D": data = obj.read() img = data.image img.save(f"extracted/{data.m_Name}.png") print(f"Extracted: {data.m_Name}.png ({img.width}x{img.height})")
#!/usr/bin/env python3 import UnityPy env = UnityPy.load("gamepwn_stayintheboxcorp/StayInTheBoxCorp_1_Data") sprites_with_pos = [] for obj in env.objects: if obj.type.name == 'SpriteRenderer': data = obj.read() try: sprite = data.m_Sprite.read() go = data.m_GameObject.read() # Get Transform component for position for comp_ptr in go.m_Components: comp = comp_ptr.read() if hasattr(comp, 'm_LocalPosition'): pos = comp.m_LocalPosition sprites_with_pos.append({ 'name': sprite.m_Name, 'x': pos.x, 'y': pos.y }) break except: continue # Sort by X coordinate sprites_with_pos.sort(key=lambda s: s['x']) # Print sorted sprites for s in sprites_with_pos: print(f"X={s['x']:.2f} Y={s['y']:.2f} → {s['name']}")
#!/usr/bin/env python3 # After sorting by X coordinate and mapping texture names to characters: char_map = { 'ewfg': 'HTB{', 'htrh': '0', 'f202': 'v', 'g09': '3', 'gi3': 'r', 'gmoe': 'c', '09t': '0', 'f4g2': 'm', 'rgeh4': '1', 'f221': 'n', 'l32': 'g', 'gh9': 'W', 'g3': '34', 'pi8o': 'k', '32g3': 'U', '04g': 's', 'qwq': 'e', '4ge': 'M', 'gj9': 'd', 'gej4': '_', '5235': 't', 'hre': 'C', 'h43': 'h', '90f2g': '}' } # Sorted positions reveal: HTB{0v3rcom1ng_W34k_UserM0de_4nt1Ch34t}
Decoded from leetspeak: "overcoming Weak UserMode antiCheat"
This perfectly fits the challenge theme — user-mode anti-cheat (like the native plugin's IsDebuggerPresent) is notoriously weak compared to kernel-mode anti-cheat solutions.
$ cat /etc/motd
Liked this one?
Pro unlocks every writeup, every flag, and API access. $9/mo.
$ cat pricing.md$ grep --similar