FlagCasino
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
| Port | Service | Version | Notes |
|---|---|---|---|
| <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
- Glibc_rand_simulation
- 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
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
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:
- The program reads 29 characters.
- 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.datasection at address0x4080.
- 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-reviseto fold lessons into XESXor_Methodology.md.
signed by XESXOR