• Welcome to Valhalla Legends Archive.
 

Dll contains CheckRevision()

Started by Trunning, April 30, 2010, 05:16 PM

Previous topic - Next topic

Trunning

#30
Changed the ProductID back to D2DV for experimentation, and I'm receiving something back from the BNLS Server now. And I'm unsure if the Cookie for packet 0x1A is suppose to be the current time, let alone if I'm giving it the right format.

#pragma comment (lib, "Ws2_32.lib")
#include <winsock2.h>
#include <windows.h>
#include <string>
#include <time.h>
#include <iostream>
using namespace std;

typedef unsigned long long FILET;

/////////////////////////////////////////
//
// Structs
//

struct BNCS_HEADER {
BYTE Sanity;
BYTE ID;
WORD Length;
};

struct BNLS_HEADER {
WORD Length;
BYTE ID;
};

struct CMSG_SID_AUTH_INFO {
DWORD   ProtocolID;
DWORD   PlatformID;
DWORD   ProductID;
DWORD   VerByte;
DWORD   ProductLang;
DWORD   LocalIP;
DWORD   TimeZone;
DWORD   LocaleID;
DWORD   LangID;
char *CountryAbbr;
char *CountryName;
};

struct SMSG_SID_AUTH_INFO {
DWORD LogonType;
DWORD ServerToken;
DWORD UDPVal;
FILET ArchiveTime;
char   *ArchiveName;
char   *Seed;
};

struct CMSG_SID_PING{
DWORD PingValue;
};

struct SMSG_SID_PING{
DWORD PingValue;
};

struct CMSG_BNLS_VERCHECK {
DWORD ProductID;
DWORD Flags;
DWORD Cookie;
FILET ArchiveTime;
char *ArchiveName;
char *Seed;
};

struct SMSG_BNLS_VERCHECK {
DWORD Success;
DWORD Version;
DWORD Checksum;
char *VerCheck;
DWORD Cookie;
DWORD LatestVer;
};

/////////////////////////////////////////
//
// Functions
//

void bnls_send(SOCKET sockBNLS, int ID, char *data, int length){
BNLS_HEADER header;
header.ID = ID;
header.Length = length + sizeof(BNLS_HEADER);

char *buffer = (char*)malloc(header.Length);
memset(buffer, 0, header.Length);
memcpy(buffer, &header, sizeof(BNLS_HEADER));
memcpy(buffer + sizeof(BNLS_HEADER), data, length);

if (send(sockBNLS, buffer, header.Length, NULL) != header.Length){
printf("Failed to send complete packet!\n");
}
}

void bncs_send(SOCKET sockBNCS, int ID, char *data, int length){
BNCS_HEADER header;
header.Sanity = 0xFF;
header.ID     = ID;
header.Length = length + sizeof(BNCS_HEADER);

send(sockBNCS, (const char*)&header, sizeof(BNCS_HEADER), NULL);
send(sockBNCS, (const char*)data, length, NULL);
}

int socket_connect(SOCKET sockBNCS, const char *Server, WORD Port){
hostent *host = gethostbyname(Server);
if (!host)
return -1;

SOCKADDR_IN info;
info.sin_family = AF_INET;
info.sin_addr = *((LPIN_ADDR)*host->h_addr_list);
info.sin_port = htons(Port);

if (connect(sockBNCS, (LPSOCKADDR)&info, sizeof(info)) == SOCKET_ERROR){
return -1;
}

return 0;
}

int send_SID_AUTH_INFO(SOCKET sockBNCS){
CMSG_SID_AUTH_INFO pkt;

int sent = 0;
memset(&pkt, 0, sizeof(CMSG_SID_AUTH_INFO));

TIME_ZONE_INFORMATION tz_Time;
GetTimeZoneInformation(&tz_Time);

pkt.ProtocolID = 0x00;
pkt.PlatformID = 'IX86';
pkt.ProductID = 'D2DV';
pkt.VerByte = 0x0C;
pkt.ProductLang = GetUserDefaultLangID();
pkt.LocalIP = inet_addr("192.168.1.100");
pkt.TimeZone = tz_Time.Bias;
pkt.LocaleID = GetUserDefaultLCID();
pkt.LangID = GetUserDefaultLangID();
pkt.CountryAbbr = (char*)malloc(4);
pkt.CountryName = (char*)malloc(14);
strcpy_s(pkt.CountryAbbr, 4, "USA");
strcpy_s(pkt.CountryName, 14, "United States");

char *buffer;
int pkt_size = sizeof(pkt) - (sizeof(char *) * 2);
int full_size = pkt_size + strlen(pkt.CountryAbbr) + strlen(pkt.CountryName) + 2;
buffer = (char*)malloc(full_size);
memset(buffer, 0, full_size);
memcpy(buffer, &pkt, pkt_size);
strcpy_s(buffer + pkt_size, 4, pkt.CountryAbbr);
strcpy_s(buffer + pkt_size + strlen(pkt.CountryAbbr) + 1, 14, pkt.CountryName);

bncs_send(sockBNCS, 0x50, buffer, full_size);
return 1;
}

void send_SID_PING(SOCKET sockBNCS, DWORD value){
printf("Pong 0x%08X\n", value);
bncs_send(sockBNCS, 0x25, (char*)&value, 4);
}

void recv_SID_PING(SOCKET sockBNCS, char *data, int length){
SMSG_SID_PING pkt;
memcpy(&pkt, data, sizeof(pkt));
printf("Ping 0x%08X\n", pkt.PingValue);
send_SID_PING(sockBNCS, pkt.PingValue);
}

void recv_SID_AUTH_INFO(SOCKET sockBNCS, char *data, int length){
SMSG_SID_AUTH_INFO pkt;
int raw_size = 20; //sizeof(pkt) - (sizeof(char *) * 2);
memcpy(&pkt, data, raw_size);

char *name_addr = data + raw_size;
int   name_len  = strlen(name_addr);
char *seed_addr = name_addr + name_len + 1;
int   seed_len  = strlen(seed_addr);

pkt.ArchiveName = (char*)malloc(name_len + 1);
strcpy_s(pkt.ArchiveName, name_len + 1, name_addr);

pkt.Seed = (char*)malloc(seed_len + 1);
strcpy_s(pkt.Seed, seed_len + 1, seed_addr);

printf("Archive: %s\nSeed: %s\n\n", pkt.ArchiveName, pkt.Seed);

SOCKET sockBNLS = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockBNLS == SOCKET_ERROR){
printf("Failed to create socket!\n");
cin.get();
}
printf("Connecting to BNLS Server...\n");
if (socket_connect(sockBNLS, "bnls.mattkv.net", 9367) == -1 ){
printf("Failed to connect to BNLS Server!\n");
cin.get();
}
printf("Connected!\n\n");

time_t tTime;
tTime = time(NULL);

CMSG_BNLS_VERCHECK packet;
packet.ProductID = 0x04;
packet.Flags = 0x00;
packet.Cookie = (DWORD)tTime;
packet.ArchiveTime = pkt.ArchiveTime;
packet.ArchiveName = pkt.ArchiveName;
packet.Seed = pkt.Seed;

int size = sizeof(packet) - (sizeof(char*) * 2);
int full_size = size + strlen(packet.ArchiveName) + strlen(packet.Seed) + 2;
char *buffer = (char*)malloc(full_size);
memset(buffer, 0, full_size);
memcpy(buffer, &packet, size);
strcpy_s(buffer + size, strlen(packet.ArchiveName) + 1, packet.ArchiveName);
strcpy_s(buffer + size + strlen(packet.ArchiveName) + 1, strlen(packet.Seed) + 1, packet.Seed);

printf("Sending 0x1A < Size %d >\n", full_size);
bnls_send(sockBNLS, 0x1A, buffer, full_size);

char *r_data = (char*)malloc(100);
memset(r_data, 0, 100);

recv(sockBNLS, r_data, 100, NULL);

printf("\nData ->\n\n%s\n\n", r_data);

closesocket(sockBNLS);
}

/////////////////////////////////////////
//
// Main Entry Point
//

int main(){
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 0), &wsaData);

SOCKET sockBNCS = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockBNCS == INVALID_SOCKET){
printf("Failed to create socket!\n");
cin.get();
return -1;
}

printf("Connecting...\n");
if (socket_connect(sockBNCS, "useast.battle.net", 6112) == -1){
printf("Failed to connect!\n");
cin.get();
return -1;
}
printf("Connected!\n\n");

printf("Initializing connection ( 0x01 )\n");

int count;
count = send(sockBNCS, "\x01", 1, NULL);

if (count > 0)
printf("Sent Protocol byte < %d >\n\n", count);
else
printf("Failed to initialize connection!\n");

if(send_SID_AUTH_INFO(sockBNCS)){
BNCS_HEADER header;
char *data = (char*)malloc(0x200);
int data_max = 0x200;
bool sid_ping = false, sid_auth = false;

while (true){
if (sid_ping = true && sid_auth == true)
break;

count = recv(sockBNCS, (char*)&header, sizeof(header), NULL);
if (count != sizeof(header)){
printf("Didn't receive full header, %d of %d\n", count, sizeof(BNCS_HEADER));
closesocket(sockBNCS);
WSACleanup();
cin.get();
return 0;
} else {
if (header.Length - 4 > data_max){
free(data);
data = (char *)malloc(header.Length - 4);
}
count = recv(sockBNCS, data, header.Length - 4, NULL);
if (count == SOCKET_ERROR){
count = WSAGetLastError();
printf("Receiving failed error #%d\n", count);
return 0;
}else if(count == 0 && header.Length != 4){
printf("Server closed connection\n");
return 0;
}else if(count != header.Length - 4){
printf("Failed to receive full packet ID: 0x%02X, received %d of %d\n",
header.ID, count, header.Length - 4);
return 0;
}else{
printf("\nReceived Packet ID: 0x%02X Length: 0x%04X (%d)\n",
header.ID, header.Length, header.Length);
switch(header.ID){
case 0x25: recv_SID_PING     (sockBNCS, data, header.Length - 4); sid_ping = true; break;
case 0x50: recv_SID_AUTH_INFO(sockBNCS, data, header.Length - 4); sid_auth = true; break;
}
}
}
}
}

printf("\nExiting Program!\n");
cin.get();
closesocket(sockBNCS);
WSACleanup();
return 0;
}

Sent
0000   6b 00 1a cc 04 00 00 00 00 00 00 00 fe 07 e1 4b  k..............K
0010   cc cc cc cc 70 5f c7 01 cc cc cc cc 76 65 72 2d  ....p_......ver-
0020   49 58 38 36 2d 31 2e 6d 70 71 00 43 3d 37 33 32  IX86-1.mpq.C=732
0030   39 31 38 33 33 33 20 42 3d 34 32 30 39 36 38 39  918333 B=4209689
0040   37 30 32 20 41 3d 31 31 37 37 33 34 38 31 33 31  702 A=1177348131
0050   20 34 20 41 3d 41 2b 53 20 42 3d 42 2d 43 20 43   4 A=A+S B=B-C C
0060   3d 43 5e 41 20 41 3d 41 2d 42 00                 =C^A A=A-B.



Received
0000   0b 00 1a 00 00 00 00 00 fe 07 e1                 ...........

Hdx

#31
You're not receiving anything new back.
You're receiving the cookie you are sending back.
Just like you were before.
Look at the packet log, compare it to the Packet structure, you can obviously see that you are sending a malformed packet.
Figure out why.

If you see 'cc' in your packet logs, 99% of the time, it's because you fucked something up. (CC is usually representative of uninitialized memory)

I think this is a case of compiler optimization, you may need to explicitly define the layout, See: #pragma pack()

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Trunning

I just put a breakpoint an it appears everything is being set, but there is still a few 'cc's in the packet log.

Hdx

Yup, liberal application of pack fixes it.

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status


Hdx

Put #pragma pack(1) before your 1st struct and #pragma paack(pop) after your last.

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Trunning

#36
Ah working now. I'm using this code to receive the packet, but its not working. And this appears to be the same as yours.

BNLS_HEADER head;
memset((void*)&head, 0, sizeof(BNLS_HEADER));
recv(sockBNLS, (char*)&head, sizeof(BNLS_HEADER), NULL);

char *rdata = (char*)malloc(head.Length);
memset((void*)rdata, 0, head.Length);
recv(sockBNLS, rdata, head.Length, NULL);

printf("\n\n%s\n", rdata);

rabbit

The cookie is just a tracking value so you can keep multiple BNLS connections separated; it has no impact on any result or action taken by BNLS.
Grif: Yeah, and the people in the red states are mad because the people in the blue states are mean to them and want them to pay money for roads and schools instead of cool things like NASCAR and shotguns.  Also, there's something about ketchup in there.

Hdx

You need to minus the size of the header from the 2nd recv. As the Length in the header includes the header.

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Trunning

#39
Didn't think of that, still didn't work.

int head_size = sizeof(BNLS_HEADER);

char *rdata = (char*)malloc(head.Length - head_size);
memset((void*)rdata, 0, head.Length - head_size);
recv(sockBNLS, rdata, head.Length - head_size, NULL);


Quote from: rabbit on May 05, 2010, 09:59 AM
The cookie is just a tracking value so you can keep multiple BNLS connections separated; it has no impact on any result or action taken by BNLS.

And the best way to keep it random is use the time.

Hdx

You never want to have a cookie be completely random....
In general it can be used as a 'Request ID', Say you have 4 bots connecting, and you want them all to use the same BNLS connection. You'd send a cookie of 1 for the first bot, 2 for the second, etc.. so you know which response goes to which bot.
BUT the theory behind things like this is way beyond you, so just set it to 0x0BADC0DE. :P

Anyways, set a break point, what happens? Nothing? Define nothing.
Also,
int body_size = head.Length - sizeof(BNLS_HEADER);
char *rdata
if(body_size > 0) {
  rdata = (char*)malloc(body_size);
  memset((void*)rdata, 0, body_size);
  printf("Recv: %d\n", recv(sockBNLS, rdata, body_size, NULL));
}

Try that. (Note how I changed your head_size to body_size, simple change means a lot easier to read code)

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Trunning

#41
Oh wow, it's the address of rdata. I'm trying to copy it to a packet but it doesn't copy the data there.

int body_size = head.Length - sizeof(BNLS_HEADER);
char *rdata;
if(body_size > 0) {
rdata = (char*)malloc(body_size);
memset((void*)rdata, 0, body_size);
printf("\nRecv: %d\n", recv(sockBNLS, rdata, body_size, NULL));
SMSG_BNLS_VERCHECK ya;
memcpy(&ya, rdata, sizeof(SMSG_BNLS_VERCHECK));
}

Hdx

In theroy it should work. I'd like to see your full code.
BTW instead of posting code here, post to pastebin.
Stops table breaking, and i can view it all in 1 glance.
Anyways, is the data being set in rdata?
What does the printf say?
Does it equal body_size?

You really need to be more specific when you post.

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Trunning


Hdx

#44
The problem you have here, is simply, the scope of the struct you are copying to is leaving as right after you do memcpy, so move the declaration of your variable out of the If.
And ugh!
Your code hurts my eyes, I should re-write it a bit cleaner/more organized...

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

|