Shaiya Core V9 runs Windows-only binaries (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.
ps_game.exe and Game.exe), so live capture and runtime debugging must be performed on Windows — either a native Windows host or WSL2 with the server running under Windows. Wireshark provides network-layer PCAP capture, while x64dbg gives plaintext access at the exact send/recv boundary before any encryption layer.
All VAs below are relative to confirmed binaries:
ps_game.exe MD5 91b212afbe6623382713772489dc82ce and Game.exe MD5 c1edd96639ad81835624b9c4516ac781, both with ImageBase 0x00400000. Re-base addresses if you are using a different build.Confirmed Paths on WSL / Windows
| Artifact | Windows path |
|---|---|
| Server binary | C:\ShaiyaServer\PSM_Client\Bin\ps_game.exe |
| Client data | C:\ShaiyaServer\PSM_Client\Bin\Data\cn_string.DB |
| Server DLL | C:\ShaiyaServer\PSM_Client\Bin\sdev.dll |
| Server logs | C:\ShaiyaServer\PSM_Client\Bin\Log\PS_GAME__system.log__*.log |
| Session captures | C:\ShaiyaServer\ps_session_redis\captures\*.log |
C:\ with /mnt/c/.
Wireshark
Capture Filter
Set a BPF capture filter before starting capture. Replace30800 with your actual game port (check Server.ini / connect.cfg):
0xA101):
Select the correct interface
Open Wireshark. Select the network interface that carries traffic between client and server (NIC, loopback for local, or a TAP adapter).
Apply the capture filter
In the capture filter bar, enter:This limits capture to only Shaiya game traffic.
Start capture and trigger a packet
Click Start, then trigger a chat event in the game client. For guilds, send any guild message. For NPC push, trigger the relevant NPC dialog or zone script event.
Apply a display filter to find opcodes
After stopping capture, use a Wireshark display filter:This matches guild chat (
0x1104 in little-endian). For normal chat: tcp.payload[0:2] == 01:11.If the session is encrypted (XOR / AES layer), Wireshark shows ciphertext. Use x64dbg hooks at the plaintext boundary (
SConnection_Send on server, PacketPayload_Decrypt on client) instead of Wireshark for reading chat field values.Loopback Capture
If client and server run on the same host, enable loopback capture:- Install Npcap with loopback adapter support.
- In Wireshark, select Npcap Loopback Adapter as the interface.
- Apply capture filter
tcp port 30800.
x64dbg — Server (ps_game.exe)
Attaching
Attach x64dbg
Open x64dbg (32-bit). Go to File → Attach and select
ps_game.exe from the process list.Reading Packet Buffers
On every hit at0x004ED0E0 (stdcall, 32-bit calling convention):
| Stack offset | Value |
|---|---|
[ESP+4] | SConnection* pointer |
[ESP+8] | Payload buffer pointer |
[ESP+0xC] | Payload size |
Key Breakpoints for Chat Analysis
| VA | Symbol | Purpose |
|---|---|---|
0x004ED0E0 | SConnection_Send | All outbound packets — read [ESP+8] for payload |
0x004C6970 | ZoneChat_MessageResolver | Fires when a zone message is resolved; [ESP+4] = message_id |
0x00408C70 | ZoneChat_TableLoader | Fires at startup when cn_string.DB is loaded |
0x004A2210 | Script_OpcodeDispatch | Fires per script opcode tick |
0x004CB3D0 | Chat_ScriptWrapper_110A | Fires when a 0x110A builtin is invoked; watch or eax, 0xC00 @ 0x004CB402 |
Filtering by Opcode
Add a conditional breakpoint at0x004ED0E0 that only breaks for guild packets:
Capturing the char[21] Name Tail (D1)
At0x004ED0E0 with a guild packet (0x1104):
buf = [ESP+8]. Bytes at offset strlen(name)+1 through 20 are the tail. Compare against the static inference from build_pattern_b_packet.py --tail stock.
x64dbg — Client (Game.exe)
Attaching
Key Client Breakpoints
| VA | Symbol | Purpose |
|---|---|---|
0x00401080 | PacketPayload_Decrypt | Fires on inbound packet decryption — read plaintext before dispatch |
0x005F1E10 | PacketDispatcher | All S→C packet dispatch |
0x005ED060 | Send chat | Fires when player sends a chat message |
0x00420DB0 | GetMsg | Fires when client resolves a cn_string.DB message ID (e.g., after receiving 0x110A) |
0x00404610 | Crypto_PRNGFill | Fires during login PRNG fill — dump 128-byte buffer for D3 |
0x005E3D60 | Handler_Packet_A101_KeyMaterial | Fires on 0xA101 recv — cross-reference with PRNG capture for D3 |
Reading Inbound Packets at PacketPayload_Decrypt
Triggering Specific Packets
D4 — NPC Script Push (0x1109 / 0x110A)
Enter an NPC-populated zone
Travel to a zone with scripted NPC events (any zone with roaming NPCs using chat scripts).
Wait for or force a script tick
Server script dispatch fires via
Script_ExecuteTick @ 0x004A4710. Set a breakpoint at 0x004C6A80 (Chat_PacketBuilder_1109_A) and wait, or force the event through GM commands.Read the builder arguments
At
0x004C6A80, [ESP+4] = message_id passed to ZoneChat_MessageResolver @ 0x004C6970.D5 — GM Tool Notice (0xF108)
0xF108 is only sent by the GM tool binary — it is outside Game.exe stock. Triggering it requires the separate GM client binary. Capture is the same as other Pattern B packets once triggered.D3 — 0xA101 Counter (PRNG Seed)
Set breakpoints for PRNG and A101 handler
In x64dbg (32-bit) attached to
Game.exe, set both breakpoints:Log in with client
Trigger login. On hit at On hit at
0x00404610, dump the 128-byte PRNG buffer that is being filled:0x005E3D60, confirm the 0xA101 handler is reached — correlate the timing with the Wireshark capture.Capture the 0xA101 packet
Simultaneously capture the login port (30900) in Wireshark to get the full 197-byte
0xA101 plaintext.sdev.dll and Injected DLLs
sdev.dll on the server implements the Genesis Chat engine (GenesisChatEngine) using opcodes in the 0x13xx range. These are not the same as the stock wire 0x11xx opcodes — there is no automatic translation without an explicit bridge.
For the client side, custom DLL hooks in custom_chat_native_bridge affect UI/render only and do not automatically log NetworkSend. To add wire logging via a DLL, hook at:
Post-Session: Scan and Copy Logs
After a capture session, scan all logs and copy new captures into the repo:Matching Against Static Analysis Findings
Once you have a live capture, cross-reference against the static analysis documents:- Packet layouts: compare field offsets against
docs/PACKET_SPEC.mdanddocs/CHAT_CHANNEL_MAP.md. - Builder VAs: confirm that backtraces from
SConnection_Sendhit the expected builders (0x004C6A80,0x004C6F50,0x004C8310,0x004C8520). - cn_string.DB IDs: correlate script operand N with DB id N vs N+0xC00 for one known NPC line to confirm the bias constant.
- Tail bytes: compare D1 tail hex from live capture against
build_pattern_b_packet.py --tail stockoutput.