Patch in a static auth seed to remove the need of updating them on new builds:

- Only works with --staticseed launch arg.
- Works on all supported game versions.
- Use the following auth seed on your server: 179D3DC3235629D07113A9B3867F97A7
This commit is contained in:
Fabian
2022-11-13 18:29:33 +01:00
parent a48224edce
commit 341897c01a
5 changed files with 71 additions and 22 deletions

View File

@@ -12,6 +12,7 @@ static class LaunchOptions
public static Option<string> GamePath = new("--path");
public static Option<string> GameBinary = new("--binary");
public static Option<bool> KeepCache = new("--keepcache", () => true);
public static Option<bool> UseStaticAuthSeed = new("--staticseed");
public static Parser Instance => new CommandLineBuilder(ConfigureCommandLine(RootCommand))
.UseHelp()
@@ -26,7 +27,8 @@ static class LaunchOptions
Version,
GamePath,
GameBinary,
KeepCache
KeepCache,
UseStaticAuthSeed
};
static Command ConfigureCommandLine(Command rootCommand)

View File

@@ -90,7 +90,7 @@ class Launcher
return gameBinaryPath;
}
public static bool LaunchGame(string appPath, string gameCommandLine)
public static bool LaunchGame(string appPath, string gameCommandLine, bool useStaticAuthSeed)
{
var startupInfo = new StartupInfo();
var processInfo = new ProcessInformation();
@@ -135,6 +135,9 @@ class Launcher
// Refresh the client data before patching.
memory.RefreshMemoryData((int)gameAppData.Length);
// We need to cache this here since we are using our RSA modulus as auth seed.
var modulusOffset = memory.Data.FindPattern(Patterns.Common.SignatureModulus);
// Wait for all direct memory patch tasks to complete,
Task.WaitAll(new[]
{
@@ -154,25 +157,7 @@ class Launcher
NativeWindows.NtResumeProcess(processInfo.ProcessHandle);
// Wait for client initialization.
var initOffset = memory?.Read(mbi.BaseAddress, (int)mbi.RegionSize)?.FindPattern(Patterns.Windows.Init) ?? 0;
while (initOffset == 0)
{
initOffset = memory?.Read(mbi.BaseAddress, (int)mbi.RegionSize)?.FindPattern(Patterns.Windows.Init) ?? 0;
Console.WriteLine("Waiting for client initialization...");
}
initOffset += BitConverter.ToUInt32(memory.Read(initOffset + memory.BaseAddress + 2, 4), 0) + 10;
while (memory?.Read(initOffset + memory.BaseAddress, 1)?[0] == null ||
memory?.Read(initOffset + memory.BaseAddress, 1)?[0] == 0)
memory.Data = memory.Read(mbi.BaseAddress, (int)mbi.RegionSize);
PrepareAntiCrash(memory, ref mbi, ref processInfo);
memory.RefreshMemoryData((int)mbi.RegionSize);
WaitForUnpack(ref processInfo, memory, ref mbi);
#if x64
Task.WaitAll(new[]
@@ -180,6 +165,21 @@ class Launcher
memory.QueuePatch(Patterns.Windows.CertBundle, Patches.Windows.CertBundle, "CertBundle"),
memory.QueuePatch(Patterns.Windows.CertCommonName, Patches.Windows.CertCommonName, "CertCommonName", 5)
}, CancellationTokenSource.Token);
if (useStaticAuthSeed)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Static auth seed used. Be sure that the server you are connecting to supports it.");
Console.ResetColor();
// Generates a patch for the auth seed so we don't have to update them on each build.
var authSeedFunctionOffset = GenerateAuthSeedFunctionPatch(memory, modulusOffset);
Task.WaitAll(new[]
{
memory.QueuePatch(authSeedFunctionOffset, Patches.Windows.AuthSeed, "CustomAuthSeedFunction")
}, CancellationTokenSource.Token);
}
#if CUSTOM_FILES
Task.WaitAll(new[]
{
@@ -248,6 +248,49 @@ class Launcher
return false;
}
static long GenerateAuthSeedFunctionPatch(WinMemory memory, long modulusOffset)
{
var authSeedLoadOffset = memory.Data.FindPattern(Patterns.Windows.AuthSeed);
if (authSeedLoadOffset == 0)
throw new InvalidDataException("authSeedLoadOffset");
var leaStartOffset = authSeedLoadOffset + 9;
var leaValue = Unsafe.ReadUnaligned<int>(ref memory.Data[leaStartOffset + 3]);
var authSeedWrapperOffset = leaStartOffset + leaValue + 7;
var jmpValue = Unsafe.ReadUnaligned<uint>(ref memory.Data[authSeedWrapperOffset + 6]);
var authSeedFunctionOffset = authSeedWrapperOffset + 5 + jmpValue + 5;
// Write the modulus offset to our custom get seed functions.
// Resulting static auth seed is: 179D3DC3235629D07113A9B3867F97A7
Unsafe.WriteUnaligned(ref Patches.Windows.AuthSeed[3], (uint)(modulusOffset - authSeedFunctionOffset - 7));
return authSeedFunctionOffset;
}
static void WaitForUnpack(ref ProcessInformation processInfo, WinMemory memory, ref MemoryBasicInformation mbi)
{
// Wait for client initialization.
var initOffset = memory?.Read(mbi.BaseAddress, (int)mbi.RegionSize)?.FindPattern(Patterns.Windows.Init) ?? 0;
while (initOffset == 0)
{
initOffset = memory?.Read(mbi.BaseAddress, (int)mbi.RegionSize)?.FindPattern(Patterns.Windows.Init) ?? 0;
Console.WriteLine("Waiting for client initialization...");
}
initOffset += BitConverter.ToUInt32(memory.Read(initOffset + memory.BaseAddress + 2, 4), 0) + 10;
while (memory?.Read(initOffset + memory.BaseAddress, 1)?[0] == null ||
memory?.Read(initOffset + memory.BaseAddress, 1)?[0] == 0)
memory.Data = memory.Read(mbi.BaseAddress, (int)mbi.RegionSize);
PrepareAntiCrash(memory, ref mbi, ref processInfo);
memory.RefreshMemoryData((int)mbi.RegionSize);
}
static void PrepareAntiCrash(WinMemory memory, ref MemoryBasicInformation mbi, ref ProcessInformation processInfo)
{
memory.RefreshMemoryData((int)mbi.RegionSize);

View File

@@ -11,6 +11,7 @@ static class Windows
public static byte[] CertCommonName = { 0xB0, 0x01 };
public static byte[] ShortJump = { 0xEB };
public static byte[] NoJump = { 0x00, 0x00, 0x00, 0x00 };
public static byte[] AuthSeed = { 0x0F, 0x28, 0x05, 0xEF, 0xBE, 0xAD, 0xDE, 0x0F, 0x11, 0x02, 0xC3 };
#elif ARM64
public static byte[] Integrity = { };
public static byte[] Branch = { 0xB5 };

View File

@@ -17,6 +17,9 @@ static class Windows
public static short[] CertBundle = { 0x75, 0x06, 0x48, -1, -1, 0x60, 0x5F, 0xC3 };
public static short[] CertCommonName = { 0x80, -1, 0x2A, 0x75, -1, 0x32, 0xC0, 0x48 };
// Auth seed function.
public static short[] AuthSeed = { 0x57, 0x6F, 0x57, 0x00, 0xE8, -1, -1, -1, -1, 0x48, 0x8D };
// Custom files (mods).
public static short[] LoadByFileId = { 0x41, -1, -1, 0x01, 0x0F, 0x84, -1, 0x00, 0x00, 0x00, 0x48, 0x8B, -1, -1, -1, -1, -1, 0x8B };
public static short[] LoadByFilePath = { 0x01, 0x0F, 0x84, -1, -1, -1, -1, 0x48, 0x8B, -1, -1, -1, -1, -1, 0x44, 0x89, -1, -1, -1, 0x48, 0x85, 0xC9 };

View File

@@ -16,7 +16,7 @@ LaunchOptions.RootCommand.SetHandler(context =>
var appPath = Launcher.PrepareGameLaunch(context.ParseResult);
var gameCommandLine = string.Join(" ", context.ParseResult.UnmatchedTokens);
if (string.IsNullOrEmpty(appPath) || !Launcher.LaunchGame(appPath, gameCommandLine))
if (string.IsNullOrEmpty(appPath) || !Launcher.LaunchGame(appPath, gameCommandLine, context.ParseResult.HasOption(LaunchOptions.UseStaticAuthSeed)))
WaitAndExit(5000);
});