• Welcome to Valhalla Legends Archive.
 

Need help. Logging BNet... [NOT solved]

Started by z-stars, July 22, 2004, 01:47 PM

Previous topic - Next topic
|

K

#30
UserLoser:  Why all the inline asm?

typedef void(__fastcall *pHashingFunction)(void* outbuf, void* inbuf, DWORD len);

DWORD dwHashAddr = 0x12400;
HMODULE hBattleSnp = LoadLibrary(_T("battle.snp"));
dwHashAddr += reinterpret_cast<DWORD>(hBattleSnp);
pHashFunction HashData = reinterpret_cast<pHashFunction>(dwHashAddr);
// ...
HashData(a, b, c); // whatever :-P


but otherwise, good code.  Nice to see other people are as lazy as I am.   

z-stars

Ok I think I understand but there are some things I dont know what they are.
I supose dwProduct is my Key1Product and my Key2Product, but what are ServerSessionKey, dwPublic and dwPrivate?


DWORD dwHashBuffer[6];
   DWORD dwOutBuffer[5];
   dwHashBuffer[0] = GetTickCount();
   //dwHashBuffer[1] = ServerSessionKey;
   dwHashBuffer[2] = Key1Product;
   //dwHashBuffer[3] = dwPublic;
   dwHashBuffer[4] = 0;
   //dwHashBuffer[5] = dwPrivate;
   HashData(24, dwOutBuffer, dwHashBuffer);
   /* ~~ */
   DWORD dwHashBuffer2[6];
   DWORD dwOutBuffer2[5];
   dwHashBuffer[0] = GetTickCount();
   //dwHashBuffer[1] = ServerSessionKey;
   dwHashBuffer[2] = Key2Product;
   //dwHashBuffer[3] = dwPublic;
   dwHashBuffer[4] = 0;
   //dwHashBuffer[5] = dwPrivate;
   HashData(24, dwOutBuffer2, dwHashBuffer2);
   /* ~~ */

UserLoser.

Quote from: z-stars on July 23, 2004, 04:57 PM
Ok I think I understand but there are some things I dont know what they are.
I supose dwProduct is my Key1Product and my Key2Product, but what are ServerSessionKey, dwPublic and dwPrivate?


DWORD dwHashBuffer[6];
   DWORD dwOutBuffer[5];
   dwHashBuffer[0] = GetTickCount();
   //dwHashBuffer[1] = ServerSessionKey;
   dwHashBuffer[2] = Key1Product;
   //dwHashBuffer[3] = dwPublic;
   dwHashBuffer[4] = 0;
   //dwHashBuffer[5] = dwPrivate;
   HashData(24, dwOutBuffer, dwHashBuffer);
   /* ~~ */
   DWORD dwHashBuffer2[6];
   DWORD dwOutBuffer2[5];
   dwHashBuffer[0] = GetTickCount();
   //dwHashBuffer[1] = ServerSessionKey;
   dwHashBuffer[2] = Key2Product;
   //dwHashBuffer[3] = dwPublic;
   dwHashBuffer[4] = 0;
   //dwHashBuffer[5] = dwPrivate;
   HashData(24, dwOutBuffer2, dwHashBuffer2);
   /* ~~ */


!  I said ServerSessionKey is from 0x50 (i believe the 3rd DWORD, received ofcourse).  dwPublic and dwPrivate are the CDKey values returned from RunCDKeyDecode which I also posted.

z-stars

Erm I got some more questions, in BnetDocs says that for each cdkey you have to put the first number of the cdkey... what does it mean with that? If it means the first group of digits and letters, there are letters, and if it means the first digit, in a packet log it isnt the first digit :(
Another thing, the third DWORD to sent is called "Exe Hash", how do I get that?
And a little thing, in RunCDKeyDecode(), the last argument, do I include the dashes or I dont include them?

UserLoser.

No dashes, no spaces.  For a Starcraft CDKey, it should be 13 numbers, for a D2/W2 CDKey, it should be 16 numbers/letters.  It doesn't support W3 CDKeys.

z-stars

I see, but how do I get Exe hash and CD Key 1 Number 1 and CD Key 2 Number 2? I tried setting Exe Hash to zero and CD Key Num 1's to some values I logged, but I send the packet and BNet IP bans me and doesn't send me the next packet...

UserLoser.

exe hash is from checkrevision, which someone posted. cdkey value 1 = dwpublic, cdkey value 2 = dwprivate.

z-stars

Quote from: UserLoser. on July 23, 2004, 08:02 PM
exe hash is from checkrevision, which someone posted. cdkey value 1 = dwpublic, cdkey value 2 = dwprivate.


Oh yeah I posted a checkrevision function, I'll try to make it work tomorrow :)

Banana fanna fo fanna

semi-OT, but how did you find the offset in battle.snp?

UserLoser.

Quote from: $t0rm on July 24, 2004, 09:49 AM
semi-OT, but how did you find the offset in battle.snp?

disassembly.

z-stars

#40
I have "finished" the function to build 0x51 packet but it doesn't work, I run it, it sends the packet, but then it doesn't receive the next packet and BNet IP bans me :( Anyway I didn't expect it to work at the first try... I think I need some help to make it work...

Some things that may be useful to know...
-CheckRevision() returns TRUE (I think that means it didnt fail)
-These are all the components of packet 0x51. BNetDocs is offline now so I dont know if there they are called exactly the same way.


(byte) 0xFF
(byte) PacketID
(word) PacketLength
(dword) Client Token
(dword) Exe Version
(dword) Exe Hash
(dword) Number of CD Keys
(dword) Always 0 for non warcraft 3 connections.

;First cd key
(dword) Key Length
(dword) Product ID
(dword) First number of the cdkey
(dword) Unknown (0)
(dword[5]) CdKey Hashed Data

;Second cd key
(dword) Key Length
(dword) Product ID
(dword) First number of the cdkey
(dword) Unknown (0)
(dword[5]) CdKey Hashed Data

(string) Exe Info
(string) CD Key Owner

-The things that I think that may go wrong are for example the conversions to LittleEndian. For example, I have assumed that dwOutputBuffer is "Rdy to send", I mean, I just copy all its bytes in order into the packet. dwOutputBuffer[0]'s first byte will  be the first byte at the packet's CDKeyDataHash bytes, etc.
-Another thing that may be wrong is (dword) First CD Key first number and (dword) Second CD Key first number. In my function, the first one is dwPublic and the second dwPrivate, because their values aren't the same than the values I log with a packet sniffer when I log to battle.net.
-szD2CdKey, the var that contains the D2 cd key for RunCDKeyDecode to decode, is declared like this: char * szD2CdKey = "xxxxxxxxxxxxxxxx"; (of course, each x represents a number / letter of the real cd key). There are 16 numbers/letters in total.
-I dont know what more to say, just ask if I forgot something.

This is the code, I have tidied it to make it more readable and commented it better... The CheckRevision() function is the same that I posted at the first page of this topic.  

// S SID_AUTH_CHECK
// This function is supossed to build and send the fifth packet (0x51)
// At the start of this function, csFifthPacket.packet (the packet 0x51 that
// this function sends to battle.net at the end) is EMPTY.
int LTBNFifthPacket()
{
   /* Var declarations... */
   int n = 0;
   char * CDKeyOwner = "Me";
   /* End of Var declarations */

   /* First, load Battle.snp to do the hasing for us */
   HMODULE battlesnp;
   battlesnp = LoadLibrary("Battle.snp");
   if(!battlesnp) cout << "Couldn't load battle.snp" << endl;
   /* Battlesnp Loaded */


   /* CHECK REVISION */
   /* Call CheckRevision() to get the some of the values to send */
   /* The values we get are: ExeHash and Version (dwExeHash, and dwVersion) */
   /* Also, we get an ExeInfo string. (To CRExeInfo). */
   DWORD dwVersion = 0;
   DWORD dwChecksum = 0;
   char CRExeInfo[5000];
   memset(CRExeInfo, 0, 5000);
   //strcpy(CRExeInfo, ExeInfo);
   BOOL bCheckRevision = 0;
   bCheckRevision =
      CheckRevision("C:\\Archivos de programa\\Diablo II\\Game.exe",
         "C:\\Archivos de programa\\Diablo II\\Bnclient.dll",
         "C:\\Archivos de programa\\Diablo II\\storm.dll",
         r_SID_AUTH_INFO.ValueString,
         &dwVersion, &dwChecksum,
         CRExeInfo,
         r_SID_AUTH_INFO.IX86ver_filename);
   if(bCheckRevision == FALSE)
      cout << "ERROR: CheckRevision() Failed" << endl;
   else cout << "CheckRevision() Success" << endl;
   /*printf("dwVersion: %x  || dwChecksum: %x || ExeInfo: %s",
      dwVersion, dwChecksum, CRExeInfo);*/
   /* END OF CHECK REVISION */
         

   /* VARIABLES TO PUT IN THE PACKET DECLARATIONS */
   int x = 0;
   BYTE FirstByte = 0xFF; // It's always 0xFF
   BYTE PacketID = 0x51; // PacketId's 0x51
   WORD PacketLen = 136; // Packet Length is 136
   DWORD ClientToken = GetTickCount(); // I use GetTickCount() to get that
   DWORD ExeVersion = dwVersion; // From CheckRevision()
   DWORD ExeHash = dwChecksum; // From CheckRevision()
   DWORD CDKeyNumber = 2; // 1 D2 cd key, 1 Lod cd key.
   DWORD UsingOfKeys = 0; // 0

   DWORD Key1Len = 0x10; // Length of D2 CdKey: 16 (0x10)
   DWORD Key1Product = 0x06000000; // Key1 Product: 0x06000000
   DWORD Key1Num1 = x; // This is supossed to be the First Number of the first cd key.
                  // I'm not sure how to get it.
   DWORD Key1Unknown = 0; // Unknown(0)

   DWORD Key2Len = 0x10; // Same...
   DWORD Key2Product = 0x0A000000; // Key2 (LOD) Product: 0x0A000000
   DWORD Key2Num1 = x;      // Same...
   DWORD Key2Unknown = 0; // Unknown (0)
   /* END OF VARIABLES TO PUT IN THE PACKET DECLARATIONS */

   /* CALL RUNCDKEYDECODE */
   DWORD dwProduct = Key1Product;
   DWORD dwPrivate = 0;
   DWORD dwPublic = 0;
   RunCDkeyDecode(&dwProduct, &dwPublic, &dwPrivate, szD2CdKey);
   ////
   //cout << endl << "RUNCDKEYDECODE" << endl;
   //cout << "dwProduct: " << hex << dwProduct << endl;
   //cout << "dwPublic: " << hex << dwPublic << endl;
   //cout << "dwPrivate: " << hex << dwPrivate << endl;
   //cout << endl << endl;
   /* END OF CALL RUNCDKEYDECODE */

   /* CALL HASHDATA FOR CDKEY1*/
   DWORD dwHashBuffer[6];
   DWORD dwOutBuffer[5]; // This is supossed to be the CDKey1 Data.
   dwHashBuffer[0] = ClientToken; // We got this with GetTickCount()
   dwHashBuffer[1] = r_SID_AUTH_INFO.Server_Token; // Bnet sent this in the last packet
   dwHashBuffer[2] = dwProduct; // We got this with RunCDKeyDecode
   dwHashBuffer[3] = dwPublic; // We got this with RunCDKeyDecode too
   dwHashBuffer[4] = 0; // 0...
   dwHashBuffer[5] = dwPrivate; // Also, we got this with RunCDKeyDecode
   HashData(24, dwOutBuffer, dwHashBuffer);
   /* END OF CALL HASHDATA */

   /* DO THE SAME FOR CDKEY2 */
   DWORD dwProduct2 = Key2Product;
   DWORD dwPrivate2 = 0;
   DWORD dwPublic2 = 0;
   RunCDkeyDecode(&dwProduct, &dwPublic, &dwPrivate, szCdKey2);

   DWORD dwHashBuffer2[6];
   DWORD dwOutBuffer2[5];
   dwHashBuffer[0] = GetTickCount();
   dwHashBuffer[1] = r_SID_AUTH_INFO.Server_Token;
   dwHashBuffer[2] = dwProduct2;
   dwHashBuffer[3] = dwPublic2;
   dwHashBuffer[4] = 0;
   dwHashBuffer[5] = dwPrivate2;
   HashData(24, dwOutBuffer2, dwHashBuffer2);
   /* ~~ */


   /* WRITE EVERYTHING IN THE PACKET */

   // Info about csFifthPacket class:
   // The packet itself is csFifthPacket.packet and it is a
   // dynamically allocated BYTE array.
   // The position the next function will write to is stored at
   // nByte2Write and is increased automatically with each WriteX function
   // call.
   // WriteByte writes a byte to packet. (csFifthPacket.packet).
   // WriteWord and WriteDWord take 2 arguments. The first one tells
   // if it has to convert the Word or DWord given to Little Endian before
   // putting it in packet or not. If the first argument is 0, it will
   // convert the DWORD given to Little Endian, and then put it in the
   // packet. If it is 1, it will put it in the packet directly without
   // converting it.
   // WriteString() just writes a string and a null terminator to packet.

   csFifthPacket.WriteByte(0xFF);
   csFifthPacket.WriteByte(0x51);
   csFifthPacket.WriteWord(0, 136);
   
   csFifthPacket.WriteDWord(0, ClientToken);
   csFifthPacket.WriteDWord(0, ExeVersion); // From CheckRevision()
   csFifthPacket.WriteDWord(0, ExeHash);  // From CheckRevision()
   csFifthPacket.WriteDWord(0, CDKeyNumber);
   csFifthPacket.WriteDWord(0, UsingOfKeys);

   csFifthPacket.WriteDWord(0, Key1Len);
   csFifthPacket.WriteDWord(1, Key1Product);
   csFifthPacket.WriteDWord(1, dwPublic);
   csFifthPacket.WriteDWord(0, Key1Unknown);
   csFifthPacket.WriteDWord(1,dwOutBuffer[0]);
   csFifthPacket.WriteDWord(1,dwOutBuffer[1]);
   csFifthPacket.WriteDWord(1,dwOutBuffer[2]);
   csFifthPacket.WriteDWord(1,dwOutBuffer[3]);
   csFifthPacket.WriteDWord(1,dwOutBuffer[4]);

   csFifthPacket.WriteDWord(0, Key2Len);
   csFifthPacket.WriteDWord(1, Key2Product);
   csFifthPacket.WriteDWord(1, dwPrivate);
   csFifthPacket.WriteDWord(0, Key2Unknown);
   csFifthPacket.WriteDWord(1,dwOutBuffer2[0]);
   csFifthPacket.WriteDWord(1,dwOutBuffer2[1]);
   csFifthPacket.WriteDWord(1,dwOutBuffer2[2]);
   csFifthPacket.WriteDWord(1,dwOutBuffer2[3]);
   csFifthPacket.WriteDWord(1,dwOutBuffer2[4]);

   csFifthPacket.WriteString(CRExeInfo); // From CheckRevision()
   csFifthPacket.WriteString(CDKeyOwner);

// These two sentences set the packet size word of packet to the packet
   // len. (Previously it was 136 instead 134).
   csFifthPacket.SetByte2Write(2);
   csFifthPacket.WriteWord(0, csFifthPacket.GetPacketLen());
   /* END OF WRITE EVERYTHING AT THE PACKET */

   
   /* SEND csFifthPacket.packet TO BATTLE.NET */
   n = SendPacket(csFifthPacket.packet, csFifthPacket.GetPacketLen());
   if(n == -1) error(10, "SendPacket");
   else cout << "Packet 0x51 Sent " << "Bytes: " << n << endl;
   /* END OF SEND PACKET TO BATTLE.NET */

   return n;
}


void HashData(DWORD length, LPVOID outbuf, LPVOID tohash)
{
  DWORD len = length;
  __asm {
     push ecx
     push edx
     mov ecx, outbuf
     mov edx, tohash
     push len
     call HashFunction
     pop edx
     pop ecx
  }
}


void RunCDkeyDecode(DWORD *Product, DWORD *CDKeyVal1, DWORD *CDKeyVal2, const char *CDKey)
{

  __asm
  {
     push ecx
     push edx
     mov ecx, CDKey
     mov edx, Product
     push CDKeyVal2
     push CDKeyVal1
     call DecodeCDKeyFunction
     pop edx
     pop ecx
  }
}


Sorry for asking so many questions and thanks for your help in advance :)

UserLoser.

#41
Could you show us a packet log of the connection?

z-stars

Packet log between my program and USWEST battle.net (Normally I use europe but I was IP banned...)
The X's are either the CDKey Hashed Data or the CD Key first numbers...


1  Hide  Hide  1  Send  
0000  01                                                 .

2  Hide  Hide  50  Send  
0000  FF 50 32 00 00 00 00 00 36 38 58 49 50 58 32 44    .P2.....68XIPX2D
0010  0A 00 00 00 53 45 73 65 50 23 6B 1D 88 FF FF FF    ....SEseP#k.....
0020  0A 0C 00 00 0A 0C 00 00 45 53 50 00 53 70 61 69    ........ESP.Spai
0030  6E 00                                              n.

3  Hide  Hide  8  Recv  
0000  FF 25 08 00 3E 6B CB 97                            .%..>k..

4  Hide  Hide  98  Recv  
0000  FF 50 62 00 00 00 00 00 23 E1 64 6C 22 6F 15 00    .Pb.....#.dl"o..
0010  00 81 8F 83 91 E7 C3 01 49 58 38 36 76 65 72 37    ........IX86ver7
0020  2E 6D 70 71 00 41 3D 35 37 38 33 31 35 30 34 32    .mpq.A=578315042
0030  20 42 3D 37 39 35 34 31 35 34 34 33 20 43 3D 36     B=795415443 C=6
0040  32 34 39 37 32 31 37 20 34 20 41 3D 41 2D 53 20    2497217 4 A=A-S
0050  42 3D 42 2B 43 20 43 3D 43 5E 41 20 41 3D 41 2D    B=B+C C=C^A A=A-
0060  42 00                                              B.

5  Hide  Hide  9  Send  
0000  FF 25 08 00 F3 2A 9F 4D CC                         .%...*.M.

6  Hide  Hide  134  Send  
0000  FF 51 88 00 67 A3 B1 00 00 0A 00 00 1E 9B F9 00    .Q..g...........
0010  02 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00    ................
0020  XX XX XX XX 00 00 00 00 XX XX XX XX XX XX XX XX    ................
0030  XX XX XX XX XX XX XX XX XX XX XX XX 10 00 00 00    ................
0040  00 00 00 00 XX XX XX XX 00 00 00 00 XX XX XX XX    .....1.`.......5
0050  XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    .....t....R5...r
0060  47 61 6D 65 2E 65 78 65 20 30 35 2F 31 36 2F 30    Game.exe 05/16/0
0070  34 20 32 31 3A 33 31 3A 33 36 20 31 31 39 38 38    4 21:31:36 11988
0080  35 37 00 4D 65 00                                  57.Me.

UserLoser.

#43
Quote
6  Hide  Hide  134  Send

You're giving 0x88 (136) as your length.

Edit: Also, you're only supposed to reply with one DWORD in 0x25, and echo what the server sent you first.  That's mostly be causing the disconnect.  The bad length on 0x51 packet would most likely just make the server wait for 2 more bytes (or however many) until the amount of data you sent matched the length you have given.

z-stars

#44
Quote from: UserLoser. on July 24, 2004, 01:47 PM
Quote
6  Hide  Hide  134  Send

You're giving 0x88 (136) as your length.

Yeah, modified the code in my program (and the code in the post) but it still doesn't work. :(

|