name: mapleshark-sniff description: Parse and analyze MapleShark2 .msb sniff files for MapleStory2 packet reverse engineering. Use when the user wants to understand packet structures, debug network traffic, or implement new packet handlers.
MapleShark Sniff Analyzer
Setup (first time only)
cd tools/mapleshark && npm install
The MSB file to analyze: $ARGUMENTS
Before you start — ask these questions if not already answered
Direction — are we looking at packets the client sends, the server sends, or both?
OUT= client → server (RecvOp) — what the client is doingIN= server → client (SendOp) — what the server is responding with- Knowing this upfront avoids wasting queries on the wrong half of the traffic, and the same opcode number means a completely different thing in each direction.
Server version — GMS2 or KMS2? The file's locale byte is often
0(Unknown) for older sniffs, so the opcode table won't auto-detect. If the user is on KMS2, pass--locale kms2to every command.
Workflow — always follow this order
Never fetch all packets at once. Use targeted commands and build up context incrementally.
Step 1 — Get an overview (always start here)
node tools/mapleshark/parse-msb.js $ARGUMENTS --summary
# If KMS2: add --locale kms2
node tools/mapleshark/parse-msb.js $ARGUMENTS --summary --locale kms2
This returns an opcode frequency table with no hex data — cheap on tokens. Use it to understand what's in the file and decide where to focus.
Step 2 — Drill into specific opcodes
# By name
node tools/mapleshark/parse-msb.js $ARGUMENTS --opcode Skill --limit 5
# By hex opcode
node tools/mapleshark/parse-msb.js $ARGUMENTS --opcode 0x0020 --limit 10
# Multiple opcodes at once
node tools/mapleshark/parse-msb.js $ARGUMENTS --opcode Skill --opcode UserEnv --limit 5
# Only server→client packets
node tools/mapleshark/parse-msb.js $ARGUMENTS --opcode 0x00AA --direction IN --limit 5
Step 3 — Inspect a specific packet in full
# By index (from step 2 output)
node tools/mapleshark/parse-msb.js $ARGUMENTS --index 42 --hex-limit 512
# A range of consecutive packets
node tools/mapleshark/parse-msb.js $ARGUMENTS --range 40-50 --no-hex
Step 4 — Track a known value across the sniff
# Find all packets referencing a specific integer (e.g. objectId, itemId)
# Value must be little-endian — e.g. 1000 decimal = E8 03 00 00
node tools/mapleshark/parse-msb.js $ARGUMENTS --search-hex "E8 03 00 00" --summary
Step 5 — Find which sniff files contain a value (folder search)
Use this when you don't know which file to look at. Pass a folder instead of a file — the same filters apply.
# Find all sniffs containing a specific hex value
node tools/mapleshark/parse-msb.js <folder-path> --search-hex "F6 F3 5E 01" --no-hex
# Find all sniffs containing a specific opcode
node tools/mapleshark/parse-msb.js <folder-path> --opcode FieldAddNpc --no-hex --limit 3
Results are grouped by file. Use filesWithMatches to narrow down which files to drill into with Steps 2–4.
Codebase cross-reference
- OUT packets (client→server) →
Maple2.Server.Game/PacketHandlers/{Name}Handler.cs - IN packets (server→client) →
Maple2.Server.Game/Packets/{Name}Packet.cs - Enums:
Maple2.Server.Core/Constants/RecvOp.cs(OUT) andSendOp.cs(IN)
When you identify an opcode, search the codebase:
# Find the handler or packet builder
# e.g. for Skill (RecvOp): look for SkillHandler.cs
# e.g. for a SendOp: look for the matching Packet.cs
Packet format reference
Direction convention
- OUT = client → server (
outbound: true) → maps toRecvOp - IN = server → client (
outbound: false) → maps toSendOp
Data types (little-endian)
| Type | Size | Notes |
|---|---|---|
| Byte | 1 | |
| Bool | 1 | 0x00 = false |
| Short | 2 | |
| Int | 4 | 27 00 00 00 = 39 |
| Long | 8 | |
| Float | 4 | IEEE 754 |
| String | 2+n | [len: short][chars: 2 bytes each] for Unicode |
Common patterns
Mode byte — many packets have a sub-type byte after the opcode:
[OPCODE 2b] [MODE 1b] [payload...]
Arrays — always length-prefixed:
[count: int] [element] × count
Converting values for --search-hex
To search for a 32-bit int in little-endian, always use Node.js for 100% accuracy:
# Convert decimal to little-endian hex
node -e "const buf = Buffer.alloc(4); buf.writeUInt32LE(23000054); console.log(buf.toString('hex').toUpperCase())"
# Output: F6F35E01
# Convert little-endian hex back to decimal
node -e "const buf = Buffer.from('F6F35E01', 'hex'); console.log(buf.readUInt32LE(0))"
# Output: 23000054
Then use in command:
node tools/mapleshark/parse-msb.js $ARGUMENTS --search-hex "F6 F3 5E 01"
Common conversions (for reference):
1000decimal →E8 03 00 00256decimal →00 01 00 00
Don't calculate manually—Node.js eliminates conversion errors.
Packet Resolver (for unknown SendOp)
For server→client packets that are missing or broken, use the in-game resolver:
resolve <opcode>
The client will report what field is expected next. Results saved to ./PacketStructures/.