• Welcome to Valhalla Legends Archive.
 

[C++] Grrr, sending a packet to BNLS

Started by Sorc_Polgara, May 20, 2004, 04:39 PM

Previous topic - Next topic

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.


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;


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*

Zeller

#1
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).

Sorc_Polgara


Eli_1


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

I don't see how you can get away with that.

Zeller

Quote from: Eli_1 on May 20, 2004, 05:17 PM

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

I don't see how you can get away with that.

Which part of that?  ;D

Im suprised this line compiled though:

char *recvMsg = "";

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.

Eli_1

#6
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
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 from: Eli_1 on May 20, 2004, 05:17 PM

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


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>

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++...


HTH


Sorc_Polgara

#7
Quote from: Eli_1 on May 20, 2004, 06:49 PM
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
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.


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.

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.

Zeller

#8
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.

Eibro

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;
}
Untested, simple example. You should be able to do something like:
WSABUF authPacket = BNLS_CreateAuthPacket( "mybotid" );
send( sock, authPacket.buf, authPacket.len, 0 );
delete[] authPacket.buf;

Eibro of Yeti Lovers.

Eli_1

Quote from: Sorc_Polgara on May 20, 2004, 07:48 PM
((loginID) + 3) + (2 bytes) + ( (char)0x0e ) + (loginID)
    DWORD               ?                  BYTE            STRING

It goes WORD, BYTE, STRING.

tA-Kane

Quote from: Zeller on May 20, 2004, 05:23 PMIm suprised this line compiled though:char *recvMsg = "";
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 from: Eli_1 on May 21, 2004, 05:46 AM
Quote from: Sorc_Polgara on May 20, 2004, 07:48 PM
((loginID) + 3) + (2 bytes) + ( (char)0x0e ) + (loginID)
    DWORD               ?                  BYTE            STRING

It goes WORD, BYTE, STRING.
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.
Macintosh programmer and enthusiast.
Battle.net Bot Programming: http://www.bash.org/?240059
I can write programs. Can you right them?

http://www.clan-mac.com
http://www.eve-online.com