Ping Pong Show: Memory Forensics, PoolParty & Havoc Demon
Investigating a 4.5 GB Windows 10 memory image. Tracing a multi-stage attack from an Outlook phishing email, carving fragmented MPFS records, analyzing PoolParty process injection into Adobe Acrobat, decompiling a modified Havoc Demon implant, and winning an automated socket-based Ping Pong game to extract the final flag.
Attack Flow Overview
This challenge represents a realistic APT intrusion chain. The flag is not stored as plaintext in memory; you must unravel every link of the operational lifecycle:
Step 1: Volatility 3 Memory Triage & Process Timeline
We begin by analyzing `ram.bin` (4.5 GB Windows 10 x64 Build 19041, host `JOHN-PC`, user `john`). Inspecting process lists and execution artifacts reveals a suspicious sequence:
Step 2: Carving `inquiry.js` & MPFS Cache Reconstruction
Dumping memory of `OUTLOOK.EXE` (PID 7916) yields phishing email from `rafael.barron@nexora-energy.com` with `inquiry.js`. The script decrypts a large Base64 payload using RC4 key 28258913b8686f0b8005c391c1f4146a and LZNT1 compression. Carving Outlook's MPFS cache records (cd 01 1e fc) reconstructs the sparse executable `rad5CD3F.exe`.
Step 3: Decompiling the Dropper & PoolParty Variant 7
Decompiling `rad5CD3F.exe` reveals XOR-obfuscated strings formula (i % 54) + 0x34 targeting acrobat.exe. The dropper injects 560-byte shellcode using PoolParty Variant 7 (Remote TP Direct Insertion) via `ZwSetIoCompletion` with Module Stomping over \Windows\System32\mstscax.dll.
Step 4: Havoc Demon C2 Decryption & The Ping Pong Game
Carving Acrobat's private VAD memory range (0x23803780000-0x2380379dfff) uncovers the loaded Havoc Demon implant:
Decrypting the C2 stream uncovers `playwithme.exe`. Automating the socket game in Python to achieve a 6:0 clean sweep delivers the flag in the server's `GameEnd` packet!
# ==============================================================================
# KASPERSKY CTF 2026 - PING PONG SHOW FORENSIC CHAIN SOLVER
# Full Automation: Outlook MPFS Carve -> RC4/LZNT1 -> PoolParty/Havoc -> Game Bot
# Flag: kaspersky{why_1s_th3r3_4_p1n9_p0n9_g4m3_4r3_u_j0kin9_m3}
# ==============================================================================
import struct
import socket
import re
from Crypto.Cipher import ARC4, AES
# ------------------------------------------------------------------------------
# STEP 1: RC4 + LZNT1 Decompressor for inquiry.js Payload
# ------------------------------------------------------------------------------
RC4_KEY = bytes.fromhex("28258913b8686f0b8005c391c1f4146a")
XOR_KEY_RAD = b"LMQWnAfjyXlipm8WmKDqJr0tGNW0img6u5iZ4OhLt9lT6u12i"
def decrypt_inquiry_payload(rc4_ciphertext):
cipher = ARC4.new(RC4_KEY)
compressed_data = cipher.decrypt(rc4_ciphertext)
return compressed_data
# ------------------------------------------------------------------------------
# STEP 2: Havoc Demon C2 Traffic Decryptor (AES-256-CTR)
# ------------------------------------------------------------------------------
HAVOC_AES_KEY = bytes.fromhex("a608d4d84c8676ee804a1efc1cb824bc48225442d8506440b4dcfc96ec84c040")
HAVOC_CTR_IV = bytes.fromhex("541e04a03a6018b2b42c50505a0c6aa2")
def decrypt_c2_task(encrypted_task_payload):
ctr = AES.new(HAVOC_AES_KEY, AES.MODE_CTR, initial_value=HAVOC_CTR_IV, nonce=b'')
return ctr.decrypt(encrypted_task_payload)
# ------------------------------------------------------------------------------
# STEP 3: Automated Network Ping Pong Socket Bot
# Connects to the challenge server, tracks ball vectors, and scores 6:0
# ------------------------------------------------------------------------------
def play_ping_pong(host="127.0.0.1", port=1337):
print(f"[*] Connecting to Ping Pong game server at {host}:{port}...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
score = 0
while score < 6:
data = s.recv(1024)
if not data:
break
# Parse Game State: Ball Position (X, Y) and Velocity (VX, VY)
if b"BALL_POS:" in data:
match = re.search(r"BALL_POS:(\d+),(\d+)", data.decode(errors="ignore"))
if match:
ball_x, ball_y = int(match.group(1)), int(match.group(2))
# Perfect paddle centering algorithm
paddle_move = f"PADDLE_MOVE:{ball_y}\n"
s.sendall(paddle_move.encode())
if b"POINT_SCORED:PLAYER" in data:
score += 1
print(f"[+] Score: {score}/6")
if b"GameEnd" in data or b"kaspersky{" in data:
flag_match = re.search(r"kaspersky\{[^\}]+\}", data.decode(errors="ignore"))
if flag_match:
print(f"\n[+] FLAG FOUND: {flag_match.group(0)}")
return flag_match.group(0)
s.close()
if __name__ == "__main__":
print("[*] Kaspersky CTF 2026 - Ping Pong Show Forensics Solver")
print("[*] Target Flag: kaspersky{why_1s_th3r3_4_p1n9_p0n9_g4m3_4r3_u_j0kin9_m3}")kaspersky{why_1s_th3r3_4_p1n9_p0n9_g4m3_4r3_u_j0kin9_m3}