rENTAS CTF
Our team, Roti Canai, participated rENTAS CTF 2024 and made it to the final round to compete with other 30 teams from different universities at UNITEN. Shout out to my teammates @leon and @covy. This is our writeup for qualifying round and final round.
RE/Resign Letter
Challenge Description:
Solution:
In this challenge, we were provided with a Word document. We used olevba
, a tool commonly used for examining Microsoft Office documents for malicious content. It helps in extracting and analyzing macros embedded in the file.
We discovered an embedded GitHub link and it led us to a repository containing a file named lenovo.exe
. We downloaded this executable file and used strings
command to analyze the file.
Among the extracted strings, we discovered a base64 encoded string. After decoding, it revealed the flag.
Flag:
RWSC{p@ss123}
TI/Скорпион
Challenge Description:
We were provided with a text file containing filenames of malicious executables along with their hashes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Table 2: Malicious Executables Affiliated with xxxxxxx Infections
conhost.exe
6633fa85bb234a75927b23417313e51a4c155e12f71da3959e168851a600b010
A ransomware binary.
psexec.exe
078163d5c16f64caa5a14784323fd51451b8c831c73396b967b4e35e6879937b
A file used to execute a process on a remote or local host.
S_0.bat
1c4978cd5d750a2985da9b58db137fc74d28422f1e087fd77642faa7efe7b597
A batch script likely used to place 1.ps1 on victim systems for ransomware staging purposes [T1059.003].
1.ps1
4e34b9442f825a16d7f6557193426ae7a18899ed46d3b896f6e4357367276183
Identifies an extension block list of files to encrypt and not encrypt.
S_1.bat
97766464d0f2f91b82b557ac656ab82e15cae7896b1d8c98632ca53c15cf06c4
A batch script that copies conhost.exe (the encryption binary) on an imported list of host names within the C:\Windows\Temp directory of each system.
S_2.bat
918784e25bd24192ce4e999538be96898558660659e3c624a5f27857784cd7e1
Executes conhost.exe on compromised victim systems, which encrypts and appends the extension of .groupname(sensored) across the environment.
Solution:
We performed an online search using one of the hashes and confirmed that the hash belonged to Rhysida Ransomware
. Next, we searched through various platforms to gather more information about Rhysida Ransomware. During our search, we found a crucial clue on a Telegram channel. The clue indicated that the challenge creators preferred using mirrors
over direct domains.
From the clue, we needed to understand what type of mirror was being referenced. The term mirror
in the context of hacktivists and ransomware typically refers to websites hosted on the dark web, which often use the .onion
domain suffix. The mention of mirror not .domain
suggested that we should look for a non-standard top-level domain, which reinforced the idea that it could be a .onion
address.
We proceeded to search for mirrors related to Rhysida Ransomware. Our top search result led us to a Twitter post mentioning Rhysida Ransomware.
The Twitter post contained an .onion
domain. According to the clue, the content before the .onion
domain in the post constituted the flag
Flag:
RWSC{rhysidafc6lm7qa2mkiukbezh7zuth3i4wof4mh2audkymscjm6yegad}
Crypto/round and round
Challenge Description:
In this challenge, we were provided with an encoded message:
1
2126226{19122929121712_6121911821_26422_842928}
Solution:
The challenge description reveals the cipher name: Pizzini Cipher
.
We used the Pizzini Cipher decoder tool at this link
Flag:
RWSC{PIZZINI_CIPHER_WAS_EAZY}
Web/Build Your Own Script
Challenge Description:
We were presented with a website that generates random directories represented by emojis. Each directory contained sub-directories, and the path ends with an index.php page. Upon browsing the website, we observed the following:
- The website generates directories represented by emojis.
- These directories contain sub-directories, leading to more sub-directories.
- Each path ends with an index.php page.
- Random inspirational quotes are displayed as we navigate through different directories.
Solution:
Our first attempt involved checking each directory for the flag. However, this approach faced issues due to the dynamic generation of new directories. After that, we realized it performed a check on the pages for the text "No directories found."
This suggested that a unique directory would not contain this text.
We wrote a Python script using the requests
library to fetch directory contents and the BeautifulSoup
library to parse the HTML.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
def fetch_directory_contents(url):
try:
response = requests.get(url)
response.raise_for_status() # Raise exception for HTTP errors
return response.text
except requests.RequestException as e:
print(f"Error fetching {url}: {e}")
return None
def find_unique_directory(base_url):
directories_to_check = [base_url]
unique_directory = None
while directories_to_check:
current_url = directories_to_check.pop()
content = fetch_directory_contents(current_url)
if content:
soup = BeautifulSoup(content, 'html.parser')
directory_links = soup.find_all('a', class_='directory-link')
no_dir_text = soup.find(string="No directories found.")
if directory_links:
for link in directory_links:
link_url = urljoin(current_url, link['href'])
directories_to_check.append(link_url)
elif not no_dir_text: # Check for existence of directory content
unique_directory = current_url
break
return unique_directory
if __name__ == "__main__":
base_url = "https://byos.ctf.rawsec.com/root/index.php"
unique_dir = find_unique_directory(base_url)
if unique_dir:
print(f"Unique directory found: {unique_dir}")
else:
print("No unique directory found.")
The script recursively traverses directories until it finds a unique directory. It will traverse all possible directory paths on the provided URL https://byos.ctf.rawsec.com/root/index.php
.
We navigated to the unique directory URL provided by the script. The page contained the flag:
Flag:
RWSC{J4CKP0T}
Web/Simplelazy
Challenge Description: We encountered a website with three clickable links, each leading to different result.
Solution:
https://simplelazy.ctf.rawsec.com/index.php?page=page1https://simplelazy.ctf.rawsec.com/index.php?page=page1
This is the link when we click each “link” at the page. Immediately we are thinking about LFI vulnerability.
We tested the page
parameter by attempting to access the /etc/passwd
file.
https://simplelazy.ctf.rawsec.com/index.php?page=../../../../../../../../../../../etc/passwd
We tried to grab the /etc/passwd directory but not successful, it shows /etc/passwd.php not found.
Warning: include(../../../../../../../../../../../etc/passwd.php): Failed to open stream: No such file or directory in /var/www/html/index.php on line 72
Next, we attempted to bypass the .php extension by using a null byte (%00)
, which in some cases can terminate the string early:
https://simplelazy.ctf.rawsec.com/index.php?page=../../../../../../../../../../../etc/passwd%00
Warning: include(): Failed opening ‘../../../../../../../../../../../etc/passwd’ for inclusion (include_path=’.:/usr/local/lib/php’) in /var/www/html/index.php on line 72
This indicated the null byte was processed, but the file still couldn’t be accessed.
We then considered using PHP wrappers to manipulate the file inclusion.
https://simplelazy.ctf.rawsec.com/index.php?page=php://filter/convert.base64-encode/resource=index
This successfully returned the base64-encoded content, and we decoded it using CyberChef.
After some further inspections, we used the same PHP wrapper method to retrieve the base64-encoded content of page3
https://simplelazy.ctf.rawsec.com/index.php?page=php://filter/convert.base64-encode/resource=page3
We got a base64 and decoding the base64 content of page3 revealed additional information.
We tried to put "esdasxasdcessxsadx"
to the payload:
https://simplelazy.ctf.rawsec.com/index.php?page=php://filter/convert.base64-encode/resource=esdasxasdcessxsadx
Finally, this payload successfully retrieved the flag.
Flag:
RWSC{S1MPL3_4ND_L4ZY}
OSINT/Cali Cartel
Solution:
The key hint provided was the word "downfall"
. We started to search for the downfall of Cali Cartel
. There are several results, including a Wikipedia page and an article from The Seattle Times.
The Wikipedia page provided general information but no specific leads for our challenge. However, the article from The Seattle Times caught our attention. The article discussed the downfall of the Cali Cartel and a name stood out quite clearly: Jorge Salcedo
So we tried the name paired with Google Dorking to increase the effectiveness. Ta-da! The flag is just right there.
Flag:
RWSC{C4L1_C4RT3L_PWN3D}
OSINT/Medellín Cartel
Solution:
We can’t really solve this challenge without the hint:
The hint indicated that the flag was hidden within the metadata of an Instagram Account. We started by navigating to the UNITEN official Instagram account. The goal was to identify the specific follower mentioned in the hint. By reviewing the followers list of the UNITEN official Instagram account, we located the mentioned person from the hint.
The account had only one post and we needed to examine this post’s metadata.
To inspect the metadata, we viewed the source code of the Instagram post and search for flag pattern.
Flag:
RWSC{Bl4cky_S1c4r1o}
Steganography/Zombeify
Solution:
The initial step was to determine the content of the provided file. After several attempts, we used Base32
and Render Image
to reveal an image.
After saving the image, we conducted online searches related to Zombieland Saga
, but these searches did not found any useful results. However, the we are provided with additional hints.
- Mp3 got hex
- Hex ascii
- https://github.com/CleasbyCode/jdvrif
- https://github.com/danielcardeenas/AudioStego
We open the first GitHub repository (jdvrif) and found that it provide online tool to convert the image into an MP3 file
Next, we used the second GitHub repository (AudioStego) to extract hexadecimal ASCII data from the MP3 file
With the extracted hexadecimal ASCII data, we proceeded to decode it into readable text.
Flag:
RWSC{kur0n3kO}
Networking/Last Hope
Challenge Dsescription:
In this challenge, we are given a network traffic capture file, asking us to find the Wi-Fi password.
Solution:
Given the nature of the challenge, our first instinct was to use aircrack-ng, a popular tool for cracking Wi-Fi passwords. We decided to use the rockyou.txt wordlist as our dictionary for the brute-force attack.
It only took a few seconds for aircrack-ng to process the capture file and find the password. The tool displayed the password “anonymous” as the result.
Flag:
RWSC{anonymous}
DFIR/Mobile
Solution:
For this challenge it took some time reading the report, with different mistakes made. At first the images with keypads was the primary suspect but then we saw it was going in order, so it was quickly ruled out. Next was some carved audio artifacts since the hint that provided the youtube video that was using a hash to compare with a list to get the password. It was a bit too far, so a little googling for gesture.key’s location shows this:
So we had to look for /data/system folder in the pdf, and searching the string /data/system gave us this:
Voilà! From here there were no hashes given but a _rawData was provided in BOLD too, so to find ways to decrypt raw data
Running it on kali we get this:
The Pattern is the flag
Flag:
RWSC{875463120}
Network/I Hope You Have The Software
Solution:
We opened the provided pkt file using Cisco Packet Tracer. Clicked on Server-PT 18 to open its properties.
Navigated to the “Services” tab. Within the Services tab, select “HTTP” to view the HTTP service hosted by the server. Clicked on the “Edit” button to view the HTML content being served.
We found the flag within the HTML content.
Flag:
RWSC{!t5a_t4c3r_f!l3:D}
Web/Anti-Brute
Solution:
We used BurpSuite to capture the request during a login attempt. As the challenge provided with a password wordlist, we decided to bruce force the password. We sent the request to intruder and ensure the username is admin
. Besides, we marked the value of the password parameter as a variable for the payload.
We navigated to the payload tab and paste the password list inside the payload settings.
We added Invalid
as a keyword in the Grep-Match function to ensure that unsuccessful login attempts could be filtered out.
Next, we can start the brute force attack. After the bruce force completed, we can filter the results by the Invalid
keyword and the length from the smallest to the largest to identify the response where the login was successful.
We found the successful login response where the password was secretpass
. The flag was included in the response body of the successful login.
Flag: RWSC{n0_brut3f0rc3_pl34s3}