diff --git a/FortniteLauncher.crproj b/FortniteLauncher.crproj new file mode 100644 index 0000000..16ed413 --- /dev/null +++ b/FortniteLauncher.crproj @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + ..\..\bin\Release + \ No newline at end of file diff --git a/FortniteLauncher.csproj b/FortniteLauncher.csproj new file mode 100644 index 0000000..ecfb188 --- /dev/null +++ b/FortniteLauncher.csproj @@ -0,0 +1,78 @@ + + + + + Debug + AnyCPU + {B4D532C1-4E45-43E1-B2AB-296CFC9ECE1B} + Exe + FortniteLauncher + FortniteLauncher + v4.0 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Icon.ico + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + 7.3 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + 7.3 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Icon.ico b/Icon.ico new file mode 100644 index 0000000..a1aa6ff Binary files /dev/null and b/Icon.ico differ diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..938a48f --- /dev/null +++ b/Program.cs @@ -0,0 +1,104 @@ +using FortniteLauncher.Utilities; +using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; + +namespace FortniteLauncher +{ + class Program + { + private const string FORTNITE_EXECUTABLE = "FortniteClient-Win64-Shipping.exe"; + + private static Process _fnProcess; + private static Process FortniteEACProcess; + private static bool InjectDLL; + + static void Main(string[] args) + { + string joinedArgs = string.Join(" ", args); + + // Check if the Fortnite client exists in the current work path. + if (!File.Exists(FORTNITE_EXECUTABLE)) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"\"{FORTNITE_EXECUTABLE}\" is missing!"); + Console.ReadKey(); + Environment.Exit(1); + } + + // Check if -NOSSLPINNING exists in args (regardless of case) to disable SSL pinning + if (joinedArgs.ToUpper().Contains("-NOSSLPINNING")) + { + joinedArgs = Regex.Replace(joinedArgs, "-NOSSLPINNING", string.Empty, RegexOptions.IgnoreCase); + InjectDLL = true; + string PlataniumPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Platanium.dll"); + if (!File.Exists(PlataniumPath)) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"\"Platanium.dll\" is missing!"); + Console.ReadKey(); + Environment.Exit(1); + } + } + + // Setup a process exit event handler + AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit); + + // Fortnite EAC + FortniteEACProcess = new Process + { + StartInfo = + { + FileName = "FortniteClient-Win64-Shipping_EAC.exe", + Arguments = $"{joinedArgs} -noeac -fromfl=be -fltoken=f7b9gah4h5380d10f721dd6a" + + } + }; + FortniteEACProcess.Start(); + FortniteEACProcess.Suspend(); + + // Initialize Fortnite process with start info + _fnProcess = new Process + { + StartInfo = + { + FileName = FORTNITE_EXECUTABLE, + Arguments = $"{joinedArgs} -noeac -fromfl=be -fltoken=f7b9gah4h5380d10f721dd6a" + } + }; + + _fnProcess.Start(); // Start Fortnite client process + + // Check if -NOSSLPINNING exists in args (regardless of case) to disable SSL pinning + if (InjectDLL) + { + string PlataniumPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Platanium.dll"); + IntPtr hProcess = Win32.OpenProcess(1082, false, _fnProcess.Id); + IntPtr procAddress = Win32.GetProcAddress(Win32.GetModuleHandle("kernel32.dll"), "LoadLibraryA"); + uint num = (uint)((PlataniumPath.Length + 1) * Marshal.SizeOf(typeof(char))); + IntPtr intPtr = Win32.VirtualAllocEx(hProcess, IntPtr.Zero, num, 12288U, 4U); + UIntPtr uintPtr; + Win32.WriteProcessMemory(hProcess, intPtr, Encoding.Default.GetBytes(PlataniumPath), num, out uintPtr); + Win32.CreateRemoteThread(hProcess, IntPtr.Zero, 0U, procAddress, intPtr, 0U, IntPtr.Zero); + _fnProcess.WaitForExit(); // We'll wait for the Fortnite process to exit, otherwise our launcher will just close instantly + } + } + + private static void OnProcessExit(object sender, EventArgs e) + { + if (!FortniteEACProcess.HasExited) + { + FortniteEACProcess.Resume(); + FortniteEACProcess.Kill(); + } + if (!_fnProcess.HasExited) + { + _fnProcess.Kill(); + } + } + } +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5c7f8fe --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FortniteLauncher")] +[assembly: AssemblyDescription("A custom FortniteLauncher by Cyuubi which includes an SSL pinning bypass. Fixed by EZFN")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FortniteLauncher")] +[assembly: AssemblyCopyright("Copyright © Cyuubi 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b4d532c1-4e45-43e1-b2ab-296cfc9ece1b")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Utilities/Extensions.cs b/Utilities/Extensions.cs new file mode 100644 index 0000000..83ec0d1 --- /dev/null +++ b/Utilities/Extensions.cs @@ -0,0 +1,46 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace FortniteLauncher.Utilities +{ + [Flags] + public enum ThreadAccess : int + { + SUSPEND_RESUME = (0x0002), + } + public static class ProcessExtension + { + [DllImport("kernel32.dll")] + static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); + [DllImport("kernel32.dll")] + static extern uint SuspendThread(IntPtr hThread); + [DllImport("kernel32.dll")] + static extern int ResumeThread(IntPtr hThread); + + public static void Suspend(this Process process) + { + foreach (ProcessThread thread in process.Threads) + { + var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); + if (pOpenThread == IntPtr.Zero) + { + break; + } + SuspendThread(pOpenThread); + } + } + public static void Resume(this Process process) + { + foreach (ProcessThread thread in process.Threads) + { + var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); + if (pOpenThread == IntPtr.Zero) + { + break; + } + ResumeThread(pOpenThread); + } + } + } +} \ No newline at end of file diff --git a/Utilities/Win32.cs b/Utilities/Win32.cs new file mode 100644 index 0000000..7b30614 --- /dev/null +++ b/Utilities/Win32.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.InteropServices; + +public static class Win32 +{ + public const int PROCESS_ALL_ACCESS = 0x1F0FFF; + + [DllImport("kernel32.dll")] + public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); + + [DllImport("kernel32.dll")] + public static extern bool ReadProcessMemory(IntPtr hProcess, ulong lpBaseAddress, byte[] lpBuffer, int dwSize, int lpNumberOfBytesRead = 0); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten); + + [DllImport("kernel32.dll")] + public static extern void RaiseException(uint dwExceptionCode, uint dwExceptionFlags, uint nNumberOfArguments, IntPtr lpArguments); + [DllImport("kernel32.dll")] + public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr GetModuleHandle(string lpModuleName); + [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] + public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); +} \ No newline at end of file