Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ThalissonTMora/shaiya-chat-native-re/llms.txt

Use this file to discover all available pages before exploring further.

The corpus includes several offline Python and shell tools for validating static RE findings without requiring a live Shaiya server. Each tool maps directly to one or more confirmed findings from the binary analysis — they either reconstruct expected wire bytes, scan existing captures, or validate static hypotheses against known constraints.
All tools work fully offline. No live ps_game.exe or Game.exe instance is required. Point them at your local binary, fixture, or capture file.

Tool Categories

Crypto

tools/crypto/validate_a101_counter.pyValidates HMAC-SHA256 counter derivation for 0xA101 login packets offline, given a captured PRNG seed.

Padding

tools/padding/build_pattern_b_packet.pyConstructs Pattern B test packets (guild/trade/area/megaphone) with configurable char[21] tail fill.tools/padding/scan_pattern_b_sends.pyScans the PE binary for memset(21) before SConnection_Send to confirm/deny stack-residue tail behavior.

Wire

tools/wire/emit_session_capture.py — emits synthetic session captures from static RE findings.tools/wire/validate_d1_padding.py — validates D1 (char[21] padding) in capture logs.tools/wire/extract_plaintext_opcodes.py — scans binary blobs for chat opcodes.tools/wire/scan_capture_logs.py — scans MITM/session logs for native chat opcodes.

ZoneChat & Artifacts

tools/zonechat/parse_cn_string_db.py — parses cn_string.DB, outputs message_id → text mapping.tools/artifacts/find_missing.sh — searches server data directories for missing RE artifacts (D1–D5).

Quick-Reference Table

Tool pathPurposeKey inputsExample command
tools/crypto/validate_a101_counter.pyValidate HMAC-SHA256 counter from 0xA101--hex or --file, optional --prng-hexpython3 tools/crypto/validate_a101_counter.py --hex <hex>
tools/padding/build_pattern_b_packet.pyBuild Pattern B plaintext packet--opcode, --name, --text, --tailpython3 tools/padding/build_pattern_b_packet.py --opcode guild --name PLAYER --text hello --tail stock
tools/padding/scan_pattern_b_sends.pyScan PE for memset(21) before sendPE binary pathpython3 tools/padding/scan_pattern_b_sends.py bin/ps_game.exe
tools/wire/emit_session_capture.pyEmit synthetic session capture log--name, --text, -opython3 tools/wire/emit_session_capture.py --name JACKSON --text teste
tools/wire/validate_d1_padding.pyValidate D1 non-zero tail in capturesCapture log pathspython3 tools/wire/validate_d1_padding.py test/captures/ui_session_20260526_static.log
tools/wire/extract_plaintext_opcodes.pyFind chat opcodes in binary blobs--file or --hex, optional --opcodespython3 tools/wire/extract_plaintext_opcodes.py --file capture.bin
tools/wire/scan_capture_logs.pyScan MITM logs for 0x11xx opcodesDirectory or log file pathpython3 tools/wire/scan_capture_logs.py /path/to/captures
tools/zonechat/parse_cn_string_db.pyParse cn_string.DB to id→text pairsDB file path, --format, --limitpython3 tools/zonechat/parse_cn_string_db.py test/fixtures/cn_string_stock.db
tools/artifacts/find_missing.shFind missing RE artifacts on diskOne or more root directories./tools/artifacts/find_missing.sh /path/to/server/data

Crypto

validate_a101_counter.py

Recomputes the Game.exe recv-path AES counter material from a captured 0xA101 body. The formula is confirmed from static analysis:
prng = LCG_fill_128(seed)
digest = HMAC_SHA256(SHA256(prng), block_b[0:field_2], key=sha256(prng))
counter_src = digest[0:16]   # before dword permute @ Crypto_CounterLoad
Without the runtime PRNG seed only the layout check (field sizes vs blocks) runs.
1

Layout-only check (no PRNG)

python3 tools/crypto/validate_a101_counter.py --hex <197-byte-plaintext-hex>
2

Full counter derivation (with PRNG from breakpoint)

Set a breakpoint at Crypto_PRNGFill in Game.exe, capture the 128-byte PRNG buffer, then:
python3 tools/crypto/validate_a101_counter.py \
  --hex <197-byte-plaintext-hex> \
  --prng-hex <128-byte-prng-hex>
3

JSON output

python3 tools/crypto/validate_a101_counter.py \
  --file capture.bin --offset 0 --prng-hex <hex> --json

Padding

build_pattern_b_packet.py

Constructs Pattern B plaintext packets (guild/trade/megaphone/area) with configurable char[21] tail fill. The --tail stock mode uses 0xCC fill to approximate MSVC debug-fill / uninit stack bytes as seen in the static analysis of Chat_BroadcastGuild @ 0x00432530.
# Build a guild packet with stock (0xCC) tail
python3 tools/padding/build_pattern_b_packet.py \
  --opcode guild --name JACKSON --text "hello world" --tail stock

# Zero-fill (emulator-safe, not stock)
python3 tools/padding/build_pattern_b_packet.py \
  --opcode trade --name JACKSON --text "hello" --tail zero

# Print full packet hex
python3 tools/padding/build_pattern_b_packet.py \
  --opcode area --name JACKSON --text "hello" --tail stock --hex
Supported opcodes: guild (0x1104), trade (0x1103), megaphone (0x1108), area (0x1111), admin_guild (0xF104).

scan_pattern_b_sends.py

Scans the PE binary for memset(21) calls immediately before SConnection_Send to confirm or deny that the server zero-fills the char[21] tail. Static analysis of Chat_BroadcastGuild @ 0x00432530 confirms no such memset exists — the tail bytes are uninit stack residue.
python3 tools/padding/scan_pattern_b_sends.py bin/ps_game.exe

Wire

emit_session_capture.py

Emits a synthetic chat_capture_live.log from static RE findings when live x64dbg capture is unavailable. Packets match scan_pattern_b_sends.py + build_pattern_b_packet.py --tail stock (MSVC uninit stack approximation 0xCC). The default output path is test/captures/ui_session_20260526_static.log.
# Write to default output path
python3 tools/wire/emit_session_capture.py --name JACKSON --text teste

# Custom output
python3 tools/wire/emit_session_capture.py --name JACKSON --text teste \
  -o test/captures/my_session.log

# Also deploy to live ShaiyaServer path
python3 tools/wire/emit_session_capture.py --name JACKSON --text teste \
  --deploy /mnt/c/ShaiyaServer/PSM_Client/Bin/chat_capture_live.log
The emitted log covers: TX/RX 0x1101 normal, TX/RX 0x1102 whisper, and RX Pattern B packets for trade (0x1103), area (0x1111), and guild (0x1104).

validate_d1_padding.py

Validates D1 — the char[21] name field tail in Pattern B packets — in capture log files. Checks that the tail bytes after the NUL terminator are non-zero (stock static inference) rather than zero-filled (emulator path). Opcodes scanned: 0x1103, 0x1104, 0x1108, 0x1111, 0xF104.
# Validate the static session capture
python3 tools/wire/validate_d1_padding.py test/captures/ui_session_20260526_static.log

# Validate a live capture
python3 tools/wire/validate_d1_padding.py /mnt/c/ShaiyaServer/PSM_Client/Bin/chat_capture_live.log
Expected output when the tail is correct (stock static):
ui_session_20260526_static.log: 0x1104: OK tail=cccccccccccccccc... (N B)
D1 validation: 3 Pattern B packet(s) with non-zero tail

extract_plaintext_opcodes.py

Scans a raw binary blob or decrypted TCP payload dump for Shaiya chat-related opcodes (0x11010x110B, 0x1111, 0xA101/0xA102, 0xF10x). Useful after decrypting game traffic to plaintext, or on login socket data before XOR.
# Scan a binary capture file
python3 tools/wire/extract_plaintext_opcodes.py --file capture.bin

# Scan for specific opcodes only
python3 tools/wire/extract_plaintext_opcodes.py \
  --file capture.bin --opcodes 1104,A101,F108

# Scan from inline hex
python3 tools/wire/extract_plaintext_opcodes.py --hex 041104...
For each 0x1104 hit the tool also prints the char[21] name field and the tail bytes after the NUL terminator.

scan_capture_logs.py

Scans ShaiyaServer MITM/session logs and hex dump files for native chat opcodes. Handles both text opcode=0xXXXX markers and raw hex patterns (LE u16 0x11040411).
# Scan a directory of .log files
python3 tools/wire/scan_capture_logs.py /mnt/c/ShaiyaServer/ps_session_redis/captures

# Scan a single file
python3 tools/wire/scan_capture_logs.py test/captures/ui_session_20260526_static.log
Existing captures in ps_session_redis/captures/ cover the ps_session port (login/session, ~30900) — they contain 0xA101 but not game-channel 0x11xx opcodes. For chat opcodes you need a capture on game port 30800.

ZoneChat

parse_cn_string_db.py

Parses data/cn_string.DB into ordered (message_id, text) pairs using the exact loader semantics confirmed from ZoneChat_TableLoader @ 0x00408C70. Supports text, tsv, and json output formats.
# Default text output
python3 tools/zonechat/parse_cn_string_db.py test/fixtures/cn_string_stock.db

# TSV (message_id TAB text) — suitable for spreadsheet import
python3 tools/zonechat/parse_cn_string_db.py test/fixtures/cn_string_stock.db --format tsv

# JSON, first 20 entries
python3 tools/zonechat/parse_cn_string_db.py test/fixtures/cn_string_stock.db \
  --format json --limit 20

# Parse from a live server tree
python3 tools/zonechat/parse_cn_string_db.py /path/to/server/data/cn_string.DB --format tsv

Artifacts

find_missing.sh

Searches one or more server data directories for missing RE artifacts: cn_string.DB, sysmsg-uni.txt, and any .pcap/.pcapng files. Reports file sizes for found artifacts. See docs/MISSING_ARTIFACTS_SEARCH.md for what to capture in-game.
# Search a single server data tree
./tools/artifacts/find_missing.sh /path/to/server/data

# Search multiple roots (server + session captures)
./tools/artifacts/find_missing.sh \
  /mnt/c/ShaiyaServer/PSM_Client/Bin \
  /mnt/c/ShaiyaServer/ps_session_redis/captures
Example output when artifacts are found:
==> Searching for cn_string.DB, sysmsg-uni.txt, pcaps...
--- /mnt/c/ShaiyaServer/PSM_Client/Bin ---
FOUND: /mnt/c/ShaiyaServer/PSM_Client/Bin/Data/cn_string.DB (842 bytes)

Build docs developers (and LLMs) love