Valhalla Legends Forums Archive | Battle.net Bot Development | [C++] Grrr, sending a packet to BNLS

AuthorMessageTime
Sorc_Polgara
I don't get it. BNLSProtocolSpec.txt doesn't help me and the help I've gotten makes me feel stupid.

I'm trying to do the first step to connect to BNLS, which is sending the BNLS login ID and recieving the server code. (I have a login ID)

The explaination of the message format in BNLSProtocolSpec.txt doesn't help me at all... I guess I'm stupid :\.

I might not be explaining correctly what I need help with necessarily, so I will show you noob code so maybe you might be able to help me better.

[code]
int sent;
int recieved;

STRING loginID = "polgara";
#define BNLS_AUTHORIZE 0x0e
   
char sentMessage[] = "";
sentMessage[0] = BNLS_AUTHORIZE;
sentMessage[1] = (char)loginID;

// sending message...
sent = send(MySocket, sentMessage, sizeof(sentMessage), 0);

// getting response...
char *recvMsg = "";
recieved = recv(MySocket, recvMsg, sizeof(recvMsg), 0);

cout << "Message sent: " << sentMessage << endl;
cout << "Message recieved: " << recvMsg << endl;
[/code]

Yeah, I'm pathetic I suppose... highschool C++ is shit.

Please help. Perhaps If I can send one message successfully and get a response successfully, then it will help with the others...

*puts on his flame retardent suit*
May 20, 2004, 9:39 PM
Zeller
I dont know were to start. How did you even get that to compile?

do some research on pointers and arrays (including strings). It looks like you are overwriting memory (thats bad).
May 20, 2004, 9:51 PM
Sorc_Polgara
It compiles =\
May 20, 2004, 10:13 PM
Eli_1
[code]
STRING loginID = "polgara";
#define BNLS_AUTHORIZE 0x0e

char sentMessage[] = "";
sentMessage[0] = BNLS_AUTHORIZE;
sentMessage[1] = (char)loginID;
[/code]
I don't see how you can get away with that.
May 20, 2004, 10:17 PM
Zeller
[quote author=Eli_1 link=board=17;threadid=6895;start=0#msg61025 date=1085091428]
[code]
STRING loginID = "polgara";
#define BNLS_AUTHORIZE 0x0e

char sentMessage[] = "";
sentMessage[0] = BNLS_AUTHORIZE;
sentMessage[1] = (char)loginID;
[/code]
I don't see how you can get away with that.
[/quote]

Which part of that? ;D

Im suprised this line compiled though:
[code]
char *recvMsg = "";
[/code]
May 20, 2004, 10:23 PM
AntiFlame
I suggest you look up Winsock programming tutorials. You will need the functions WSAStartup and WSACleanup in addition to what you are doing. (Connecting also helps as well.)

http://www.hal-pc.org/~johnnie2/winsock.html

That should help you get started.
May 20, 2004, 10:55 PM
Eli_1
One thing is your packet isn't in the correct format.
[quote]
BNLS General Info
-----------------

The BNLS server listens on TCP/IP port 9367.
The official BNLS server is bnls.valhallalegends.com.

BNLS message format:

(WORD) Message size, including this 3-byte header
(BYTE) Message ID
(....) Message-dependant data
[/quote]
You would have to take the length of the data your sending (loginID) + 3, and that's the WORD that would start your packet. I'm not sure how you would get those 2 bytes with C++ but in VB I think they use CopyMemory.

Then the next byte of the packet would be \0x0e ( (char)0x0e )

Then your data (loginID) and a null terminator.

[quote author=Eli_1 link=board=17;threadid=6895;start=0#msg61025 date=1085091428]
[code]
STRING loginID = "polgara";
#define BNLS_AUTHORIZE 0x0e

char sentMessage[] = "";
sentMessage[0] = BNLS_AUTHORIZE;
sentMessage[1] = (char)loginID;
[/code]
[/quote]

For future reference:

You could have done something like this, instead of what you have (which I don't know how it compiles anyway :P):

#include <stdio.h>
#include <string.h>
#include <windows.h>
[code]
char packet0E[512];
char copyResult[2]; // Thanks, K

CopyMemory( copyResult, strlen( loginID ) + 3, 2 );

sprintf(packet0E, "%s\0x0e%s\0x00", copyResult, loginID);
// copyResult = The length of the packet+header
// \0x0e is the packet ID...
// loginID is "polgara"
// \0x00 is a NULL-terminator

// packet0E = a char array containing the data
// for packet 0x0e... maybe...

// btw, this might still be wrong, I suck at C++...
[/code]

HTH

May 20, 2004, 11:49 PM
Sorc_Polgara
[quote author=Eli_1 link=board=17;threadid=6895;start=0#msg61036 date=1085096988]
One thing is your packet isn't in the correct format.
[quote]
BNLS General Info
-----------------

The BNLS server listens on TCP/IP port 9367.
The official BNLS server is bnls.valhallalegends.com.

BNLS message format:

(WORD) Message size, including this 3-byte header
(BYTE) Message ID
(....) Message-dependant data
[/quote]
You would have to take the length of the data your sending (loginID) + 3, and that's the WORD that would start your packet. I'm not sure how you would get those 2 bytes with C++ but in VB I think they use CopyMemory.

Then the next byte of the packet would be \0x0e ( (char)0x0e )

Then your data (loginID) and a null terminator.
[/quote]


So, I need to find the length of the loginID then add 3 to it. What does that add 3 come from? Is that the "including this 3-byte header"?

[quote]
I'm not sure how you would get those 2 bytes with C++ but in VB I think they use CopyMemory.
[/quote]

Where did get those 2 bytes from? I don't see the anything about adding 2 bytes. =\

The CopyMemory just by the sound of it, sounds like the memcpy() in C++. Why do you need to use the CopyMemory?

From what I just read, this is what the format for the message to BNLS is:


((loginID) + 3) + (2 bytes) + ( (char)0x0e ) + (loginID)
DWORD ? BYTE STRING


There is nothing between the Message ID and the loginID? So it would be like: "(char)0x0epolgara"?


@AntiFlame
I know how to connect and already have tutorials for that kind of stuff. It doesn't really help when it comes to trying to understand the BNLS system of message sending. Atleast for me.


Edit - Fixed tags so it doesn't break thread table.
May 21, 2004, 12:48 AM
Zeller
You should ignore eli's code. Not only dous he have invalid params in copymemory function, but the sprintf function looks pretty messed up to.
May 21, 2004, 2:19 AM
Eibro
[code]enum PacketIdentifier
{
   BNLS_NULL            = 0x00,
   BNLS_CDKEY            = 0x01,
   BNLS_LOGONCHALLENGE   = 0x02,
   BNLS_LOGONPROOF      = 0x03,
   BNLS_CREATEACCOUNT   = 0x04,
   BNLS_CHANGECHALLENGE   = 0x05,
   BNLS_CHANGEPROOF      = 0x06,
   BNLS_UPGRADECHALLENGE= 0x07,
   BNLS_UPGRADEPROOF      = 0x08,
   BNLS_VERSIONCHECK      = 0x09,
   BNLS_CONFIRMLOGON      = 0x0A,
   BNLS_HASHDATA         = 0x0B,
   BNLS_CDKEY_EX         = 0x0C,
   BNLS_CHOOSENLSREVISION= 0x0D,
   BNLS_AUTHORIZE         = 0x0E,
   BNLS_AUTHORIZEPROOF   = 0x0F,
   BNLS_REQUESTVERSIONBYTE   = 0x10,
   BNLS_VERIFYSERVER      = 0x11,
   BNLS_RESERVESERVERSLOTS   = 0x12,
   BNLS_SERVERLOGONCHALLENGE = 0x13,
   BNLS_SERVERLOGONPROOF= 0x14,
};

#pragma pack( push )
#pragma pack ( 1 )

struct BNLS_Header
{
   WORD packetLength;
   BYTE packetId;
};

#pragma pack( pop )

WSABUF BNLS_CreateAuthPacket( const char* botid ) {
u_long totalLen = sizeof( BNLS_Header ) + strlen( botid ) + 1;
char* buf = new char[totalLen];

BNLS_Header* lpHeader = (BNLS_Header*)buf;
lpHeader->packetLength = totalLen;
lpHeader->packetId = BNLS_AUTHORIZE;

strcpy( buf + sizeof( BNLS_Header ), botid );

WSABUF returnBuf = { totalLen, buf };
return returnBuf;
}[/code]Untested, simple example. You should be able to do something like:
[code]WSABUF authPacket = BNLS_CreateAuthPacket( "mybotid" );
send( sock, authPacket.buf, authPacket.len, 0 );
delete[] authPacket.buf;[/code]
May 21, 2004, 3:03 AM
Eli_1
[quote author=Sorc_Polgara link=board=17;threadid=6895;start=0#msg61053 date=1085100480]
((loginID) + 3) + (2 bytes) + ( (char)0x0e ) + (loginID)
DWORD ? BYTE STRING
[/quote]

It goes WORD, BYTE, STRING.
May 21, 2004, 10:46 AM
tA-Kane
[quote author=Zeller link=board=17;threadid=6895;start=0#msg61026 date=1085091821]Im suprised this line compiled though:[code]char *recvMsg = "";[/code][/quote]I'm not. The compiler would create an empty string in the string table, and then recvMsg would point to the address of that empty string.

I'd just hope you don't then write to recvMsg... ;)

[quote author=Eli_1 link=board=17;threadid=6895;start=0#msg61116 date=1085136412]
[quote author=Sorc_Polgara link=board=17;threadid=6895;start=0#msg61053 date=1085100480]
((loginID) + 3) + (2 bytes) + ( (char)0x0e ) + (loginID)
DWORD ? BYTE STRING
[/quote]

It goes WORD, BYTE, STRING.
[/quote]I'm not exactly sure where this format came up, but I'm going to assume it's the BNLS protocol's packet header, in which case, it's like this (to expand on Eli_1's correct information):

There's first a WORD (2 bytes) that is the length of the packet data + the length of the packet header (so, since you've got loginID as "polgara", that's a total of 8 bytes (counting the null terminator byte for the loginID) for the packet data, plus the 3 byte header, for a total of 11 bytes. So, the first two bytes should be 0x000B).

The next byte is the packet ID. In this case (BNLS_AUTHORIZE), it's 0x0E.

Next up is the packet data, of variable length. For this case, the packet data only contains the loginID, which is "polgara". Don't forget to add the null-terminating byte (so that the server knows where the string ends), so you actually end up with "polgara\0".

Once you've sent the server your login ID, it will send you DWORD, and you will then use that DWORD to create a checksum of your password using the BNLSChecksum() function, which is available here:
http://www.valhallalegends.com/yoni/BNLSChecksum.cpp

Hopefully you'll figure out your way from here.
May 21, 2004, 10:35 PM

Search