Valhalla Legends Forums Archive | Battle.net Bot Development | "Server Token"

AuthorMessageTime
HydraPride
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.
June 22, 2003, 4:56 AM
Grok
It seems rather obvious, but I have to ask -- "Are you on a Token Ring Network?"
June 22, 2003, 10:19 AM
iago
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).
June 22, 2003, 2:09 PM
HydraPride
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.
June 22, 2003, 2:53 PM
HydraPride
Does the client token have to maintain any consistency with anything?
June 22, 2003, 3:10 PM
DarkMinion
[code]
      case SID_AUTH_INFO: //0x50
         {
            dwNLSRevision = *(unsigned long *)(pszData + 4);
            dwSessionKey = *(unsigned long *)(pszData + 8); //Server key
[/code]

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:

[code]
      case SID_OLD_SERVER_KEY: //0x1d
         dwSessionKey = *(unsigned long *)(pszData + 8); //Server key
         break;
[/code]

It is used for things like password and cdkey hashing....for example here are it's uses with the old logon and cdkey packets.

[code]
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);
}
[/code]

And...

[code]
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);
}
[/code]

Hope this helps...
June 22, 2003, 4:25 PM
HydraPride
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.
June 22, 2003, 4:45 PM
DarkMinion
Paste the code you're using?
June 22, 2003, 5:35 PM
HydraPride
[code]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.[/code]

Edit: use the code tag when pasting source.
June 22, 2003, 6:06 PM
c0ol
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.
June 22, 2003, 7:53 PM
Arta
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.
June 22, 2003, 7:57 PM
HydraPride
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.
June 22, 2003, 8:25 PM
iago
You have to figure out the hashing system that battle.net uses, preferably by reverse engineering. Hint: Check battle.snp ;-)
June 22, 2003, 11:10 PM
HydraPride
[code]
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;
}[/code]


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 =]
June 22, 2003, 11:29 PM
Zakath
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
June 22, 2003, 11:49 PM
HydraPride
Is there one included in mvc++?






Now, referring back to my question.. the code i posted... does that work?
June 22, 2003, 11:54 PM
iago
I don't know .. where did you get it from?
June 23, 2003, 9:01 AM
HydraPride
The code? That's from TheMinistered. I checked it next to prolix's code... it's basically the same.
June 23, 2003, 3:20 PM
iago
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 :)
June 24, 2003, 9:37 AM

Search