Author Topic: SID_AUTH_INFO Signature  (Read 14386 times)

0 Members and 1 Guest are viewing this topic.

Offline Punk

  • Newbie
  • *
  • Posts: 21
    • View Profile
SID_AUTH_INFO Signature
« on: May 25, 2009, 04:26:29 pm »
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.

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: SID_AUTH_INFO Signature
« Reply #1 on: May 25, 2009, 04:42:43 pm »
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?

Offline MyndFyre

  • Boticulator Extraordinaire
  • x86
  • Hero Member
  • *****
  • Posts: 4540
  • The wait is over.
    • View Profile
    • JinxBot :: the evolution in boticulation
Re: SID_AUTH_INFO Signature
« Reply #2 on: May 26, 2009, 02:55:46 am »
I also have it implemented in C#: http://code.google.com/p/jinxbot/source/browse/trunk/development/projects/BNSharp/MBNCSUtil/NLS.cs (line 399).

Skywing authored an article that discussed this briefly: http://uninformed.org/index.cgi?v=2&a=1&p=17
I have a programming folder, and I have nothing of value there

Running with Code has a new home!

Our species really annoys me.

Offline sdfg

  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: SID_AUTH_INFO Signature
« Reply #3 on: May 26, 2009, 07:54:13 am »
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'

Offline Punk

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: SID_AUTH_INFO Signature
« Reply #4 on: May 26, 2009, 11:43:05 am »
Thanks for the help though guys. I guess I'll leave this one be.

Btw, when I said
Code: [Select]
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
« Last Edit: May 26, 2009, 11:47:09 am by Punk »

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: SID_AUTH_INFO Signature
« Reply #5 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.

Offline Camel

  • Hero Member
  • *****
  • Posts: 1703
    • View Profile
    • BNU Bot
Re: SID_AUTH_INFO Signature
« Reply #6 on: May 26, 2009, 02:06:32 pm »
the 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?
« Last Edit: May 26, 2009, 02:08:30 pm by Camel »

<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!

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: SID_AUTH_INFO Signature
« Reply #7 on: May 26, 2009, 05:20:50 pm »
the 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.

Offline Punk

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: SID_AUTH_INFO Signature
« Reply #8 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?

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: SID_AUTH_INFO Signature
« Reply #9 on: May 26, 2009, 07:53:58 pm »
If you mean modify the client, that's certainly possible -- you can easily modify the client to always accept a server signature.

Offline Camel

  • Hero Member
  • *****
  • Posts: 1703
    • View Profile
    • BNU Bot
Re: SID_AUTH_INFO Signature
« Reply #10 on: May 26, 2009, 09:22:46 pm »
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!

Offline Punk

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: SID_AUTH_INFO Signature
« Reply #11 on: May 27, 2009, 04:49:15 pm »
bool verifyItIsBlizzard() {
    return YES_IT_IS;
}


I wish it where that easy :-P

Offline sdfg

  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: SID_AUTH_INFO Signature
« Reply #12 on: May 28, 2009, 12:15:37 am »
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?

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'

Offline Joe

  • B&
  • Moderator
  • Hero Member
  • *****
  • Posts: 10319
  • In Soviet Russia, text read you!
    • View Profile
    • Github
Re: SID_AUTH_INFO Signature
« Reply #13 on: May 29, 2009, 05:00:47 am »
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.
I'd personally do as Joe suggests

You might be right about that, Joe.


Offline Hdx

  • The Hdx!
  • Full Member
  • ***
  • Posts: 311
  • <3 Java/Cpp/VB/QB
    • View Profile
Re: SID_AUTH_INFO Signature
« Reply #14 on: May 29, 2009, 09:29:17 am »
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.

Offline Camel

  • Hero Member
  • *****
  • Posts: 1703
    • View Profile
    • BNU Bot
Re: SID_AUTH_INFO Signature
« Reply #15 on: May 29, 2009, 12:00:01 pm »
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.
No. Just no.

It's 8^128, actually. That would take an astronomically long time to guess. Assuming you have a 2GHz processor, and you could generate and test a key in a single cycle, google calculator says:
Quote
8^128 / 2GHz in years = 6.2430045 × 1098 years

Without the private key, there's no point trying to generate one.
« Last Edit: May 29, 2009, 12:08:28 pm by Camel »

<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!

Offline sdfg

  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: SID_AUTH_INFO Signature
« Reply #16 on: May 29, 2009, 04:54:24 pm »
Correct me if i'm wrong, but using the birthday attack principle couldn't you get that down to 8^64?
dey see me trollin'
dey hatin'

Offline iago

  • Leader
  • Administrator
  • Hero Member
  • *****
  • Posts: 17914
  • Fnord.
    • View Profile
    • SkullSecurity
Re: SID_AUTH_INFO Signature
« Reply #17 on: May 29, 2009, 05:32:59 pm »
Correct me if i'm wrong, but using the birthday attack principle couldn't you get that down to 8^64?
No, I don't think the birthday attack applies here, since you can't get them to encrypt arbitrary plaintext. Or something. :)

Offline Joe

  • B&
  • Moderator
  • Hero Member
  • *****
  • Posts: 10319
  • In Soviet Russia, text read you!
    • View Profile
    • Github
Re: SID_AUTH_INFO Signature
« Reply #18 on: May 29, 2009, 07:08:13 pm »
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();
       
        for(int i = 0; i < 4; i++)
            if(result[i] != ip[i])
                throw new IOException("Error! Server failed validation check!");

        for(int i = 4; i < result.length; i++)
            if(result[i] != (byte) 0xBB)
                throw new IOException("Error! Server failed validation check!");

    }


Think you can figure it out from there?


Fixed?
« Last Edit: May 29, 2009, 07:11:12 pm by Joe »
I'd personally do as Joe suggests

You might be right about that, Joe.


Offline Camel

  • Hero Member
  • *****
  • Posts: 1703
    • View Profile
    • BNU Bot
Re: SID_AUTH_INFO Signature
« Reply #19 on: May 30, 2009, 03:08:27 am »
Correct me if i'm wrong, but using the birthday attack principle couldn't you get that down to 8^64?
The birthday attack principle is based on the idea that hashing sqrt(hash strength) variations of each of two different inputs will (probably) result in a hash collision. A classic example is getting a digital signature on an evil message by requesting a signature on sqrt(strength) variants of an innocent message, and then testing each of those signatures for collision with sqrt(strength) variants of an evil message.

There are still O(strength) comparisons, simply fewer hashes.

I don't think the birthday attack applies here, since you can't get them to encrypt arbitrary plaintext. Or something. :)
The reason iago gave is sufficient to preclude the possibility of performing a birthday attack, but there's an even better reason: what the client expects to see is that the hash itself matches the IP address, not the message. The very nature of the birthday attack is finding hashing collisions, but the hash is invariant.
« Last Edit: May 30, 2009, 03:13:18 am by Camel »

<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!