← Back to Writeups
HTBN/AReversing

Dog Simulator

XESXOR8/23/20264 min read
#reversing#htb#n/a

Dog Simulator

Platform: Broncoctf2026 | Category: Reversing | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2026-07-11 | Status: Solved Techniques: fnv1a_preimage_z3, macho_arm64_reversing, state_machine_recovery, string_analysis

Summary

Task: stripped ARM64 Mach-O 'Dog Simulator' game requiring a correct 6-day action routine. Solution: reverse the state machine, recover the fixed action order plus two Speak commands — a 12-letter FNV-1a preimage of 0x9f58d866 (via Z3) and the owner-name 'gremlin' from day-6 dialogue.

Recon

Port scan

nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: broncoctf2026 | ID: 20260711_broncoctf2026_dog_simulator
  • Tags: state_machine, fnv1a, arm64, stripped_binary, macho, hash_preimage
  • Indicators: stripped ARM64 Mach-O game/simulator, fixed routine in the right order, FNV-1a offset 0x811c9dc5 prime 0x01000193, wrong length' failure message, owner-name echoed in dialogue
  • Source: 20260711_broncoctf2026_dog_simulator.md

Foothold

Vulnerability / Misconfiguration

  1. Fnv1a_preimage_z3
  2. Macho_arm64_reversing
  3. State_machine_recovery
  4. String_analysis
<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

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • fnv1a_preimage_z3
  • macho_arm64_reversing
  • state_machine_recovery
  • string_analysis
  • Tags: state_machine, fnv1a, arm64, stripped_binary, macho, hash_preimage

Original Writeup

<details><summary>Click to expand original content</summary>

Description

If you can survive 6 dog-days of walkies, tricks, and zoomies, you might uncover a secret (if you can stick to the right routine in the right order)!

A "Dog Simulator" game binary (stripped ARM64 Mach-O, PIE, dynamically linked to libSystem). Over 6 days you choose menu actions. State (Score, Bond, Energy, Mood) is tracked, and at the finale the owner either prints a garbled failure message or reveals the flag if the correct routine was followed in the correct order. Goal: recover the exact six-day routine.

Analysis

The whole program logic lives in a single stripped function (0x100000500). Actions deterministically update Score, Bond, Energy, and Mood (calm/hyped/overstimulated/sleepy), and advance a four-stage combo counter. The finale gates the flag on all of the following:

  • exactly one Bark, one Fetch, one Sit, one Eat; zero Zoomies; two Speak actions
  • final Score == 55, Bond > 24, Energy > 20, Mood != overstimulated
  • combo state reaches 4 (right actions in the right order)
  • total alphabetic Speak letters == 19
  • two FNV-1a hash constants must match (combo hash + transcript hash)

Speak normalizes input to lowercase alphabetic and hashes it with FNV-1a (offset basis 0x811c9dc5, prime 0x01000193):

  • The first Speak (at combo state 3) must hash to 0x9f58d866. Any 12-letter lowercase preimage works — this explains the "the words feel the wrong length" failure when a baseline (e.g. six barks) is used: the spoken letters never reach the expected total length of 19.
  • The second Speak must normalize exactly to gremlin — the name the owner calls the dog in the day-6 line "Last day of the week, little gremlin." This triggers "(He seems to fixate on what your owner called you.)" and adds the final 7 letters (12 + 7 = 19).

Key finale strings recovered:

  • Owner: awww he said "%s" — success path prints the flag
  • Owner: he tried to say it, but it came out garbled.
  • Owner: the routine felt right, but the timing was off.
  • Owner: he keeps trying to say something... but the words feel the wrong length.
  • (Good boy! combo completed!)

Solution

The correct six-day routine (menu sequence 2,3,1,6,4,6):

  1. Fetch
  2. Sit
  3. Bark
  4. Speak: naxxzpxhhzgk (12-letter FNV-1a preimage of 0x9f58d866)
  5. Eat
  6. Speak: gremlin (owner-name from day-6 dialogue)

Recover the 12-letter preimage with Z3:

#!/usr/bin/env python3
from z3 import *
c = [BitVec(f'c{i}', 32) for i in range(12)]
s = Solver()
for x in c:
    s.add(x >= ord('a'), x <= ord('z'))
h = BitVecVal(0x811c9dc5, 32)          # FNV-1a offset basis
for x in c:
    h = (h ^ x) * 0x01000193           # FNV-1a prime
s.add(h == 0x9f58d866)                 # target combo hash
print(s.check())
m = s.model()
print(''.join(chr(m[x].as_long()) for x in c))   # -> naxxzpxhhzgk

Drive the binary (press Enter to begin, then feed choices/commands):

printf '\n2\n3\n1\n6\nnaxxzpxhhzgk\n4\n6\ngremlin\n' | ./dog-sim-mac

Final state on success: Score=55 Bond=30 Energy=36 Mood=calm, Speak total letters 19, and the finale prints:

Owner: awww he said "bronco{REDACTED}"
</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR