Decryptify (CTF) | TryHackMe | PART 1
PART 1: Recon and Initial Entry
Decryptify (CTF) | TryHackMe | PART 1

PART 1: Recon and Initial Entry
Scope
Target: <IP Address>
Reconnaissance mindset
Start by treating the target like a standard Linux web box. The goal here is not just to list ports, but to understand attack surface types.
A quick full port scan with service detection and default scripts is enough to map the first layer of the system.
nmap -sC -sV -T4 <IP Address>
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
1337/tcp open http Apache httpd 2.4.41 ((Ubuntu))
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Login - Decryptify
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
This revealed that ports 22 and 1337 were open
What to pay attention to
- SSH is present, but usually not the first entry point
- A non-standard HTTP port is exposed (1337), which often indicates a custom web app
- Web service versions can hint at known misconfigurations or outdated behavior
At this stage, the important takeaway is: focus on the web service first, not SSH
Web enumeration
Once a web server is identified, the next step is to map hidden content.
Use directory brute forcing to uncover:
- hidden endpoints
- backup files
- API endpoints
- admin panels
gobuster dir -u http://<IP Address>:1337/ -w <wordlist>

What you should be looking for
Rather than just collecting paths, categorize them:
- authentication-related pages (login, dashboard)
- debugging or logging endpoints
- API or JavaScript files
In this case, interesting findings include:
- a login interface
- a logs directory
- a JavaScript file exposed publicly
At this point, a key idea should form:
If logs are exposed, the application may be leaking internal state or sensitive workflow data.

JavaScript analysis
When a JS file like api.js is discovered, do not skim it.
Instead, treat it like client-side source code that may contain:
- hidden endpoints
- hardcoded secrets
- obfuscation layers

Handling obfuscated JavaScript
If the code is unreadable:
- Beautify it first
- Then identify patterns:
- arrays used as lookup tables
- wrapper functions like decoders
- numeric or hex-based indexing
A common trick is a function that maps numbers to hidden strings.
Hint for progression
Ask yourself:
What happens if I manually test the decoder function with different numeric inputs?
This often leads to hidden credentials or API keys.
Once the logic is understood, you may recover a secret used for authentication into another endpoint (in this case, /api.php).
Hidden functionality discovery
// Token generation example
function calculate_seed_value($email, $constant_value) {
$email_length = strlen($email);
$email_hex = hexdec(substr($email, 0, 8));
$seed_value = hexdec($email_length + $constant_value + $email_hex);
return $seed_value;
}
$seed_value = calculate_seed_value($email, $constant_value);
mt_srand($seed_value);
$random = mt_rand();
$invite_code = base64_encode($random);
After gaining access to a restricted API page, look for:
- code snippets
- backend logic leaks
- token generation functions
Here, the interesting part is an invite code generator.
Instead of trying to immediately break it, analyze its structure:
Key observation
The token depends on:
- email length
- part of the email string
- a constant value
- PHP’s random number generator seed
Important learning point
If a token is deterministic:
Any missing parameter becomes a reverse-engineering target.
So the challenge becomes:
- We know the input email
- We know the output token
- We are missing one variable
<?php
function calculate_seed_value($email, $constant_value) {
$email_length = strlen($email);
$email_hex = hexdec(substr($email, 0, 8));
$seed_raw = $email_length + $constant_value + $email_hex;
// same behavior as original code
$seed_value = hexdec((string)$seed_raw);
return $seed_value;
}
function generate_random_from_constant($email, $constant_value) {
$seed = calculate_seed_value($email, $constant_value);
mt_srand($seed);
return mt_rand();
}
function find_constant_value($email, $invite_code, $max_range = 1000000) {
// decode invite code
$target_random = (int) base64_decode($invite_code);
$email_length = strlen($email);
$email_hex = hexdec(substr($email, 0, 8));
for ($constant = 0; $constant <= $max_range; $constant++) {
$seed_raw = $email_length + $constant + $email_hex;
$seed = hexdec((string)$seed_raw);
mt_srand($seed);
$rand = mt_rand();
if ($rand === $target_random) {
return $constant;
}
}
return null;
}
/*
Example usage
*/
$email = "";
$invite_code = "";
$constant = find_constant_value($email, $invite_code, 1000000);
if ($constant !== null) {
echo "Found constant value: " . $constant . PHP_EOL;
} else {
echo "No constant found in range." . PHP_EOL;
}
Log analysis
Now shift attention to exposed logs.
Logs often reveal:
- real user actions
- system behavior over time
- Repeated API patterns
Here, the logs show:
- Invite codes are being generated
- account creation and deletion events
- different email usage patterns

Key insight
If multiple users go through the same process:
Their token generation likely follows the same formula with only minor variable changes.
This is your bridge to reverse engineering.
HINT: Try using the PHP script provided above.
Reverse engineering the invite system
At this stage, you already have:
- algorithm logic (from API leak)
- one known email
- One known invite code (99999)
Now the problem becomes:
Find the missing constant that makes the system reproduce the known output.
How to think about it
Instead of brute forcing immediately:
- Recreate the formula locally
- Confirm how PHP casts and converts values
- Verify randomness seed behavior
- Then attempt constrained brute force
Important hint
The mistake many people make here is ignoring type conversion issues in PHP:
- strings vs integers
- hex conversion behavior
- casting before hashing
These subtle differences often determine whether brute force works or fails.
Solving strategy
When brute forcing:
- Start with a small range first (sanity check)
- Confirm your reproduction matches the expected output
- Then scale the search space
If done correctly, the missing constant can be recovered.
Final step: token generation
Once the missing constant is identified, the rest becomes straightforward:
- plug values back into the formula
- generate the same deterministic random output
- encode it as required
At this point, you can generate valid invite codes for new emails and gain access to the next user account.

Key takeaway from Part 1
This challenge is less about exploitation and more about:
- Understanding exposed logic
- reconstructing hidden parameters
- validating assumptions through small tests
If you can reliably reverse deterministic systems like this, you are already thinking like a web attacker.
메타데이터
- post_id
- 0a1bd3faebbe
- slug
- decryptify-ctf-tryhackme-part-1-0a1bd3faebbe
- url
- https://medium.com/@azilrababe/decryptify-ctf-tryhackme-part-1-0a1bd3faebbe
- canonical_url
- https://medium.com/@azilrababe/decryptify-ctf-tryhackme-part-1-0a1bd3faebbe
- author_url
- https://medium.com/@azilrababe
- status
- ok
- fetched_at
- 2026-07-26 02:36:47