News:

Facebook killed the radio star. And by radio star, I mean the premise of distributed forums around the internet. And that got got by Instagram/SnapChat. And that got got by TikTok. Where the fuck is the internet we once knew?

Main Menu

SID_AUTH_INFO Signature

Started by Punk, May 25, 2009, 04:26:29 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Punk

I'm looking for some information on the 0x50 128-bit signature that battle.net includes at the end of the packet. I've done countless hours of trying to find documentation on this, but have found close to none. I talked this over with brew and we came to the conclusion that the signature is generated by the servers ipaddress in conjuction with powmod.

I'm relatively new to encryption so right now I'm stuck at a brick wall. I'm trying to write a gateway (in C or VB6, haven't decided yet) for Warcraft III. Unfortunately, in order to do this, I have to update the signature battle.net sends to the client, else wise, the Warcraft III client will pop an error informing me that the server I am trying to connect to doesn't appear to be a battle.net server.

So, ultimately, I need a way to generate the 128-bit signature.

iago

You can find an implementation somewhere on my wiki or, if nothing else, in JavaOp2. :)

<edit>
Quote
    // I don't really like this function being here, but I can't think of anywhere else it might belong :-/
    private void checkServerSignature(byte []sig, byte []ip) throws IOException
    {
        // The constants
        BigIntegerEx key = new BigIntegerEx(BigIntegerEx.LITTLE_ENDIAN, new byte[] { 0x01, 0x00, 0x01, 0x00 });
        BigIntegerEx mod = new BigIntegerEx(BigIntegerEx.LITTLE_ENDIAN, new byte[]
        {
                (byte) 0xD5, (byte) 0xA3, (byte) 0xD6, (byte) 0xAB, (byte) 0x0F, (byte) 0x0D, (byte) 0xC5, (byte) 0x0F, (byte) 0xC3, (byte) 0xFA, (byte) 0x6E, (byte) 0x78, (byte) 0x9D, (byte) 0x0B, (byte) 0xE3, (byte) 0x32,
                (byte) 0xB0, (byte) 0xFA, (byte) 0x20, (byte) 0xE8, (byte) 0x42, (byte) 0x19, (byte) 0xB4, (byte) 0xA1, (byte) 0x3A, (byte) 0x3B, (byte) 0xCD, (byte) 0x0E, (byte) 0x8F, (byte) 0xB5, (byte) 0x56, (byte) 0xB5,
                (byte) 0xDC, (byte) 0xE5, (byte) 0xC1, (byte) 0xFC, (byte) 0x2D, (byte) 0xBA, (byte) 0x56, (byte) 0x35, (byte) 0x29, (byte) 0x0F, (byte) 0x48, (byte) 0x0B, (byte) 0x15, (byte) 0x5A, (byte) 0x39, (byte) 0xFC,
                (byte) 0x88, (byte) 0x07, (byte) 0x43, (byte) 0x9E, (byte) 0xCB, (byte) 0xF3, (byte) 0xB8, (byte) 0x73, (byte) 0xC9, (byte) 0xE1, (byte) 0x77, (byte) 0xD5, (byte) 0xA1, (byte) 0x06, (byte) 0xA6, (byte) 0x20,
                (byte) 0xD0, (byte) 0x82, (byte) 0xC5, (byte) 0x2D, (byte) 0x4D, (byte) 0xD3, (byte) 0x25, (byte) 0xF4, (byte) 0xFD, (byte) 0x26, (byte) 0xFC, (byte) 0xE4, (byte) 0xC2, (byte) 0x00, (byte) 0xDD, (byte) 0x98,
                (byte) 0x2A, (byte) 0xF4, (byte) 0x3D, (byte) 0x5E, (byte) 0x08, (byte) 0x8A, (byte) 0xD3, (byte) 0x20, (byte) 0x41, (byte) 0x84, (byte) 0x32, (byte) 0x69, (byte) 0x8E, (byte) 0x8A, (byte) 0x34, (byte) 0x76,
                (byte) 0xEA, (byte) 0x16, (byte) 0x8E, (byte) 0x66, (byte) 0x40, (byte) 0xD9, (byte) 0x32, (byte) 0xB0, (byte) 0x2D, (byte) 0xF5, (byte) 0xBD, (byte) 0xE7, (byte) 0x57, (byte) 0x51, (byte) 0x78, (byte) 0x96,
                (byte) 0xC2, (byte) 0xED, (byte) 0x40, (byte) 0x41, (byte) 0xCC, (byte) 0x54, (byte) 0x9D, (byte) 0xFD, (byte) 0xB6, (byte) 0x8D, (byte) 0xC2, (byte) 0xBA, (byte) 0x7F, (byte) 0x69, (byte) 0x8D, (byte) 0xCF
        });
       
        // Do the calculation
        byte []result = new BigIntegerEx(BigIntegerEx.LITTLE_ENDIAN, sig).modPow(key, mod).toByteArray();
       
        // Create the array of the correct result
        byte []correctResult = new byte[result.length];
        // Put the ip into the array
        correctResult[0] = ip[0];
        correctResult[1] = ip[1];
        correctResult[2] = ip[2];
        correctResult[3] = ip[3];

        // Pad the result with 0xBB's
        for(int i = 4; i < correctResult.length; i++)
            correctResult = (byte) 0xBB;
       
        for(int i = 0; i < result.length; i++)
            if(result != correctResult)
                throw new IOException("Error! Server failed validation check!");
    }

Think you can figure it out from there?

MyndFyre

Quote from: Joe on January 23, 2011, 11:47:54 PM
I have a programming folder, and I have nothing of value there

Running with Code has a new home!

Quote from: Rule on May 26, 2009, 02:02:12 PMOur species really annoys me.

sdfg

Quote from: Punk on May 25, 2009, 04:26:29 PM
I talked this over with brew and we came to the conclusion that the signature is generated by the servers ipaddress in conjuction with powmod.

You must've misunderstood, it's not generated with powmod, it's checked with powmod :( i'm sure brew wouldn't say something dumb like that.

The signature is a 1024 byte number that, when raised to the power of 0x10001, modulus this big honkin' number, it comes out to another 1024 byte number where the first four bytes are the ip address of the server you'd like to connect to, and the rest are 0xBBs. Finding such a unique number takes a lot of effort unless you have Blizzard's algorithm to do this. This is somewhat similar to how Starcraft checks if a warden module is indeed from Blizzard, imagine the results if you connected to a pvpgn server that sent some arbitrary code to execute... =[
They're smart people. They've been in this business for a while, and it really is not as simple as you and everyone else in this thread makes it seem (they've implemented the code to check the signature, not to generate one, since that's the entire point behind this security).
dey see me trollin'
dey hatin'

Punk

#4
Thanks for the help though guys. I guess I'll leave this one be.

Btw, when I said
I talked this over with brew and we came to the conclusion that the signature is generated by the servers ipaddress in conjuction with powmod.

I didn't say it was used to create the encryption, I meant that powmod was related to its enc / decrpy somehow. But yeah, I understand now. Thanks for clearing that up :-P

iago

Aha, I just noticed that you asked how to generate the signature, not how to verify it -- the easy answer is, it's impossible. :)

The long answer is, you have to hack Blizzard or something if you want it.

Camel

#6
Quote from: iago on May 26, 2009, 12:10:01 PMthe easy answer is, it's impossible. :)
Tut-tut, iago! It's impossible just because the public key is 1024 bits? Brute forcing the key would be trivial! Never mind how many lifetimes it would take...

[edit] Out of curiosity, does the official client allow any way to bypass this check?

<Camel> i said what what
<Blaze> in the butt
<Camel> you want to do it in my butt?
<Blaze> in my butt
<Camel> let's do it in the butt
<Blaze> Okay!

iago

Quote from: Camel on May 26, 2009, 02:06:32 PM
Quote from: iago on May 26, 2009, 12:10:01 PMthe easy answer is, it's impossible. :)
Tut-tut, iago! It's impossible just because the public key is 1024 bits? Brute forcing the key would be trivial! Never mind how many lifetimes it would take...

[edit] Out of curiosity, does the official client allow any way to bypass this check?
Not anymore. Original versions of War3 worked fine if you just didn't include the check (or maybe if you 00'ed it out, I forget now). But they fixed that loophole.

Punk

Brew gave me a good idea. What if you temporarily changed the subroutine that verifies the address to always return a pos value then change it back after 0x51?

iago

If you mean modify the client, that's certainly possible -- you can easily modify the client to always accept a server signature.

Camel

bool verifyItIsBlizzard() {
    return YES_IT_IS;
}

<Camel> i said what what
<Blaze> in the butt
<Camel> you want to do it in my butt?
<Blaze> in my butt
<Camel> let's do it in the butt
<Blaze> Okay!

Punk

Quote from: Camel on May 26, 2009, 09:22:46 PM
bool verifyItIsBlizzard() {
    return YES_IT_IS;
}


I wish it where that easy :-P

sdfg

Quote from: Punk on May 26, 2009, 06:58:48 PM
Brew gave me a good idea. What if you temporarily changed the subroutine that verifies the address to always return a pos value then change it back after 0x51?

Quote from: Camel on May 26, 2009, 09:22:46 PM
bool verifyItIsBlizzard() {
    return YES_IT_IS;
}


Yup!
It's 7 bytes, all you need to do is find out where to put them!
dey see me trollin'
dey hatin'

Joe

Quote from: iago on May 26, 2009, 12:10:01 PM
Aha, I just noticed that you asked how to generate the signature, not how to verify it -- the easy answer is, it's impossible. :)

The long answer is, you have to hack Blizzard or something if you want it.


Well, it's 128 characters. That means that there's only 10^128 different possibilities. It shouldn't take more than a few hours to generate the one for your IP.

And since it's mod, I think there may be more than one correct number.
Quote from: Camel on June 09, 2009, 04:12:23 PMI'd personally do as Joe suggests

Quote from: AntiVirus on October 19, 2010, 02:36:52 PM
You might be right about that, Joe.


Hdx

Quote from: Joe on May 29, 2009, 05:00:47 AM
Quote from: iago on May 26, 2009, 12:10:01 PM
Aha, I just noticed that you asked how to generate the signature, not how to verify it -- the easy answer is, it's impossible. :)

The long answer is, you have to hack Blizzard or something if you want it.


Well, it's 128 characters. That means that there's only 255^128 different possibilities. It shouldn't take more than a few hours decades to generate the one for your IP.

And since it's mod, I think there may be more than one correct number.
neh?
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.