Valhalla Legends Forums Archive | Battle.net Bot Development | ID's

AuthorMessageTime
Lenny
Code:
1 Hide Hide 11 Send
0000 0B 00 0E 73 74 65 61 6C 74 68 00 ...stealth.

2 Hide Hide 7 Recv
0000 07 00 0E 1C 16 F8 36 ......6

3 Hide Hide 7 Send
0000 07 00 0F 02 97 93 3D ......=

4 Hide Hide 7 Recv
0000 07 00 0F 00 00 00 00 .......

5 Hide Hide 7 Send
0000 07 00 10 02 00 00 00 .......

6 Hide Hide 11 Recv
0000 0B 00 10 02 00 00 00 C7 00 00 00 ...........

This is a packet log of stealthbot, the next packet is 0x50...Can someone me the names of these 6 packets? I couldn't find them at Bnet Docs.
(Also its a BNLS connection)
August 10, 2003, 4:13 AM
Kp
The names for the messages ought to be in the BNLSProtocolSpec.
August 10, 2003, 4:53 AM
CrAz3D
I do beleive that the first one is just the sending of the BNLS username.

& the last maybe the client?
August 11, 2003, 3:22 AM
Soul Taker
The last sent/recved packets are requesting and recieving the version byte.
August 11, 2003, 5:59 AM
tA-Kane
Lenny, the first send is StealthBot (I assume?) telling BNLS its bot ID.

The first receive is the BNLS server telling the bot that the ID has been recognized, but that a password hash is necessary, and the last DWORD therein is the seed with which to hash. Note that the BNLS password hash function is different than BNCS's broken SHA-1 hash function.

The second sent packet is the bot telling the server the hash of the password, using the seed given above.

The second receive is the server saying that the hash is accepted.

The third send is the bot requesting the version byte for Brood War (product ID 2).

The third receive is the server telling the bot that Brood War is a recognized product ID, and that the version byte for that is 0xC7.
August 11, 2003, 1:55 PM
Lenny
Also, just to confirm... the name of the BNLS packets are right after the header? Such as packet 1 would be 0xE
August 12, 2003, 3:58 AM
tA-Kane
As stated in the BNLS protocol specification, available at
http://www.valhallalegends.com/yoni/BNLSProtocolSpec.txt:

[quote]BNLS message format:

(WORD) Message size, including this 3-byte header
(BYTE) Message ID
(....) Message-dependant data[/quote]
August 12, 2003, 12:50 PM
Arta
<shamelessplug>
Also documented, slightly more prettily, on BnetDocs
</shamelessplug>
August 13, 2003, 8:05 AM
Lenny
Can someone show me an example of how to process a recieved packet? (such as text from chat)
August 13, 2003, 8:13 AM
Arta
Assuming you're talking about receiving text over a Binary connection:

Text would be received in packet 0x0F (SID_CHATEVENT), which has the following structure:

[code]
(DWORD)       Event ID
(DWORD)       User's Flags
(DWORD)       Ping
(DWORD)       IP Address (Defunct)
(DWORD)       Account number (Defunct)
(DWORD)       Registration Authority (Defunct)
(STRING)       Username
(STRING)       Text
[/code]

A DWORD is an integer (A whole number). It is 4 bytes long. Therefore, Event ID consists of the first 4 bytes of the packet, after the header. User's Flags would be the next 4, ping the 4 after that. Generally, people write a class or a set of functions that process a packet by getting information (in this case, a DWORD) from the beginning of the packet, and incrementing a position variable - so that you know what you've processed so far, and what the next bit of information is that you're going to get.

For example:

Say you have a Battle.net packet (this one is invented):

FF 99 00 0C 11 11 11 11 22 22 22 22 33 33 33 33

The first 4 bytes (FF 99 00 0C) are the header, they tell you that your packet ID is 99, and the length is '00 0C', or 12. Usually, people set their Position variable to the first byte after the header - so it would start at 4 (5 if your language is 1-based and not 0-based). If we now call a function to get the first DWORD of the packet, it would work like this:

1. Examine Position to find out where we are in the packet
2. Take 4 bytes of data at that position and save them somewhere
3. Add 4 to the Position variable, so that it's now pointing at the byte of the packet right after what we just read.

Thus, we'd end up with '11 11 11 11' as the DWORD, Position would be 8, and we'd be ready to read the next DWORD ('22 22 22 22') when we need to.

Processing text works in exactly the same way. You'd start by reading ther Event ID - this tells you what the rest of the packet will mean. It could be a user leaving or joining the channel, an error, information, a whisper, or chat text (among other things). There's a complete list on BnetDocs. Assuming it's chat text (the number for which is 5) you'd want to read the username of the person who's talking, and the text they're sending. You don't really need the flags and ping and soforth for this event, so most people wouldn't bother reading them. They'd just set their Position variable to 28 - so it would point to the start of the Username.

Reading strings is obviously a bit different from reading numbers, because they can be any length. Strings in Battle.net packets always end with a NULL byte (That's a byte with a value of zero), and this makes it fairly easy to read them. You just read one byte of the packet at a time and save it. If that byte is NULL, then you've reached the end of the string. If not, you're still in the middle, so add that byte to the end of string variable, and read the next byte. When you get to a NULL, your string variable will contain the string from the packet. You then add the length of your string to your Position variable, so that it points to the next byte of the packet. In this case, if the name was 'Arta', your Position variable would equal 33 after reading the name. That's 28 (Current value of Position) + 5 (The length of the username, including it's NULL byte).

Processing packets works in basically the same way, be it Botnet, Battle.net, or BNLS. The only thing that changes is the content of the packets. You need to know, for each packet, what the data is you're looking at. Is it a string? a word? a dword? Having this information allows you to process the packet, get the data you need from it, and send a reply (or whatever) based on that information. BnetDocs was set up to provide some of this information.

Hope that helps!
August 13, 2003, 8:39 AM
tA-Kane
[quote author=Arta[vL] link=board=17;threadid=2268;start=0#msg17944 date=1060763975]You just read one byte of the packet at a time and save it. If that byte is NULL, then you've reached the end of the string. If not, you're still in the middle, so add that byte to the end of string variable, and read the next byte. When you get to a NULL, your string variable will contain the string from the packet.[/quote]Or, if you're using VB, then there's no reason to create your own loop to search for the null byte; InStrB() will do this for you. Simply do this:

[code]Function MyBinaryBuffer.GetStr() As String
//Me.Data contains the packet data
//Me.Location is the reading start position
Dim Length As Integer
Dim Buffer As String

Length = InStrB(Me.Location+1,Me.Data,Null)-Me.Location-1
//Me.Location+1, because InStrB() is 1-based, not 0-based
//Remove the Location from the return value, because the position is based off of the start of the string
Buffer = MidB(Me.Data,Me.Location+1,Length)
//MidB() is also 1-based
Me.Location = Me.Location + Length + 1
//+1 to pass over the NULL byte
Return Buffer
End Function[/code]

If you're familiar with InStr(), but aren't familiar with InStrB(), then they work the same, except that InStr() assumes the string is text, and works with international text (null bytes are a valid byte in international languages, and don't necessarily mean the end of the string. Also, "c" and "C" are the same thing, meaning that InStr() is case insensitive), and InStrB() assumes the string is binary data (so, "c" is different than "C").

Same goes for the difference between Mid() and MidB().
August 13, 2003, 1:03 PM
Lenny
Thanks Arta and ta
August 14, 2003, 6:37 AM

Search