Author Topic: Logging to BNet in c/c++  (Read 13102 times)

0 Members and 4 Guests are viewing this topic.

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Logging to BNet in c/c++
« on: April 13, 2007, 12:19:06 pm »
Hey, its my first post here.

I am trying to write program that would log to bnet as Diablo II client (and sit in a game for two hours which is rather boring, but its not important now), and ,of course, I've spotted some problems.
Before you redirect me, I already found these docs mirrored here. It helped me a lot with login sequence, but there is nothing about "A=A.S" etc strings in packet from bnet. I've found some functions reffering to these strings in javaop source, but I don't understand them. Here is my question: does any of you know any tutorial about this? Or, is any of you willing to tell me what should I do to connect to bnet? Please, don't tell me to use BNLS, its slow and require sending cdkeys as plain text.

It would be also nice if you could show algorithm in pseudocode/c/c++ in easy format ;)

PS:  sorry for my english.
« Last Edit: April 13, 2007, 12:21:11 pm by KrzaQ »

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: Logging to BNet in c/c++
« Reply #1 on: April 13, 2007, 01:18:22 pm »
The actual stuff you're talking about is CheckRevision. It's recently been changed on older games (Starcraft and Warcraft 2), but I believe Diablo 2 is still the older version.

The code in CheckRevision.java would be a good place to start, or search for other implementations of CheckRevision, I know there's a few.

Good luck!

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #2 on: April 14, 2007, 07:56:11 am »
I really hope its not a stupid question. I've tried to understand how this algorithm works and i think I'm close to, but I don't know where do you get
Code: [Select]
String[] files, int mpqNum from.
 (in CheckRevision.java)

Thanks in advance.

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: Logging to BNet in c/c++
« Reply #3 on: April 14, 2007, 09:55:07 am »
Each game has three important files that are used. Starcraft uses Starcraft.exe, Storm.dll, and Battle.snp. Diablo 2, I believe, uses Diablo2.exe, storm.dll, and bnclient.dll. But I don't remember which order they're in, and I'm not positive that those are the right ones, there should be a file called Diablo2.java somewhere that lists them.

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #4 on: April 14, 2007, 11:43:30 am »
Code: [Select]
        games.getWrite("D2XP", "File1", prefix + "D2XP/Game.exe");
        games.getWrite("D2XP", "File2", prefix + "D2XP/Bnclient.dll");
        games.getWrite("D2XP", "File3", prefix + "D2XP/D2Client.dll");
I guess these are files you meant.  (found here)

If so, Check.Revision.javas "files.length" is always 3 (for now, at least) and, for Diablo2
Code: [Select]
string files[] = "D2XP/Game.exe" "D2XP/Bnclient.dll" "D2XP/D2Client.dll"; is exactly what I need.

Alsio, I am not sire what is "String versionString" needed in CheckRevision function. Is it "D2XP" or version hash or...

Its first time I am doing something that big and complicated, if there was no Open Source bnet bot I would probably give up.

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: Logging to BNet in c/c++
« Reply #5 on: April 14, 2007, 11:57:47 am »
Yeah, those are the three files you need, and everything else is in the CheckRevision() function. The algorithm isn't really that complicated, once you understand it.

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #6 on: April 14, 2007, 12:49:18 pm »
I hope its ok right now:

Code: [Select]
public static int checkRevision(String versionString, String[] files, int mpqNum) throws FileNotFoundException, IOException
Thats string i got by logging today in the morning.
[some non writable chars before]ver-IX86-3.mpqC=3463600698 B=817405548 A=2386379605 4 A=A^S B=B-C C=C+A A=A^B

Just tell me if am I right:
versionString = C=3463600698 B=817405548 A=2386379605 4 A=A^S B=B-C C=C+A A=A^B;
files = these 3 i mentioned before
mpqNum = 3; <-- ?

thanks alot!

edit:

I also don't know what exactly is done here:
Code: [Select]
            File currentFile = new File(files[i]);
            int roundedSize = (int)((currentFile.length() / 1024) * 1024);

            MappedByteBuffer fileData = new FileInputStream(currentFile).getChannel().map(FileChannel.MapMode.READ_ONLY, 0, roundedSize);
            fileData.order(ByteOrder.LITTLE_ENDIAN);
and how to write it in c/cpp.

I guess (oh, theres nothing to guess, its too simple) first two lines give me rounded file size in kB but I don't have a clue whats done in lines #3 and #4 :/
« Last Edit: April 14, 2007, 01:13:08 pm by KrzaQ »

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: Logging to BNet in c/c++
« Reply #7 on: April 14, 2007, 06:41:56 pm »
The last two lines set up the file to be used like an array. It's not necessary, it's an optimization. You should be able to figure out how it works without those lines.

And yes, you have those values right.

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #8 on: April 15, 2007, 03:04:51 am »
I have found some info here and here, it tells me nothing tho.

Would this arrat look so:
Code: [Select]
[type] filedata[roundedsize*1024] = load this_file;
Then, changing byteorder to Little Endian seems to be quite important.

and, I hope last question for this algorithm:
Code: [Select]
int s = fileData.getInt(j);Does it just get  4 bits value as int? (and if byte order is reverted, its getting values from last to first, yep?)

edit:
Code: [Select]
        crCache.put(versionString + mpqNum + files[0], new Integer(c));
       
        return c;
Whats returned?
« Last Edit: April 15, 2007, 05:58:48 am by KrzaQ »

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: Logging to BNet in c/c++
« Reply #9 on: April 15, 2007, 11:08:11 am »
Don't worry about crCache, it's useless.

The variable "c" is returned. Duh?

All it's doing is looping through the three files, and putting each byte of the file into the "s" variable, and doing mathematical operations on a, b, c, and s.

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #10 on: April 16, 2007, 12:26:35 pm »
I think i have my code almost done, but I am not sure.
could you tell me proper "c" value for this string received:
Code: [Select]
ver-IX86-3.mpqC=3463600698 B=817405548 A=2386379605 4 A=A^S B=B-C C=C+A A=A^B
I hoped its not that complicated :/

If proper result is sent as 0x51 response then my code is wrong :/

(my code returned 0x87 84 9E 77 22 3C 4D 7A )

edit:
after few modifications (some stpid bugs) my code returns 28 9D 9D EB 82 CA E1 54
« Last Edit: April 16, 2007, 03:20:24 pm by KrzaQ »

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: Logging to BNet in c/c++
« Reply #11 on: April 16, 2007, 04:03:25 pm »
I don't have code handy that can do it. If anybody else wants to field, I'd appreciate it.

Offline Hdx

  • The Hdx!
  • Full Member
  • ***
  • Posts: 311
  • <3 Java/Cpp/VB/QB
    • View Profile
Re: Logging to BNet in c/c++
« Reply #12 on: April 17, 2007, 07:12:27 pm »
Version 1: 0x0faf5346
Version 2: 0x0faf5346
Yay for no padding needed :P
~Hdx
http://img140.exs.cx/img140/6720/hdxnew6lb.gif
09/08/05 - Clan SBs @ USEast
 [19:59:04.000] <DeadHelp> We don't like customers.
 [19:59:05.922] <DeadHelp> They're assholes
 [19:59:08.094] <DeadHelp> And they're never right.

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #13 on: April 20, 2007, 03:45:33 pm »
Version 1: 0x0faf5346
Version 2: 0x0faf5346
Yay for no padding needed :P
~Hdx
If thats right (and I suppose it is) my code doesn't work :/

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #14 on: April 21, 2007, 02:27:30 pm »
I have some questions:

Code: [Select]
fileData.order(ByteOrder.LITTLE_ENDIAN);Does whole code get reverted? Or just partially?
Lets say I have file with "ABCDEFGH" data (  0x 41424344 45464748 )
What do I receive after conversion?
Maybe:
"HGFEDCBA" or "DCBAHGFE" or "BADCFEHG" ?

Also, the code seems to be wrong in one part:
Code: [Select]
     * weird version strings that Battle.net would never send.  Battle.net's version strings are _always_ in the form:
     * A=x B=y C=z 4 A=A?S B=B?C C=C?A A=A?B:

Actually bnet is sending e=x f=y g=z 4 A=A?S B=B?C C=C?A A=A?B where e f g are A B C in random order.
Which value do i hash? Which one do i return?

Offline Sidoh

  • x86
  • Hero Member
  • *****
  • Posts: 17634
  • MHNATY ~~~~~
    • View Profile
    • sidoh
Re: Logging to BNet in c/c++
« Reply #15 on: April 21, 2007, 02:33:55 pm »

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #16 on: April 21, 2007, 02:41:44 pm »
http://en.wikipedia.org/wiki/Endianness
I have already checked Wiki, but I don't know how will it change file

 - I don't know the "element size")


I guess the question about A B and C order in 0x50 packet is more significant :/


BREAKING NEWS!
I got Check revision to work properly, probably when i make source more clear I'll post it here.
« Last Edit: April 21, 2007, 03:40:34 pm by KrzaQ »

Offline Hdx

  • The Hdx!
  • Full Member
  • ***
  • Posts: 311
  • <3 Java/Cpp/VB/QB
    • View Profile
Re: Logging to BNet in c/c++
« Reply #17 on: April 21, 2007, 11:14:11 pm »
Just read the file fount to end IIRC.
As for The order of A/B/C
Doesn't matter. Just do it in the order they send you.
Code: [Select]
        for(int x = 0; x<3; x++){
          String seed = tok.nextToken();
          if(seed.toLowerCase().startsWith("a=") == true) a = Long.parseLong(seed.substring(2));
          if(seed.toLowerCase().startsWith("b=") == true) b = Long.parseLong(seed.substring(2));
          if(seed.toLowerCase().startsWith("c=") == true) c = Long.parseLong(seed.substring(2));
        }
Just do something like that.
~Hdx
« Last Edit: April 21, 2007, 11:31:41 pm by HdxBmx27 »
http://img140.exs.cx/img140/6720/hdxnew6lb.gif
09/08/05 - Clan SBs @ USEast
 [19:59:04.000] <DeadHelp> We don't like customers.
 [19:59:05.922] <DeadHelp> They're assholes
 [19:59:08.094] <DeadHelp> And they're never right.

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #18 on: April 22, 2007, 12:30:02 pm »
Just read the file fount to end IIRC.
As for The order of A/B/C
Doesn't matter. Just do it in the order they send you.
Code: [Select]
        for(int x = 0; x<3; x++){
          String seed = tok.nextToken();
          if(seed.toLowerCase().startsWith("a=") == true) a = Long.parseLong(seed.substring(2));
          if(seed.toLowerCase().startsWith("b=") == true) b = Long.parseLong(seed.substring(2));
          if(seed.toLowerCase().startsWith("c=") == true) c = Long.parseLong(seed.substring(2));
        }
Just do something like that.
~Hdx

Thank you, I have already managed to get check revision to work.

What I need now is to understand cdkey encoding, I hope this is right source to start.

Offline Hdx

  • The Hdx!
  • Full Member
  • ***
  • Posts: 311
  • <3 Java/Cpp/VB/QB
    • View Profile
Re: Logging to BNet in c/c++
« Reply #19 on: April 22, 2007, 12:42:08 pm »
http://jbls.org/Downloads/JBLS.jar
Open that up, it has all the spiffy functions that you need.
For something like thats your only choices are to look at other's sources or reverse it yourself :P
~Hdx
http://img140.exs.cx/img140/6720/hdxnew6lb.gif
09/08/05 - Clan SBs @ USEast
 [19:59:04.000] <DeadHelp> We don't like customers.
 [19:59:05.922] <DeadHelp> They're assholes
 [19:59:08.094] <DeadHelp> And they're never right.

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: Logging to BNet in c/c++
« Reply #20 on: April 22, 2007, 12:55:47 pm »
What I need now is to understand cdkey encoding, I hope this is right source to start.
It's typically called "Decoding" for some reason. And that's one for Starcraft, but if you want to do D2 look for one called AlphaKeyDecode or something similar.


Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #21 on: April 22, 2007, 02:08:35 pm »
I meant AlphaKeyDecode, just pasted link from wrong tab in browser.

I guess I should hash each key with algorithm used there, but again I can't understand whats returned. hash() doesn't get any variables, and returns none.

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: Logging to BNet in c/c++
« Reply #22 on: April 22, 2007, 02:14:50 pm »
It uses and sets class variables. Just look at what it uses, everything should be fairly common sense. For example, "cdkey" is the cdkey.

Offline KrzaQ

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Logging to BNet in c/c++
« Reply #23 on: April 23, 2007, 08:24:13 am »
Funny example ;)

I guess it should return keyarray, so I tried to port it to c and make it return keyarray.

For now I would need some confirmation again.
For cdkey 8VP8H276GG6ZNTTJ keyarray i receive is 06419C125496D5A0
Is it proper?

PS: the cdkey is banned.

Edit:
I guess its proper, since all decoded cdkeys start with 06 for me.

Edit 2:
Code: [Select]
    public int[] getKeyHash(int clientToken, int serverToken)

    {

       

        Buffer hashData = new Buffer();

       

        hashData.addDWord(clientToken);

        hashData.addDWord(serverToken);

        hashData.addDWord(getProduct());

        hashData.addDWord(getVal1());

        hashData.addDWord(0);

        hashData.addDWord(getVal2());

       

        return BrokenSHA1.calcHashBuffer(hashData.getBuffer());

    }

This function sends 6 DWords to calcHashBuffer, but it only needs 5. Or am I wrong?
« Last Edit: April 23, 2007, 04:55:00 pm by KrzaQ »