• Welcome to Valhalla Legends Archive.
 

Exe Hash and Hashed key Data (C++)

Started by ThePro, November 19, 2005, 04:15 AM

Previous topic - Next topic

ThePro

Hi there!
I'm trying to code a Bot in C++ for bnet which will Login as a Starcraft Client, since "Normal" bots are restricted to the most channels. I'm using a Packet sniffer (WPE) and logged in with SC a few times, so I was able to see, what SC sends out while logging in. I also read the BnetDocs, which are very helpful. I'm working on SID_AUTH_CHECK (0x51) at the moment.

The Problem is, that a Exe Hash and the Hashed key Data changes every time you log in (since the Server Token is random I guess) So, how to calculate a valid Exe hash and how to Get that Hashed key data? Ich read something of a CheckRevision.dll but I can't find any Information where to find it or how to use it. :(


Ringo

#1
Hi
I did a quick search of the forum and found these:
Check revision:
http://forum.valhallalegends.com/index.php?topic=13059.msg131870#msg131870

Key hashing:
http://forum.valhallalegends.com/index.php?topic=623.msg4742#msg4742

im not sure how helpfull/working they are, so you might need to search more.
You will also need to decode the cdkey with some sort or CDkeydecode() function before you hash it.

EDIT: could try here also: http://forum.valhallalegends.com/index.php?topic=11491.msg111146#msg111146

ThePro

Thx!
I've found this code to calculate the hash:


void _stdcall calchashbuf(unsigned long *hash, void *inbuf, int len)
{
   char *buf = (char*)inbuf;
   int pos;
   int sublen;
   unsigned long hashbuf[0x10 + 5];
   hashbuf[0] = 0x67452301;
   hashbuf[1] = 0xEFCDAB89;
   hashbuf[2] = 0x98BADCFE;
   hashbuf[3] = 0x10325476;
   hashbuf[4] = 0xC3D2E1F0;
   for(pos=0; pos<len; pos+=0x40) {
      sublen = len - pos;
      if(sublen > 0x40)
         sublen = 0x40;
      memcpy(hashbuf+5, buf+pos, sublen);
      if(sublen<0x40)
         ZeroMemory((char*)(hashbuf+5)+sublen, 0x40-sublen);
      datahash(hashbuf);
   }
   memcpy(hash, hashbuf, 5*4);
}


void _stdcall datahash(unsigned long *param)
{

   unsigned long buf[0x50];
   unsigned long dw, a, b, c, d, e, *p;
   int i;
   memcpy(buf, param+5, 0x40);
   for(i=0x10; i<0x50; i++) {
      dw = buf[i-0x10]^buf[i-0x8]^buf[i-0xe]^buf[i-0x3];
      buf = (1>>(0x20-(unsigned char)dw)) | (1<<(unsigned char)dw);     
   }
   a = param[0];
   b = param[1];
   c = param[2];
   d = param[3];
   e = param[4];
   p = buf;
   i = 0x14;
   do
   {
      dw = ((a<<5) | (a>>0x1b)) + ((~b & d) | (c & b)) + e + *p++ + 0x5A827999;
      e = d;
      d = c;
      c = (b>>2)  | (b<<0x1e);
      b = a;
      a = dw;
   }
   while(--i);
   i = 0x14;
   do
   {
      dw = (d ^ c ^ b) + e + ((a<<5) | (a>>0x1b)) + *p++ + 0x6ED9EBA1;
      e = d;
      d = c;
      c = (b>>2) | (b<<0x1e);
      b = a;
      a = dw;
   }
   while(--i);
   i = 0x14;
   do
   {
      dw = ((c & b) | (d & c) | (d & b)) + e + ((a<<5) | (a>>0x1b)) + *p++ - 0x70E44324;
      e = d;
      d = c;
      c = (b>>2) | (b<<0x1e);
      b = a;
      a = dw;
   }
   while(--i);

   i = 0x14;
   do
   {
      dw = ((a<<5) | (a>>0x1b)) + e + (d ^ c ^ b) + *p++ - 0x359D3E2A;
      e = d;
      d = c;
      c = (b>>2) | (b<<0x1e);
      b = a;
      a = dw;
   }
   while(--i);

   param[0] += a;
   param[1] += b;
   param[2] += c;
   param[3] += d;
   param[4] += e;
}


What do I have to put into inbuf and len? How to decode the CD-Key? I can't find anything about it. :(



rabbit

I think that you will find BNCSutil very helpful for your project.  You should take a look at it.  ^^
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.

ThePro

Thanks man, that's what I was looking for. :)
Which CD-Key do I have to decode now? Is it this one: 2421-63903-6220? Or is that the decoded key already?

I'm coding in C++ but the documentation is for VB. Since .dll works for every language I only have to translate it in C++ and it will work I guess ;)

QwertyMonster


DeTaiLs

Posting your cd-key is not a smart idea and that is the one you have to decode.



ThePro

Nevermind, that's not my CD-Key lol.  I just wanted to let you know what I mean, since there are some other encrypting "Keys". (a,b,c,d,e,f,g,x ect.)

Thanks. ;)

l)ragon

void HashData(void* lpSource, int nLength, void* lpResult)
{
BYTE bBuffer[1024];
int i;
DWORD a, b, c, d, e, g, * lpdwBuffer;

ZeroMemory(bBuffer, 1024);
CopyMemory(bBuffer, lpSource, nLength);
lpdwBuffer = (LPDWORD) bBuffer;

for (i=0; i<64; i++)
lpdwBuffer[i+16] = ROL(1, (lpdwBuffer[i] ^ lpdwBuffer[i+8] ^
lpdwBuffer[i+2] ^ lpdwBuffer[i+13]) % 32);

a = 0x67452301lu;
b = 0xefcdab89lu;
c = 0x98badcfelu;
d = 0x10325476lu;
e = 0xc3d2e1f0lu;

for(i = 0; i < (20 * 4); i++) {
if((i >= -1) && (i <= (20*1)-1)) {
g = lpdwBuffer[i] + ROL(a,5) + e + ((b & c) | (~b & d)) + 0x5a827999lu;
}
if((i >= (20*1)) && (i <= (20*2)-1)) {
g = (d ^ c ^ b) + e + ROL(g,5) + lpdwBuffer[i] + 0x6ed9eba1lu;
}
if((i >= (20*2)) && (i <= (20*3)-1)) {
g = lpdwBuffer[i] + ROL(g,5) + e + ((c & b) | (d & c) | (d & b)) -
0x70e44324lu;
}
if((i >= (20*3)) && (i <= (20*4)-1)) {
g = (d ^ c ^ b) + e + ROL(g,5) + lpdwBuffer[i] - 0x359d3e2alu;
}
e = d;
d = c;
c = ROL(b,30);
b = a;
a = g;
}

  lpdwBuffer = (LPDWORD) lpResult;
  lpdwBuffer[0] = 0x67452301lu + g;
  lpdwBuffer[1] = 0xefcdab89lu + b;
  lpdwBuffer[2] = 0x98badcfelu + c;
  lpdwBuffer[3] = 0x10325476lu + d;
  lpdwBuffer[4] = 0xc3d2e1f0lu + e;
  return;
}

Something which I passed on sometime ago via PM, though some might not like it.
*^~·.,¸¸,.·´¯`·.,¸¸,.-·~^*ˆ¨¯¯¨ˆ*^~·.,l)ragon,.-·~^*ˆ¨¯¯¨ˆ*^~·.,¸¸,.·´¯`·.,¸¸,.-·~^*

Joe[x86]

BNCSutil helped greatly in writing my bot.

For key decoding, call kd_init and then kd_create(std::string key, int length).

For check revision, call checkRevision(std::string checksumForumla, std::string File1, std::string File2, std::string File3, std::string mpqNum, DWORD checksum). For checksum, pass a newly created DWORD, and thats where the result is stored.

For checkRevision, you need to call this function, which then calls the DLL. I trust you can port this from VB on your own.
Public Function checkRevision(ValueString As String, File1$, File2$, File3$, mpqNumber As Long, Checksum As Long) As Boolean
    checkRevision = (checkRevision_Raw(ValueString, File1, File2, File3, mpqNumber, Checksum) > 0)
End Function


NOTE -
C++ has the ability to create classes instead of using DLL calls. C and VB do not.
Quote from: brew on April 25, 2007, 07:33 PM
that made me feel like a total idiot. this entire thing was useless.