The question:
WHAT IS THE SERVER TOKEN?
It's simple. How do I find it? Nobody seems to want to tell me how to find the server token. Rather, they just talk about other things when I try and get real information out of them. It's not like I haven't tried to find it; believe me, I have. Now I'm looking for answers.
It seems rather obvious, but I have to ask -- "Are you on a Token Ring Network?"
Go to bnetdocs and search for it.
What you'll find out is that it's a random-ish dword sent to you from battle.net in the packet s->SID_AUTH_INFO (0x50).
Hmm.. thanks iago.. but that's what I've been using in my program and I still get 0x101 from packet 0x51S->C. everything else is correct, it seems. I just dont get it.
Does the client token have to maintain any consistency with anything?
case SID_AUTH_INFO: //0x50
{
dwNLSRevision = *(unsigned long *)(pszData + 4);
dwSessionKey = *(unsigned long *)(pszData + 8); //Server key
As you can see it is the second DWORD in 0x50. If you are using Warcraft II then it would be the second DWORD in packet 0x1d:
case SID_OLD_SERVER_KEY: //0x1d
dwSessionKey = *(unsigned long *)(pszData + 8); //Server key
break;
It is used for things like password and cdkey hashing....for example here are it's uses with the old logon and cdkey packets.
void SendOLSPassword(char *szAccount, char *szPassword, unsigned long dwSessionKey)
{
unsigned long dwPasswordHash[7];
dwPasswordHash[0] = GetTickCount();
dwPasswordHash[1] = dwSessionKey;
calchashbuf(dwPasswordHash + 2, (char *)szPassword, strlen(szPassword));
calchashbuf(dwPasswordHash + 2, dwPasswordHash, 7 * sizeof(unsigned long));
dBuf.add(dwPasswordHash, 7 * sizeof(unsigned long));
dBuf.add(szAccount);
SendPacket(SID_OLS_PASSWORD);
}
And...
void SendOldCDKey(char *szCDKey, unsigned long dwSessionKey)
{
unsigned long dwProductId, dwValue1, dwValue2, dwClientKey;
dwClientKey = GetTickCount();
DecodeCDKey(szCDKey, &dwProductId, &dwValue1, &dwValue2);
dBuf.add((int)0);
dBuf.add((int)strlen(szCDKey));
dBuf.add(dwProductId);
dBuf.add(dwValue1);
dBuf.add(dwSessionKey);
dBuf.add(dwClientKey);
unsigned long dwHash[5], dwHash2[5];
dwHash[0] = dwClientKey;
dwHash[1] = dwSessionKey;
dwHash[2] = dwProductId;
dwHash[3] = dwValue1;
dwHash[4] = dwValue2;
calchashbuf(dwHash2, dwHash, 20);
dBuf.add(dwHash2, 20);
dBuf.add("DMBot");
SendPacket(SID_OLD_CDKEY);
}
Hope this helps...
That does help , but I already had my answer. Now I'm still trying to figure out what the m'f is wrong with this. everything seems right, but I dont know about the hash data that I send. Maybe that's incorrect. Is there a new hashing function I should be aware of? Currently, I'm using something like prolix's.
Paste the code you're using?
DWORD numKeys = 0x00000001;
DWORD bSpawn = 0x00000000;
DWORD dwProgram = 0x00000001;
DWORD dwKeyLen = 0x0000000d;
DWORD dwKeyVal1 = b; // b is the "value 1" from decode.
// this value is correct.
DWORD dwBlank = 0x00000000;
DWORD dwClient = GetTickCount();
// CALC HASH -- >
DWORD hashbuf[6], hash[5];
// set up hash buffer
hashbuf [ 0 ] = dwClient; // there's a space here because the forum is weird
// doesnt accept some things
hashbuf[1] = dwServerToken;
hashbuf[2] = a; // program id, the first return val
hashbuf[3] = b; // val 1
hashbuf[4] = 0; // 0
hashbuf[5] = c; // val 2
sha1_hash((char*)hashbuf, 24, (char*)hash);
// END CALC HASH
// Setup for packet 0x51
char newDP[120];
dwBP *bpToken=new dwBP(NULL), *bpVersion=new dwBP(NULL), *bpChecksum=new dwBP(NULL), *bpNumKeys=new dwBP(NULL), *bpSpawn=new dwBP(NULL), *bpKeyLen=new dwBP(NULL), *bpProduct=new dwBP(NULL), *bpKeyVal1=new dwBP(NULL), *bpBlank=new dwBP(NULL), *bpHash[5];
for(int k=0; k<5; k++)
bpHash[k]=new dwBP(NULL);
bpToken->SetNewBitsValue((DWORD)dwClient);
bpVersion->SetNewBitsValue((DWORD)lpdwVersion);
bpChecksum->SetNewBitsValue((DWORD)lpdwChecksum);
bpNumKeys->SetNewBitsValue((DWORD)numKeys);
bpSpawn->SetNewBitsValue((DWORD)bSpawn);
bpKeyLen->SetNewBitsValue((DWORD)dwKeyLen);
bpProduct->SetNewBitsValue((DWORD)dwProgram);
bpKeyVal1->SetNewBitsValue((DWORD)dwKeyVal1);
bpBlank->SetNewBitsValue((DWORD)dwBlank);
// I do stuff a little bit differently, and it's just an interim code
// snippet that i put together for the packets.
// I do set up packet 0x51 correctly... I've verified that.
Edit: use the code tag when pasting source.
i dont totally understand ur packet buffer system, but assuming it works, is sha1_hash a normal sha1 hashing function, or one that works on bnet. Bnet uses a non standard sha1 hashing function.
Are you using the correct hashing function? Battle.net doesn't use standard sha-1, they modified it.
Are you using the same Client Token in each packet that contains Client Token (hashed or otherwise)? This value should be the same every time you use it.
What is 'dwBP'? Whatever you're doing looks very strange. I hope you're freeing all that memory at some point.
First, I am freeing the memory so dont worry.
=P
Second, Where can I get documentation on a hashing function that works? I'm using prolix's style hash right now.
Third, the client token does remain the same.
dwBP as I said is just some temporary thing until i get going
I just put it together in about 1 second.
I'd appreciate a link to some sort of proper hashing function. Thanks.
You have to figure out the hashing system that battle.net uses, preferably by reverse engineering. Hint: Check battle.snp ;-)
void sha1_hash(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 * 1); i++)
{
g = lpdwBuffer[i] + ROL(a,5) + e + ((b & c) | (~b & d)) + 0x5a827999lu;
e = d;
d = c;
c = ROL(b,30);
b = a;
a = g;
}
for (; i < (20 * 2); i++)
{
g = (d ^ c ^ b) + e + ROL(g,5) + lpdwBuffer[i] + 0x6ed9eba1lu;
e = d;
d = c;
c = ROL(b,30);
b = a;
a = g;
}
for (; i < (20 * 3); i++)
{
g = lpdwBuffer[i] + ROL(g,5) + e + ((c & b) | (d & c) | (d & b)) -
0x70e44324lu;
e = d;
d = c;
c = ROL(b,30);
b = a;
a = g;
}
for (; i < (20 * 4); i++)
{
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;
}
Above is the hashing function I use.
I had a different one, but I switched it with something I found on this board, and it still returns the same failure.
This makes me sad. I cannot open the file battle.snp, for it is too large for my windows to load. Wordpad, or whatever text program I use, locks up when I load the file. Lol
This is crap!!!
can anyone help me more specifically? pretty please =]
It wouldn't do you a ton of good to open it in a text editor. You really need to open it in a disassembler :P
Is there one included in mvc++?
Now, referring back to my question.. the code i posted... does that work?
I don't know .. where did you get it from?
The code? That's from TheMinistered. I checked it next to prolix's code... it's basically the same.
The hashing that battle.net binary bots use is non-standard. It doesn't conform exactly to any other algorithm you'll find online or elsewhere, except for that exact purpose. But if TheMinistered says it's right, it probably is.
Get a packet sniffer, and find the server/client token/cd-keyval1/2 and hash it with your function, and check if it's the same as the right hash. If not, you know there must be a problem :)