This document contains the protocol header specifications for the BNCS, Realm, D2GS, BNLS, W3GS, and Storm UDP protocols.
BNCS stands for Battle.Net Chat Server and is the protocol that Blizzard's Battle.net enabled games use to communicate. Every BNCS message has the same header:
(UINT8) Always 0xFF (UINT8) Message ID (UINT16) Message length, including this header (VOID) Message Data
The BNCS protocol is aggressively enforced by Battle.net - at least, for clients - and violations of the protocol generally result in an IP ban.
When connecting to a BNCS server, you must first tell the server which protocol you wish to use by sending a protocol ID byte before any packets. Some of the protocol IDs are:
0x01(see Logon Sequences for the logon sequences)
0x02(see BNFTPv1 or BNFTPv2 for the protocols)
- Telnet (Chat):
0x63(see Telnet Protocol for the protocol) DEFUNCT
Other Battle.net protocol IDs are MCP to BNCS communication (
0x04). There is also the
0x81 protocols, which we know almost nothing about. At a guess,
0x06 is used for interserver synchronization (see this thread).
Battle.net's Realm Servers are what control Diablo II's realms. Realm (sometimes referred to as MCP) message headers are
also always the same, albeit slightly different from BNCS's:
(UINT16) Message length, including this header (UINT8) Message ID (VOID) Message Data
Violations of the MCP protocol are less severely enforced by MCP servers. If they IP ban at all, it is generally only for a few minutes.
When connecting to an MCP server, you must first send the protocol ID byte
0x01 before sending any packets, like for BNCS. See Diablo II Realm Server Logon Sequence for the logon sequence.
D2GS stands for Diablo 2 Game Server. This constitutes the in-game protocol used by Diablo II. The D2GS protocol is somewhat more complicated than other Blizzard protocols - most D2GS messages have set lengths, and those that don't generally have some unique way of obtaining it. The headers are as follows (for decompressed messages):
(UINT8) Message ID (VOID) Message Data
For compressed messages the format depends on the size of the compressed chunk
If the first byte is < 0xF0:
(UINT8) Message Size (VOID) Message Data
If the first byte is >= 0xF0
(UINT8) High Message Size (UINT8) Low Message Size (VOID) Message Data
The length of the compressed block beginning with bytes >= 0xF0 is:
((High << 8) | Low) & 0xFFF
This size includes the length of the 1-2 byte header.
See Diablo II Game Server Accept Sequence for the logon sequence.
This is a legacy protocol from the early period of Battle.net reverse engineering.
Botnet is a system whereby bots can share information about users and send commands to each other. It is also used by various bot authors as a means of leak protection & statistics collection, and to administer BNLS & Webchannel, in addition to being a useful chat medium when more privacy is needed than Battle.net allows. The headers are as follows:
(UINT8) Protocol Version (Currently 0x01) (UINT8) Message ID (UINT16) Message Length, including this header (VOID) Message Data
BNLS is the Battle.Net Logon Server, and can be used by bot authors to perform some of the computational tasks required during a Battle.net logon. It also allows bot authors to obtain useful information such as the current version byte for a game client, and has provisions for BNCS server emulator authors.
It has the following headers:
(UINT16) Message Length, including this header (UINT8) Message ID (VOID) Message Data
Used by both ladder games and custom games, the format of these messages are nearly the same as BNCS packets. Every packet has the same header:
(UINT8) Always 0xF7 (UINT8) Message ID (UINT16) Message length, including this header (VOID) Message Data
Storm UDP Protocol
This protocol is defined and processed by functions within
Storm.dll and is used for numerous games - namely, Diablo I, Warcraft II: BNE, Starcraft, and Starcraft: Brood War.
(UINT16) Checksum (UINT16) Header Length (UINT16) Seq1 (UINT16) Seq2 (UINT8) CLS (UINT8) Command (UINT8) PlayerID (UINT8) Resend
Checksumis performed by a storm function and is calculated on the whole message, starting at
Header Lengthis the length of the entire message.
Seq1is the sender's position in the outbound stream.
Seq2is the most recently received message.
CLSis always a value from 0-2, 0 indicating that the message is processed by Storm, 1 for asynchronous data, 2 for synchronous data, both of which are passed onto the game client.
Commandspecifies the message type for
CLStype zero, but is always zero otherwise.
PlayerIDis the ID of the sending player.
Resendcontains control flags.
Synchronous messages contain data that all clients must process on the same turn.
Thanks for porting it over, Hdx. :)
"[BNCS Headers Section]
When connecting to a BNCS server, you must first tell the server which protocol you wish to use. Some of the Protocol IDs are:
* Games: 0x01 * FTP: 0x02 * Chat: 0x03
Other Battle.net protocol IDs are MCP to BNCS communication (0x04) and 0x06, which we know nothing about. At a guess, it is used for interserver synchronisation."
That last line looks like it belongs at the end of the first section, not at the end of the entire page.
Otherwise, it doesn't appear to be documented that you must send a protocol ID byte 0x01 before sending other packets for the realm connection (MCP), just like for the BNCS.
On a side note, PLEASE SANITIZE YOUR SQL INPUT! (I just got an error because of my '!)
I also cleaned up the actual document a bit so that there are less blank lines everywhere.
<strong>EDIT:</strong> I cannot see why 0x04 would be up there, I've tried using it on more than one server and it just gets me disconnected (just like any other protocol byte does that is not listed above). However, 0x06 does do something, but I cannot figure out what at this point.
I have concluded this about 0x06:
Client -> 0x06
Server -> DWORD (Server Token?)
Client -> DWORD (Client Token?)
Server -> 20-bytes (BSHA-1 hash?)
Then I get disconnected for doing anything further. If anyone wants to add to what I have, you're more than welcome to. I also do not receive anything periodically from protocol 0x06, and nor do I ever get IP banned (ever), or disconnected for sitting idle.
Compressed Diablo II game server headers are actually a variable length header.
This means the message is the following if the first byte is strictly less than 0xF0.
[Byte] Size of message including this header (void) Compressed payload
and if the first byte is >= 0xF0 the format is:
[Byte] H1 [Byte] H2 (void) Compressed payload.
In this case compute the message length including the header by
computing (pseudo code)
length = ((H1 << 8) + H2) & 0xFFF
Decompressed Diablo II game server protocol looks like:
[Byte] Message ID (void) Decompressed payload
Each compressed message can contain multiple messages in the payload once decompressed and a compressed message may be delivered in multiple reads. The compressed data is padded with zeroes to the next byte boundary. Message lengths are in most cases fixed and can be computed from the contents when they are variable length.
NOTE: Only D2GS S>C messages are compressed except message id 0xAF. C>S are not. See https://bnetdocs.org/packet/245/d2gs-startlogon for more information.