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) (http://bnetdocs.valhallalegends.com/content.php?Section=m&Code=4) 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. :(
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
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. :(
I think that you will find BNCSutil (http://bncsutil.ionws.com/) very helpful for your project. You should take a look at it. ^^
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 ;)
Don't post your cdkey!
Posting your cd-key is not a smart idea and that is the one you have to decode.
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. ;)
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.
BNCSutil (http://bncsutil.ionws.com/) 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.