www.pudn.com > boogiebot.zip > RealmListClient.Auth.cs


using System; 
using System.Collections.Generic; 
using System.Text; 
using System.IO; 
using Foole.Crypt; 
using Foole.WoW; 
 
namespace BoogieBot.Common 
{ 
    public partial class RealmListClient 
    { 
        private Srp6 srp;       // http://srp.stanford.edu/design.html  <- SRP6 information 
 
        private BigInteger A;   // My public key? 
        private BigInteger B;   // Server's public key 
        private BigInteger a;   // my random number, used to initalize A from g and N. 
        private byte[] I;       // Hash of "username:password" 
        private BigInteger M;   // Combination of... everything! 
        private byte[] M2;      // M2 is the combination of the server's everything to proof with ours (which we don't actually do, cause we trust blizzard, right?) 
 
 
        private byte[] N;       // Modulus for A and B 
        private byte[] g;       // base for A and B 
 
        private BigInteger Salt;    // Server provided salt 
        private byte[] crcsalt;     // Server provided crcsalt for file crc's. 
 
        public byte[] K;        // Our combined key used for encryption of all traffic 
 
        public void DoLogonChallenge() 
        { 
            wout.Write((byte)RLOp.AUTH_LOGON_CHALLENGE); 
            wout.Write((byte)3);                             // Used to be 2, now its 3. 
 
            wout.Write((UInt16)(30 + mUsername.Length));                                                        // Packet size + name length 
 
            wout.Write((byte)'W'); wout.Write((byte)'o'); wout.Write((byte)'W'); wout.Write((byte)'\0');        // WoW 
 
            wout.Write(BoogieCore.wowVersion.major); 
            wout.Write(BoogieCore.wowVersion.minor); 
            wout.Write(BoogieCore.wowVersion.update); 
            wout.Write(BoogieCore.wowVersion.build); 
 
            switch (BoogieCore.wowType) 
            { 
                case WoWType.OSXppc: 
                    wout.Write((byte)'C'); wout.Write((byte)'P'); wout.Write((byte)'P'); wout.Write((byte)'\0');     // CPP 
                    wout.Write((byte)'X'); wout.Write((byte)'S'); wout.Write((byte)'O'); wout.Write((byte)'\0');     // XSO 
                    break; 
                case WoWType.OSXx86: // NOT TESTED -- I don't have an intel mac. 
                    wout.Write((byte)'6'); wout.Write((byte)'8'); wout.Write((byte)'X'); wout.Write((byte)'\0');     // 68X 
                    wout.Write((byte)'X'); wout.Write((byte)'S'); wout.Write((byte)'O'); wout.Write((byte)'\0');     // XSO 
                    break; 
                case WoWType.Win32: 
                    wout.Write((byte)'6'); wout.Write((byte)'8'); wout.Write((byte)'x'); wout.Write((byte)'\0');     // 68x 
                    wout.Write((byte)'n'); wout.Write((byte)'i'); wout.Write((byte)'W'); wout.Write((byte)'\0');     // niW 
                    break; 
                default: 
                    throw new Exception();  // Shouldn't get here anyway. 
            } 
 
            wout.Write((byte)'S'); wout.Write((byte)'U'); wout.Write((byte)'n'); wout.Write((byte)'e');  // SUne 
 
            wout.Write(1); 
 
            wout.Write((byte)127); wout.Write((byte)0); wout.Write((byte)0); wout.Write((byte)1);       // Interestingly, mac sends IPs in reverse order. 
 
            wout.Write((byte)mUsername.Length); 
            wout.Write(Encoding.Default.GetBytes(mUsername)); // Name - NOT null terminated 
            wout.Flush(); 
        } 
 
        private bool HandleLogonChallenge() 
        { 
            byte op = win.ReadByte(); 
            byte unk = win.ReadByte(); 
 
            BoogieCore.Log(LogType.System, "Login Challenge: Response Type = {0}", unk); 
 
            byte error = win.ReadByte(); 
            if (error > 0) 
            { 
                BoogieCore.Log(LogType.System, "Login Challenge: Error = {0}", error); 
                return false; 
            } 
            B = new BigInteger(win.ReadBytes(32));               // Varies 
            byte glen = win.ReadByte();                          // Length = 1 
            g = win.ReadBytes(glen);                             // g = 7 
            byte Nlen = win.ReadByte();                          // Length = 32 
            N = win.ReadBytes(Nlen);                             // N = B79B3E2A87823CAB8F5EBFBF8EB10108535006298B5BADBD5B53E1895E644B89 
            Salt = new BigInteger(win.ReadBytes(32));            // Salt = 3516482AC96291B3C84B4FC204E65B623EFC2563C8B4E42AA454D93FCD1B56BA 
            crcsalt = win.ReadBytes(16);                         // Varies 
 
            srp = new Srp6(new BigInteger(N), new BigInteger(g)); 
 
            // A hack, yes. We just keep trying till we get an S thats not negative so we get rid of auth=4 error logging on. 
            BigInteger S; 
            do 
            { 
                a = BigInteger.Random(19 * 8); 
                A = srp.GetA(a); 
 
                I = Srp6.GetLogonHash(mUsername, mPassword); 
 
                BigInteger x = Srp6.Getx(Salt, I); 
                BigInteger u = Srp6.Getu(A, B); 
                S = srp.ClientGetS(a, B, x, u); 
            } 
            while (S < 0); 
 
            K = Srp6.ShaInterleave(S); 
            M = srp.GetM(mUsername, Salt, A, B, new BigInteger(K)); 
 
            unk = win.ReadByte(); 
 
            // BoogieCore.wardenClient.Initialize(K); // shame you don't have this class. 
 
            return true; 
        } 
 
        public void DoLogonProof() 
        { 
            Sha1Hash sha; 
            byte[] files_crc; 
            string[] crcfilenames; 
 
            switch (BoogieCore.wowType) 
            { 
                case WoWType.OSXppc: 
                case WoWType.OSXx86: 
                    crcfilenames = new string[] { 
                            "World of Warcraft.app/Contents/MacOS/World of Warcraft", 
                            "World of Warcraft.app/Contents/Info.plist", 
                            "World of Warcraft.app/Contents/Resources/Main.nib/objects.xib", 
                            "World of Warcraft.app/Contents/Resources/wow.icns", 
                            "World of Warcraft.app/Contents/PkgInfo" }; 
                    break; 
 
                case WoWType.Win32: 
                    crcfilenames = new string[] { "WoW.exe", "fmod.dll", "ijl15.dll", "dbghelp.dll", "unicows.dll" }; 
                    break; 
 
                default: 
                    throw new Exception(); 
            } 
 
            // Generate CRC/hashes of the Game Files 
            files_crc = GenerateCrc(crcsalt, crcfilenames); 
 
            // get crc_hash from files_crc 
            sha = new Sha1Hash(); 
            sha.Update(A); 
            sha.Update(files_crc); 
            byte[] crc_hash = sha.Final(); 
 
            wout.Write((byte)RLOp.AUTH_LOGON_PROOF); 
            wout.Write(A); // 32 bytes 
            wout.Write(M); // 20 bytes 
            wout.Write(crc_hash); // 20 bytes 
            wout.Write((byte)0); // number of keys 
            wout.Write((byte)0); // unk (1.11.x) 
            wout.Flush(); 
        } 
 
        private byte[] GenerateCrc(byte[] crcsalt, string[] crcfilenames) 
        { 
            Sha1Hash sha; 
 
            byte[] buffer1 = new byte[0x40]; 
            byte[] buffer2 = new byte[0x40]; 
 
            for (int i = 0; i < 0x40; ++i) 
            { 
                buffer1[i] = 0x36; 
                buffer2[i] = 0x5c; 
            } 
 
            for (int i = 0; i < crcsalt.Length; ++i) 
            { 
                buffer1[i] ^= crcsalt[i]; 
                buffer2[i] ^= crcsalt[i]; 
            } 
 
            sha = new Sha1Hash(); 
            sha.Update(buffer1); 
 
 
            foreach (string filename in crcfilenames) 
            { 
                try 
                { 
                    FileStream fs = new FileStream(BoogieCore.wowPath + filename, FileMode.Open, FileAccess.Read); 
                    byte[] Buffer = new byte[fs.Length]; 
                    fs.Read(Buffer, 0, (int)fs.Length); 
                    sha.Update(Buffer); 
                } 
                catch (Exception e) 
                { 
                    BoogieCore.Log(LogType.Error, e.Message); 
                } 
            } 
            byte[] hash1 = sha.Final(); 
 
            sha = new Sha1Hash(); 
            sha.Update(buffer2); 
            sha.Update(hash1); 
            return sha.Final(); 
        } 
 
        private bool HandleLogonProof() 
        { 
            byte op = win.ReadByte(); 
            byte error = win.ReadByte(); 
 
            if (error > 0) 
            { 
                BoogieCore.Log(LogType.System, "Login Proof: Error = {0}", error); 
                return false; 
            } 
 
            M2 = win.ReadBytes(20); 
            int unknown = win.ReadInt32(); 
            UInt16 unk2 = win.ReadUInt16(); 
 
            return true; 
        } 
    } 
}