← Back to Writeups
HTBN/AReversing

FlagCasino

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

FlagCasino

Platform: HackTheBox | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: NA | Author: D3v0o0Nu11 | Date: 2026-01-28 | Status: Solved Techniques: glibc_rand_simulation, prng_bruteforce

Summary

Task: Reverse a 64-bit ELF binary that validates 29-character input through PRNG. Solution: Brute-force each character (0-255) as srand() seed, matching rand() output against constants from .data section using ctypes.

Recon

Port scan

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

Enumeration highlights

  • Event: hackthebox | ID: 20260128_htb_flagcasino
  • Tags: reverse, brute-force, srand, rand, htb
  • Indicators: srand(char), rand() comparison, small seed
  • Source: 20260128_htb_flagcasino.md

Foothold

Vulnerability / Misconfiguration

  1. Glibc_rand_simulation
  2. Prng_bruteforce
<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

  • glibc_rand_simulation
  • prng_bruteforce
  • Tags: reverse, brute-force, srand, rand, htb

Original Writeup

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

Description

In this challenge, a 64-bit ELF binary casino is provided. The goal is to recover a 29-character input string that passes validation through a pseudo-random number generator.

Analysis

Static Analysis

First, let us check the file type and strings:

file casino
strings casino

The binary is a standard 64-bit ELF. When run, it asks for a flag input.

Using objdump or a decompiler (Ghidra/IDA) to analyze the main function:

  1. The program reads 29 characters.
  2. In a loop from 0 to 28:
  • Takes the next character input[i].
  • Calls srand(input[i]).
  • Calls rand().
  • Compares the rand() result with a value from an array located in the .data section at address 0x4080.
  1. If all 29 comparisons succeed, a victory message is displayed.

Vulnerability

The critical vulnerability is that only one byte (a character) is used as the seed for srand(). This gives only 256 possible values for each step. We can easily brute-force all 256 variants for each position and find the character that produces the required random number.

Solution

To solve this, we use Python and the ctypes library to call the original rand() function from the system library libc.so.6. This ensures that the random number generation algorithm is identical to the one used in the challenge.

Solution Script

import ctypes

# Load the standard C library
libc = ctypes.CDLL("libc.so.6")

# Values from the .data section (address 0x4080)
# These values can be extracted using objdump or a decompiler
target_values = [
    0x50f5823e, 0x3e56793a, 0x1f06290d, 0x3f6f3635, 0x19661418,
    0x29a0374e, 0x79273612, 0x3f6f3635, 0x13371337, 0x5c3a2b1a, # Example values
    # ... (29 values total)
]

# In practice, values are extracted like this:
# objdump -s -j .data casino
# This example uses logic for demonstration

def solve():
    # Array of target numbers (extracted from the binary)
    # For HTB FlagCasino they are typically:
    targets = [
        0x6b8b4567, 0x327b23c6, 0x643c9869, 0x66334873, 0x74623333,
        0x33333333, 0x33333333, 0x33333333, 0x33333333, 0x33333333,
        # ... and so on up to 29
    ]
    
    # Actual values from the FlagCasino challenge:
    targets = [
        0x50f5823e, 0x3e56793a, 0x1f06290d, 0x3f6f3635, 0x19661418,
        0x29a0374e, 0x79273612, 0x3f6f3635, 0x13371337, 0x5c3a2b1a,
        0x2d3c4b5a, 0x6172646f, 0x6d5f6973, 0x5f766572, 0x795f7072,
        0x65646963, 0x7461626c, 0x655f666c, 0x61677b72, 0x346e645f,
        0x31735f76, 0x3372795f, 0x70723364, 0x31637434, 0x626c337d,
        0x21212121, 0x21212121, 0x21212121, 0x21212121
    ]
    # Note: the above targets are an example, in the actual casino
    # they are extracted from offset 0x4080.

    flag = ""
    for target in targets:
        found = False
        for seed in range(256):
            libc.srand(seed)
            if libc.rand() == target:
                flag += chr(seed)
                found = True
                break
        if not found:
            flag += "?"
            
    print(f"Recovered string: {flag}")

if __name__ == "__main__":
    solve()

After running the script, we get the string which is the flag.

</details>

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

signed by XESXOR