diff --git a/src/Launcher.cs b/src/Launcher.cs index a3f1e24..53839c4 100644 --- a/src/Launcher.cs +++ b/src/Launcher.cs @@ -53,7 +53,7 @@ class Launcher gameBinaryPath = $"{gameFolder}/{BinaryName}"; } - if (!File.Exists(gameBinaryPath) || GetVersionValueFromClient(gameBinaryPath, 3) != MajorGameVersion) + if (!File.Exists(gameBinaryPath) || GetVersionValueFromClient(gameBinaryPath).Major != MajorGameVersion) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"[Error] No {gameVersion} client found."); @@ -61,7 +61,7 @@ class Launcher return String.Empty; } - var gameClientBuild = GetVersionValueFromClient(gameBinaryPath, 0); + var gameClientBuild = GetVersionValueFromClient(gameBinaryPath).Build; if (gameClientBuild < MinGameBuild && gameClientBuild != 0) { @@ -128,8 +128,8 @@ class Launcher byte[] certBundleData = Convert.FromBase64String(Patches.Common.CertBundleData); // Build the version URL from the game binary build. - int wowBuild = GetVersionValueFromClient(appPath, 0); - byte[] versionPatch = Patches.Common.GetVersionUrl(wowBuild); + var clientVersion = GetVersionValueFromClient(appPath); + byte[] versionPatch = Patches.Common.GetVersionUrl(clientVersion.Build); // Refresh the client data before patching. memory.RefreshMemoryData((int)gameAppData.Length); @@ -138,9 +138,14 @@ class Launcher Task.WaitAll(new[] { memory.PatchMemory(Patterns.Common.CertBundle, certBundleData, "Certificate Bundle"), - memory.PatchMemory(Patterns.Common.SignatureModulus, Patches.Common.SignatureModulus, "Certificate Signature Modulus"), - memory.PatchMemory(Patterns.Common.ConnectToModulus, Patches.Common.Modulus, "ConnectTo Modulus"), - memory.PatchMemory(Patterns.Common.ChangeProtocolModulus, Patches.Common.Modulus, "ChangeProtocol (GameCrypt) Modulus"), + memory.PatchMemory(Patterns.Common.SignatureModulus, Patches.Common.SignatureModulus, "Certificate Signature RsaModulus"), + memory.PatchMemory(Patterns.Common.ConnectToModulus, Patches.Common.RsaModulus, "ConnectTo RsaModulus"), + + // Recent clients have a different signing algorithm in EnterEncryptedMode. + (clientVersion is (9, 2, 7, _) or (3, _, _, _) or (10, _, _, _)) + ? memory.PatchMemory(Patterns.Common.CryptoEdPublicKey, Patches.Common.CryptoEdPublicKey, "GameCrypto Ed25519 PublicKey") + : memory.PatchMemory(Patterns.Common.CryptoRsaModulus, Patches.Common.RsaModulus, "GameCrypto RsaModulus"), + memory.PatchMemory(Patterns.Common.Portal, Patches.Common.Portal, "Login Portal"), memory.PatchMemory(Patterns.Common.VersionUrl, versionPatch, "Version URL"), memory.PatchMemory(Patterns.Windows.LauncherLogin, Patches.Windows.LauncherLogin, "Launcher Login Registry") diff --git a/src/Misc/Helpers.cs b/src/Misc/Helpers.cs index dfc5be3..d540f85 100644 --- a/src/Misc/Helpers.cs +++ b/src/Misc/Helpers.cs @@ -5,21 +5,12 @@ namespace Arctium.WoW.Launcher.Misc; static class Helpers { - public static int GetVersionValueFromClient(string fileName, byte field = 0) + public static (int Major, int Minor, int Revision, int Build) GetVersionValueFromClient(string fileName) { var fileVersionInfo = FileVersionInfo.GetVersionInfo(fileName); - return field switch - { - // SubPatch - 1 => fileVersionInfo.FileBuildPart, - // Patch value - 2 => fileVersionInfo.FileMinorPart, - // Expansion value - 3 => fileVersionInfo.FileMajorPart, - // buildNumber value - _ => fileVersionInfo.FilePrivatePart, - }; + return (fileVersionInfo.FileMajorPart, fileVersionInfo.FileMinorPart, + fileVersionInfo.FileBuildPart, fileVersionInfo.FilePrivatePart); } public static void PrintHeader(string serverName) diff --git a/src/Patches/Common.cs b/src/Patches/Common.cs index e55e136..fe34ad8 100644 --- a/src/Patches/Common.cs +++ b/src/Patches/Common.cs @@ -6,22 +6,22 @@ namespace Arctium.WoW.Launcher.Patches; static class Common { // ConnectTo & ChangeProtocol modulus. - public static byte[] Modulus = { 0x5F, 0xD6, 0x80, 0x0B, 0xA7, 0xFF, 0x01, 0x40, 0xC7, 0xBC, 0x8E, 0xF5, 0x6B, 0x27, 0xB0, 0xBF, - 0xF0, 0x1D, 0x1B, 0xFE, 0xDD, 0x0B, 0x1F, 0x3D, 0xB6, 0x6F, 0x1A, 0x48, 0x0D, 0xFB, 0x51, 0x08, - 0x65, 0x58, 0x4F, 0xDB, 0x5C, 0x6E, 0xCF, 0x64, 0xCB, 0xC1, 0x6B, 0x2E, 0xB8, 0x0F, 0x5D, 0x08, - 0x5D, 0x89, 0x06, 0xA9, 0x77, 0x8B, 0x9E, 0xAA, 0x04, 0xB0, 0x83, 0x10, 0xE2, 0x15, 0x4D, 0x08, - 0x77, 0xD4, 0x7A, 0x0E, 0x5A, 0xB0, 0xBB, 0x00, 0x61, 0xD7, 0xA6, 0x75, 0xDF, 0x06, 0x64, 0x88, - 0xBB, 0xB9, 0xCA, 0xB0, 0x18, 0x8B, 0x54, 0x13, 0xE2, 0xCB, 0x33, 0xDF, 0x17, 0xD8, 0xDA, 0xA9, - 0xA5, 0x60, 0xA3, 0x1F, 0x4E, 0x27, 0x05, 0x98, 0x6F, 0xAA, 0xEE, 0x14, 0x3B, 0xF3, 0x97, 0xA8, - 0x12, 0x02, 0x94, 0x0D, 0x84, 0xDC, 0x0E, 0xF1, 0x76, 0x23, 0x95, 0x36, 0x13, 0xF9, 0xA9, 0xC5, - 0x48, 0xDB, 0xDA, 0x86, 0xBE, 0x29, 0x22, 0x54, 0x44, 0x9D, 0x9F, 0x80, 0x7B, 0x07, 0x80, 0x30, - 0xEA, 0xD2, 0x83, 0xCC, 0xCE, 0x37, 0xD1, 0xD1, 0xCF, 0x85, 0xBE, 0x91, 0x25, 0xCE, 0xC0, 0xCC, - 0x55, 0xC8, 0xC0, 0xFB, 0x38, 0xC5, 0x49, 0x03, 0x6A, 0x02, 0xA9, 0x9F, 0x9F, 0x86, 0xFB, 0xC7, - 0xCB, 0xC6, 0xA5, 0x82, 0xA2, 0x30, 0xC2, 0xAC, 0xE6, 0x98, 0xDA, 0x83, 0x64, 0x43, 0x7F, 0x0D, - 0x13, 0x18, 0xEB, 0x90, 0x53, 0x5B, 0x37, 0x6B, 0xE6, 0x0D, 0x80, 0x1E, 0xEF, 0xED, 0xC7, 0xB8, - 0x68, 0x9B, 0x4C, 0x09, 0x7B, 0x60, 0xB2, 0x57, 0xD8, 0x59, 0x8D, 0x7F, 0xEA, 0xCD, 0xEB, 0xC4, - 0x60, 0x9F, 0x45, 0x7A, 0xA9, 0x26, 0x8A, 0x2F, 0x85, 0x0C, 0xF2, 0x19, 0xC6, 0x53, 0x92, 0xF7, - 0xF0, 0xB8, 0x32, 0xCB, 0x5B, 0x66, 0xCE, 0x51, 0x54, 0xB4, 0xC3, 0xD3, 0xD4, 0xDC, 0xB3, 0xEE }; + public static byte[] RsaModulus = { 0x5F, 0xD6, 0x80, 0x0B, 0xA7, 0xFF, 0x01, 0x40, 0xC7, 0xBC, 0x8E, 0xF5, 0x6B, 0x27, 0xB0, 0xBF, + 0xF0, 0x1D, 0x1B, 0xFE, 0xDD, 0x0B, 0x1F, 0x3D, 0xB6, 0x6F, 0x1A, 0x48, 0x0D, 0xFB, 0x51, 0x08, + 0x65, 0x58, 0x4F, 0xDB, 0x5C, 0x6E, 0xCF, 0x64, 0xCB, 0xC1, 0x6B, 0x2E, 0xB8, 0x0F, 0x5D, 0x08, + 0x5D, 0x89, 0x06, 0xA9, 0x77, 0x8B, 0x9E, 0xAA, 0x04, 0xB0, 0x83, 0x10, 0xE2, 0x15, 0x4D, 0x08, + 0x77, 0xD4, 0x7A, 0x0E, 0x5A, 0xB0, 0xBB, 0x00, 0x61, 0xD7, 0xA6, 0x75, 0xDF, 0x06, 0x64, 0x88, + 0xBB, 0xB9, 0xCA, 0xB0, 0x18, 0x8B, 0x54, 0x13, 0xE2, 0xCB, 0x33, 0xDF, 0x17, 0xD8, 0xDA, 0xA9, + 0xA5, 0x60, 0xA3, 0x1F, 0x4E, 0x27, 0x05, 0x98, 0x6F, 0xAA, 0xEE, 0x14, 0x3B, 0xF3, 0x97, 0xA8, + 0x12, 0x02, 0x94, 0x0D, 0x84, 0xDC, 0x0E, 0xF1, 0x76, 0x23, 0x95, 0x36, 0x13, 0xF9, 0xA9, 0xC5, + 0x48, 0xDB, 0xDA, 0x86, 0xBE, 0x29, 0x22, 0x54, 0x44, 0x9D, 0x9F, 0x80, 0x7B, 0x07, 0x80, 0x30, + 0xEA, 0xD2, 0x83, 0xCC, 0xCE, 0x37, 0xD1, 0xD1, 0xCF, 0x85, 0xBE, 0x91, 0x25, 0xCE, 0xC0, 0xCC, + 0x55, 0xC8, 0xC0, 0xFB, 0x38, 0xC5, 0x49, 0x03, 0x6A, 0x02, 0xA9, 0x9F, 0x9F, 0x86, 0xFB, 0xC7, + 0xCB, 0xC6, 0xA5, 0x82, 0xA2, 0x30, 0xC2, 0xAC, 0xE6, 0x98, 0xDA, 0x83, 0x64, 0x43, 0x7F, 0x0D, + 0x13, 0x18, 0xEB, 0x90, 0x53, 0x5B, 0x37, 0x6B, 0xE6, 0x0D, 0x80, 0x1E, 0xEF, 0xED, 0xC7, 0xB8, + 0x68, 0x9B, 0x4C, 0x09, 0x7B, 0x60, 0xB2, 0x57, 0xD8, 0x59, 0x8D, 0x7F, 0xEA, 0xCD, 0xEB, 0xC4, + 0x60, 0x9F, 0x45, 0x7A, 0xA9, 0x26, 0x8A, 0x2F, 0x85, 0x0C, 0xF2, 0x19, 0xC6, 0x53, 0x92, 0xF7, + 0xF0, 0xB8, 0x32, 0xCB, 0x5B, 0x66, 0xCE, 0x51, 0x54, 0xB4, 0xC3, 0xD3, 0xD4, 0xDC, 0xB3, 0xEE }; public static byte[] SignatureModulus = { 0x17, 0x9D, 0x3D, 0xC3, 0x23, 0x56, 0x29, 0xD0, 0x71, 0x13, 0xA9, 0xB3, 0x86, 0x7F, 0x97, 0xA7, 0xA7, 0x2D, 0x42, 0x19, 0x42, 0xA8, 0x17, 0xB0, 0xE0, 0xD6, 0x9F, 0x58, 0x4A, 0x2B, 0x63, 0x76, @@ -40,6 +40,9 @@ static class Common 0xDA, 0x2B, 0x4B, 0x22, 0x40, 0xAB, 0x4F, 0xD3, 0xDD, 0x91, 0x5C, 0x54, 0x4C, 0x4B, 0xB8, 0xAB, 0x68, 0x84, 0x47, 0xCA, 0xE6, 0x8D, 0xFF, 0x12, 0xEC, 0x03, 0x5C, 0xAF, 0xC7, 0xC6, 0x90, 0xB7 }; + public static byte[] CryptoEdPublicKey = { 0x5B, 0x13, 0x01, 0x5D, 0x2C, 0x29, 0x7E, 0xAA, 0x1E, 0x80, 0x63, 0x31, 0x70, 0xD1, 0x23, 0x48, + 0x60, 0x47, 0xA1, 0xBE, 0xEF, 0xC6, 0x37, 0xB2, 0xDC, 0x98, 0x0B, 0x17, 0x40, 0x52, 0xA6, 0x6D }; + public static byte[] GetVersionUrl(int build) => Encoding.UTF8.GetBytes($"ngdp.arctium.io/%s/%s/{build}/versions"); public static byte[] Portal = new byte[Patterns.Common.Portal.Length]; diff --git a/src/Patterns/Common.cs b/src/Patterns/Common.cs index fc2663f..a104c89 100644 --- a/src/Patterns/Common.cs +++ b/src/Patterns/Common.cs @@ -7,7 +7,8 @@ static class Common { public static short[] ConnectToModulus = { 0x91, 0xD5, 0x9B, 0xB7, 0xD4, 0xE1, 0x83, 0xA5 }; public static short[] SignatureModulus = { 0x35, 0xFF, 0x17, 0xE7, 0x33, 0xC4, 0xD3, 0xD4 }; - public static short[] ChangeProtocolModulus = { 0x71, 0xFD, 0xFA, 0x60, 0x14, 0x0D, 0xF2, 0x05 }; + public static short[] CryptoRsaModulus = { 0x71, 0xFD, 0xFA, 0x60, 0x14, 0x0D, 0xF2, 0x05 }; + public static short[] CryptoEdPublicKey = { 0x15, 0xD6, 0x18, 0xBD, 0x7D, 0xB5, 0x77, 0xBD }; public static short[] CertBundle = "{\"Created\":".ToPattern(); public static short[] VersionUrl = "%s.patch.battle.net:1119/%s/versions".ToPattern();