diff options
author | BobTheBob <32057864+BobTheBob9@users.noreply.github.com> | 2021-08-18 03:56:51 +0100 |
---|---|---|
committer | BobTheBob <32057864+BobTheBob9@users.noreply.github.com> | 2021-08-18 03:56:51 +0100 |
commit | 125f53aaa690e4870af88aa3a8947ac5ac0b435d (patch) | |
tree | 2ee0c9ec4abd9ad49850a8807b7afd5cc16dcddb | |
parent | f63b853468225e2bc675cde9484a27acfe8548b5 (diff) | |
download | NorthstarLauncher-125f53aaa690e4870af88aa3a8947ac5ac0b435d.tar.gz NorthstarLauncher-125f53aaa690e4870af88aa3a8947ac5ac0b435d.zip |
lots of launcher stuff
23 files changed, 1180 insertions, 21 deletions
diff --git a/GameInjector/GameInjector.vcxproj b/GameInjector/GameInjector.vcxproj new file mode 100644 index 00000000..37a269df --- /dev/null +++ b/GameInjector/GameInjector.vcxproj @@ -0,0 +1,176 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <VCProjectVersion>16.0</VCProjectVersion> + <Keyword>Win32Proj</Keyword> + <ProjectGuid>{b3554508-967e-49d2-bf87-586dd95d817c}</ProjectGuid> + <RootNamespace>GameInjector</RootNamespace> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>WIN32;_DEBUG;GAMEINJECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeader>Use</PrecompiledHeader> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <AdditionalIncludeDirectories>$(ProjectDir)</AdditionalIncludeDirectories> + <LanguageStandard>stdcpp17</LanguageStandard> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableUAC>false</EnableUAC> + <AdditionalDependencies>$(ProjectDir)MinHook.x86.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>WIN32;NDEBUG;GAMEINJECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeader>Use</PrecompiledHeader> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <AdditionalIncludeDirectories>$(ProjectDir)</AdditionalIncludeDirectories> + <LanguageStandard>stdcpp17</LanguageStandard> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableUAC>false</EnableUAC> + <AdditionalDependencies>$(ProjectDir)MinHook.x86.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>_DEBUG;GAMEINJECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeader>Use</PrecompiledHeader> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableUAC>false</EnableUAC> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>NDEBUG;GAMEINJECTOR_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <PrecompiledHeader>Use</PrecompiledHeader> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableUAC>false</EnableUAC> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="framework.h" /> + <ClInclude Include="MinHook.h" /> + <ClInclude Include="pch.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="dllmain.cpp" /> + <ClCompile Include="pch.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> + </ClCompile> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/GameInjector/GameInjector.vcxproj.filters b/GameInjector/GameInjector.vcxproj.filters new file mode 100644 index 00000000..e70fcdb6 --- /dev/null +++ b/GameInjector/GameInjector.vcxproj.filters @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Header Files\include"> + <UniqueIdentifier>{111f468d-e3a5-4d1a-903d-8911f4cfd715}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="framework.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="pch.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="MinHook.h"> + <Filter>Header Files\include</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="dllmain.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="pch.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/GameInjector/MinHook.h b/GameInjector/MinHook.h new file mode 100644 index 00000000..15c0a875 --- /dev/null +++ b/GameInjector/MinHook.h @@ -0,0 +1,186 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2017 Tsuda Kageyu. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) + #error MinHook supports only x86 and x64 systems. +#endif + +#include <windows.h> + +// MinHook Error Codes. +typedef enum MH_STATUS +{ + // Unknown error. Should not be returned. + MH_UNKNOWN = -1, + + // Successful. + MH_OK = 0, + + // MinHook is already initialized. + MH_ERROR_ALREADY_INITIALIZED, + + // MinHook is not initialized yet, or already uninitialized. + MH_ERROR_NOT_INITIALIZED, + + // The hook for the specified target function is already created. + MH_ERROR_ALREADY_CREATED, + + // The hook for the specified target function is not created yet. + MH_ERROR_NOT_CREATED, + + // The hook for the specified target function is already enabled. + MH_ERROR_ENABLED, + + // The hook for the specified target function is not enabled yet, or already + // disabled. + MH_ERROR_DISABLED, + + // The specified pointer is invalid. It points the address of non-allocated + // and/or non-executable region. + MH_ERROR_NOT_EXECUTABLE, + + // The specified target function cannot be hooked. + MH_ERROR_UNSUPPORTED_FUNCTION, + + // Failed to allocate memory. + MH_ERROR_MEMORY_ALLOC, + + // Failed to change the memory protection. + MH_ERROR_MEMORY_PROTECT, + + // The specified module is not loaded. + MH_ERROR_MODULE_NOT_FOUND, + + // The specified function is not found. + MH_ERROR_FUNCTION_NOT_FOUND +} +MH_STATUS; + +// Can be passed as a parameter to MH_EnableHook, MH_DisableHook, +// MH_QueueEnableHook or MH_QueueDisableHook. +#define MH_ALL_HOOKS NULL + +#ifdef __cplusplus +extern "C" { +#endif + + // Initialize the MinHook library. You must call this function EXACTLY ONCE + // at the beginning of your program. + MH_STATUS WINAPI MH_Initialize(VOID); + + // Uninitialize the MinHook library. You must call this function EXACTLY + // ONCE at the end of your program. + MH_STATUS WINAPI MH_Uninitialize(VOID); + + // Creates a Hook for the specified target function, in disabled state. + // Parameters: + // pTarget [in] A pointer to the target function, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); + + // Creates a Hook for the specified API function, in disabled state. + // Parameters: + // pszModule [in] A pointer to the loaded module name which contains the + // target function. + // pszTarget [in] A pointer to the target function name, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHookApi( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); + + // Creates a Hook for the specified API function, in disabled state. + // Parameters: + // pszModule [in] A pointer to the loaded module name which contains the + // target function. + // pszTarget [in] A pointer to the target function name, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + // ppTarget [out] A pointer to the target function, which will be used + // with other functions. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHookApiEx( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); + + // Removes an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); + + // Enables an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // enabled in one go. + MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); + + // Disables an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // disabled in one go. + MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); + + // Queues to enable an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // queued to be enabled. + MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); + + // Queues to disable an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // queued to be disabled. + MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); + + // Applies all queued changes in one go. + MH_STATUS WINAPI MH_ApplyQueued(VOID); + + // Translates the MH_STATUS to its name as a string. + const char * WINAPI MH_StatusToString(MH_STATUS status); + +#ifdef __cplusplus +} +#endif + diff --git a/GameInjector/MinHook.x64.dll b/GameInjector/MinHook.x64.dll Binary files differnew file mode 100644 index 00000000..b4f51c2e --- /dev/null +++ b/GameInjector/MinHook.x64.dll diff --git a/GameInjector/MinHook.x64.lib b/GameInjector/MinHook.x64.lib Binary files differnew file mode 100644 index 00000000..909fe682 --- /dev/null +++ b/GameInjector/MinHook.x64.lib diff --git a/GameInjector/MinHook.x86.dll b/GameInjector/MinHook.x86.dll Binary files differnew file mode 100644 index 00000000..d6167c83 --- /dev/null +++ b/GameInjector/MinHook.x86.dll diff --git a/GameInjector/MinHook.x86.lib b/GameInjector/MinHook.x86.lib Binary files differnew file mode 100644 index 00000000..02f351c2 --- /dev/null +++ b/GameInjector/MinHook.x86.lib diff --git a/GameInjector/dllmain.cpp b/GameInjector/dllmain.cpp new file mode 100644 index 00000000..c18495be --- /dev/null +++ b/GameInjector/dllmain.cpp @@ -0,0 +1,119 @@ +// dllmain.cpp : Defines the entry point for the DLL application. + +#include "pch.h" +#include "MinHook.h" +#include <string> +#include <sstream> +#include <filesystem> +#include <iostream> +#include <iomanip> + +#define DLL_NAME L"Northstar.dll" + +typedef BOOL(WINAPI *CreateProcessWType)( + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation +); +CreateProcessWType CreateProcessWOriginal; + +HMODULE ownHModule; +std::filesystem::path tf2DirPath; + +BOOL WINAPI CreateProcessWHook( + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation +) +{ + bool isTitanfallProcess = false; + + // origin doesn't use lpApplicationName + if (lpApplicationName) + isTitanfallProcess = wcsstr(lpApplicationName, L"Titanfall2\\Titanfall2.exe"); + else + isTitanfallProcess = wcsstr(lpCommandLine, L"Titanfall2\\Titanfall2.exe"); + + std::wcout << lpCommandLine << std::endl; + + // suspend process on creation so we can hook + if (isTitanfallProcess) + dwCreationFlags |= CREATE_SUSPENDED; + + BOOL ret = CreateProcessWOriginal(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); + + if (isTitanfallProcess) + { + std::cout << "Creating titanfall process!" << std::endl; + std::cout << "Handle: " << lpProcessInformation->hProcess << " ID: " << lpProcessInformation->dwProcessId << " Thread: " << lpProcessInformation->hThread << std::endl; + + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + + std::stringstream argStr; + argStr << lpProcessInformation->dwProcessId; + argStr << " "; + argStr << lpProcessInformation->dwThreadId; + + CreateProcessA((tf2DirPath / "InjectionProxy64.exe").string().c_str(), (LPSTR)(argStr.str().c_str()), 0, 0, false, 0, 0, tf2DirPath.string().c_str(), (LPSTARTUPINFOA)&si, &pi); + WaitForSingleObject(pi.hThread, INFINITE); + ResumeThread(lpProcessInformation->hProcess); + + MH_RemoveHook(&CreateProcessW); + FreeLibrary(ownHModule); + } + + + return ret; +} + +BOOL APIENTRY DllMain(HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + //DisableThreadLibraryCalls(hModule); + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + + ownHModule = hModule; + char ownDllPath[MAX_PATH]; + GetModuleFileNameA(hModule, ownDllPath, MAX_PATH); + + tf2DirPath = std::filesystem::path(ownDllPath).parent_path(); + + //AllocConsole(); + //freopen("CONOUT$", "w", stdout); + + // hook CreateProcessW + if (MH_Initialize() > MH_ERROR_ALREADY_INITIALIZED) // MH_ERROR_ALREADY_INITIALIZED = 1, MH_OK = 0, these are the only results we should expect + return TRUE; + + MH_CreateHook(&CreateProcessW, &CreateProcessWHook, reinterpret_cast<LPVOID*>(&CreateProcessWOriginal)); + MH_EnableHook(&CreateProcessW); + + return TRUE; +} + diff --git a/GameInjector/framework.h b/GameInjector/framework.h new file mode 100644 index 00000000..54b83e94 --- /dev/null +++ b/GameInjector/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include <windows.h> diff --git a/GameInjector/pch.cpp b/GameInjector/pch.cpp new file mode 100644 index 00000000..64b7eef6 --- /dev/null +++ b/GameInjector/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" + +// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/GameInjector/pch.h b/GameInjector/pch.h new file mode 100644 index 00000000..1fd0adab --- /dev/null +++ b/GameInjector/pch.h @@ -0,0 +1,15 @@ +// pch.h: This is a precompiled header file. +// Files listed below are compiled only once, improving build performance for future builds. +// This also affects IntelliSense performance, including code completion and many code browsing features. +// However, files listed here are ALL re-compiled if any one of them is updated between builds. +// Do not add files here that you will be updating frequently as this negates the performance advantage. + +#ifndef PCH_H +#define PCH_H + +#define _CRT_SECURE_NO_WARNINGS + +// add headers that you want to pre-compile here +#include "framework.h" + +#endif //PCH_H diff --git a/InjectionProxy64/InjectionProxy64.vcxproj b/InjectionProxy64/InjectionProxy64.vcxproj new file mode 100644 index 00000000..39e7df5a --- /dev/null +++ b/InjectionProxy64/InjectionProxy64.vcxproj @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <VCProjectVersion>16.0</VCProjectVersion> + <Keyword>Win32Proj</Keyword> + <ProjectGuid>{a8ce6730-a6c7-441d-8c65-8a39ee5a01a2}</ProjectGuid> + <RootNamespace>InjectionProxy64</RootNamespace> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="main.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/InjectionProxy64/InjectionProxy64.vcxproj.filters b/InjectionProxy64/InjectionProxy64.vcxproj.filters new file mode 100644 index 00000000..ce0c35cc --- /dev/null +++ b/InjectionProxy64/InjectionProxy64.vcxproj.filters @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/InjectionProxy64/main.cpp b/InjectionProxy64/main.cpp new file mode 100644 index 00000000..f338f910 --- /dev/null +++ b/InjectionProxy64/main.cpp @@ -0,0 +1,40 @@ +#include <string> +#include <Windows.h> + +#define DLL_NAME L"Northstar.dll" + +int main(int argc, char** argv) +{ + // this a proxy process used for injecting into titanfall, since launchers are 32bit you can't inject from those into 64bit titanfall + // dont bother to do any error checking here, just assume it's getting called right + DWORD pid = std::stoi(argv[0]); + DWORD threadId = std::stoi(argv[1]); + + HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, false, pid); + HANDLE thread = OpenThread(THREAD_ALL_ACCESS, false, threadId); + + HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll"); + LPTHREAD_START_ROUTINE pLoadLibraryW = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryW"); + + SIZE_T dwLength = (wcslen(DLL_NAME) + 1) * 2; + LPVOID lpLibName = VirtualAllocEx(process, NULL, dwLength, MEM_COMMIT, PAGE_READWRITE); + + SIZE_T written = 0; + WriteProcessMemory(process, lpLibName, DLL_NAME, dwLength, &written); + + HANDLE hThread = CreateRemoteThread(process, NULL, NULL, pLoadLibraryW, lpLibName, NULL, NULL); + + WaitForSingleObject(hThread, INFINITE); + + // TODO: need to call initialisenorthstar in the new process + // (this does not currently work!!! ) + //LPTHREAD_START_ROUTINE pInitNorthstar = (LPTHREAD_START_ROUTINE)GetProcAddress((HMODULE)lpLibName, "InitialiseNorthstar"); + //HANDLE hInitThread = CreateRemoteThread(processInfo.hProcess, NULL, NULL, pInitNorthstar, NULL, NULL, NULL); + //WaitForSingleObject(hInitThread, INFINITE); + //CloseHandle(hInitThread); + + ResumeThread(thread); + CloseHandle(hThread); + + VirtualFreeEx(process, lpLibName, dwLength, MEM_RELEASE); +}
\ No newline at end of file diff --git a/InjectorTest/main.cpp b/InjectorTest/main.cpp index e9e1e320..09a92314 100644 --- a/InjectorTest/main.cpp +++ b/InjectorTest/main.cpp @@ -10,7 +10,7 @@ int main() { memset(&startupInfo, 0, sizeof(startupInfo)); memset(&processInfo, 0, sizeof(processInfo)); - CreateProcessW(PROC_NAME, (LPWSTR)L"-noorigin -multiple -novid", NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInfo); + CreateProcessW(PROC_NAME, (LPWSTR)L"-multiple -novid", NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInfo); HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll"); LPTHREAD_START_ROUTINE pLoadLibraryW = diff --git a/LauncherInjector/LauncherInjector.vcxproj b/LauncherInjector/LauncherInjector.vcxproj new file mode 100644 index 00000000..620303b1 --- /dev/null +++ b/LauncherInjector/LauncherInjector.vcxproj @@ -0,0 +1,153 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <VCProjectVersion>16.0</VCProjectVersion> + <Keyword>Win32Proj</Keyword> + <ProjectGuid>{0ea82cb0-53fe-4d4c-96df-47fa970513d0}</ProjectGuid> + <RootNamespace>LauncherInjector</RootNamespace> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v142</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard>stdcpp17</LanguageStandard> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard>stdcpp17</LanguageStandard> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard>stdcpp17</LanguageStandard> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ConformanceMode>true</ConformanceMode> + <LanguageStandard>stdcpp17</LanguageStandard> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="main.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/LauncherInjector/LauncherInjector.vcxproj.filters b/LauncherInjector/LauncherInjector.vcxproj.filters new file mode 100644 index 00000000..ce0c35cc --- /dev/null +++ b/LauncherInjector/LauncherInjector.vcxproj.filters @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="main.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/LauncherInjector/main.cpp b/LauncherInjector/main.cpp new file mode 100644 index 00000000..1f26dfc0 --- /dev/null +++ b/LauncherInjector/main.cpp @@ -0,0 +1,161 @@ +#include <Windows.h> +#include <TlHelp32.h> +#include <filesystem> +#include <sstream> +#include <iostream> + +namespace fs = std::filesystem; + +DWORD GetProcessByName(std::wstring processName) +{ + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + + PROCESSENTRY32 processSnapshotEntry = { 0 }; + processSnapshotEntry.dwSize = sizeof(PROCESSENTRY32); + + if (snapshot == INVALID_HANDLE_VALUE) + return 0; + + if (!Process32First(snapshot, &processSnapshotEntry)) + return 0; + + while (Process32Next(snapshot, &processSnapshotEntry)) + { + if (!wcscmp(processSnapshotEntry.szExeFile, processName.c_str())) + { + CloseHandle(snapshot); + return processSnapshotEntry.th32ProcessID; + } + } + + CloseHandle(snapshot); + return 0; +} + +void InjectInjectorIntoProcess(DWORD pid) +{ + HANDLE procHandle = OpenProcess(PROCESS_ALL_ACCESS, false, pid); + + std::wstring path = (fs::current_path() / "GameInjector.dll").wstring(); + size_t length = (path.length() + 1) * 2; + LPVOID lpLibName = VirtualAllocEx(procHandle, NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + WriteProcessMemory(procHandle, lpLibName, path.c_str(), length, 0); + + // load minhook, since origin's loadlibrary won't load it from the tf directly by default + std::wstring minhookPath = (fs::current_path() / "MinHook.x86.dll").wstring(); + size_t minhookLength = (minhookPath.length() + 1) * 2; + LPVOID lpMinhookLibName = VirtualAllocEx(procHandle, NULL, minhookLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + WriteProcessMemory(procHandle, lpMinhookLibName, minhookPath.c_str(), minhookLength, 0); + + HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll"); + LPTHREAD_START_ROUTINE pLoadLibraryW = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryW"); + HANDLE thread = CreateRemoteThread(procHandle, NULL, 0, pLoadLibraryW, lpMinhookLibName, 0, 0); + WaitForSingleObject(thread, INFINITE); + + thread = CreateRemoteThread(procHandle, NULL, 0, pLoadLibraryW, lpLibName, 0, 0); + WaitForSingleObject(thread, INFINITE); + + DWORD dwExitCode; + GetExitCodeThread(thread, &dwExitCode); + std::cout << dwExitCode << std::endl; + + CloseHandle(procHandle); + + std::cout << pid << std::endl; +} + +void CreateAndHookUnpackedTitanfallProcess() +{ + PROCESS_INFORMATION tfPi; + memset(&tfPi, 0, sizeof(tfPi)); + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + CreateProcessA("Titanfall2-unpacked.exe", (LPSTR)"", NULL, NULL, false, CREATE_SUSPENDED, NULL, NULL, (LPSTARTUPINFOA)&si, &tfPi); + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + memset(&si, 0, sizeof(si)); + + std::stringstream argStream; + argStream << tfPi.dwProcessId; + argStream << " "; + argStream << tfPi.dwThreadId; + + CreateProcessA("InjectionProxy64.exe", (LPSTR)(argStream.str().c_str()), NULL, NULL, false, 0, NULL, NULL, (LPSTARTUPINFOA)&si, &pi); + WaitForSingleObject(pi.hThread, INFINITE); + + CloseHandle(pi.hThread); + CloseHandle(tfPi.hThread); +} + +int main() +{ + //AllocConsole(); + + // check if we're in the titanfall directory + if (!fs::exists("Titanfall2.exe") && !fs::exists("Titanfall2-unpacked.exe")) + { + MessageBox(NULL, L"Titanfall2.exe not found! Please launch from your titanfall 2 directory!", L"", MB_OK); + return 1; + } + + // check for steam dll and unpacked exe + bool unpacked = fs::exists("Titanfall2-unpacked.exe"); + bool steamBuild = !unpacked && fs::exists("steam_api64.dll"); + + // unpacked origin + if (unpacked) + { + // check origin process + DWORD origin = GetProcessByName(L"Origin.exe"); + + if (!origin) + { + // unpacked exe will crash if origin isn't open on launch, so launch it + // get origin path from registry, code here is reversed from OriginSDK.dll + HKEY key; + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\WOW6432Node\\Origin", 0, KEY_READ, &key) != ERROR_SUCCESS) + return 1; + + char originPath[520]; + DWORD originPathLength = 520; + if (RegQueryValueExA(key, "ClientPath", 0, 0, (LPBYTE)&originPath, &originPathLength) != ERROR_SUCCESS) + return 1; + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + CreateProcessA(originPath, (LPSTR)"", NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_PROCESS_GROUP, NULL, NULL, (LPSTARTUPINFOA)&si, &pi); + + // bit of a hack, but wait 12.5s to give origin a sec to init + // would be nice if we could do this dynamically, but idk how rn + Sleep(12500); + } + + CreateAndHookUnpackedTitanfallProcess(); + } + // packed origin + else + { + // create a titanfall process, this will cause origin to start launching the game + // if we're on steam, origin will launch the steam release here, too + // we can't hook the titanfall process here unfortunately, since the titanfall process we create here dies when origin stuff starts + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + CreateProcessA("Titanfall2.exe", (LPSTR)"", NULL, NULL, false, 0, NULL, NULL, (LPSTARTUPINFOA)&si, &pi); + + // hook launcher + DWORD launcherPID; + if (steamBuild) + while (!(launcherPID = GetProcessByName(L"steam.exe"))) Sleep(50); + else + while (!(launcherPID = GetProcessByName(L"Origin.exe"))) Sleep(50); + + // injector should clean itself up after its job is done + InjectInjectorIntoProcess(launcherPID); + } +}
\ No newline at end of file diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp index 80ab4002..c7663201 100644 --- a/NorthstarDedicatedTest/dedicated.cpp +++ b/NorthstarDedicatedTest/dedicated.cpp @@ -7,7 +7,7 @@ bool IsDedicated() { // temp: should get this from commandline - //return true; + return true; return false; } @@ -20,9 +20,18 @@ enum EngineState_t DLL_PAUSED, // engine is paused, can become active from this state }; +struct CEngine +{ +public: + char unknown[12]; + + EngineState_t m_nDllState; + EngineState_t m_nNextDllState; +}; + void InitialiseDedicated(HMODULE engineAddress) { - std::cout << "InitialiseDedicated()" << std::endl; + spdlog::info("InitialiseDedicated"); while (!IsDebuggerPresent()) Sleep(100); @@ -66,6 +75,32 @@ void InitialiseDedicated(HMODULE engineAddress) *(ptr + 4) = (char)0x90; } + { + // runframeserver + char* ptr = (char*)engineAddress + 0x159819; + TempReadWrite rw(ptr); + + // nop some access violations + *ptr = (char)0x90; + *(ptr + 1) = (char)0x90; + *(ptr + 2) = (char)0x90; + *(ptr + 3) = (char)0x90; + *(ptr + 4) = (char)0x90; + *(ptr + 5) = (char)0x90; + *(ptr + 6) = (char)0x90; + *(ptr + 7) = (char)0x90; + *(ptr + 8) = (char)0x90; + *(ptr + 9) = (char)0x90; + *(ptr + 10) = (char)0x90; + *(ptr + 11) = (char)0x90; + *(ptr + 12) = (char)0x90; + *(ptr + 13) = (char)0x90; + *(ptr + 14) = (char)0x90; + *(ptr + 15) = (char)0x90; + *(ptr + 16) = (char)0x90; + } + + CDedicatedExports* dedicatedApi = new CDedicatedExports; dedicatedApi->Sys_Printf = Sys_Printf; dedicatedApi->RunServer = RunServer; @@ -100,16 +135,16 @@ void RunServer(CDedicatedExports* dedicated) CEngine__Frame engineFrame = (CEngine__Frame)((char*)engine + 0x1C8650); CEngineAPI__ActivateSimulation engineApiStartSimulation = (CEngineAPI__ActivateSimulation)((char*)engine + 0x1C4370); - void* cEnginePtr = (void*)((char*)engine + 0x7D70C8); + CEngine* cEnginePtr = (CEngine*)((char*)engine + 0x7D70C8); CEngineAPI__SetMap engineApiSetMap = (CEngineAPI__SetMap)((char*)engine + 0x1C7B30); - - engineApiSetMap(nullptr, "mp_thaw"); - Sys_Printf(dedicated, (char*)"CDedicatedServerAPI::RunServer(): map mp_lobby"); + + // call once to init + engineFrame(cEnginePtr); // allow us to hit CHostState::FrameUpdate - //*((int*)((char*)cEnginePtr + 12)) = 2; - //*((int*)((char*)cEnginePtr + 16)) = 2; + cEnginePtr->m_nDllState = EngineState_t::DLL_ACTIVE; + cEnginePtr->m_nNextDllState = EngineState_t::DLL_ACTIVE; while (true) { diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index 8cea40a0..12268d85 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -28,7 +28,6 @@ BOOL APIENTRY DllMain( HMODULE hModule, { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: - DisableThreadLibraryCalls(hModule); case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; diff --git a/NorthstarDedicatedTest/modlocalisation.cpp b/NorthstarDedicatedTest/modlocalisation.cpp index ccc06722..25c9e19f 100644 --- a/NorthstarDedicatedTest/modlocalisation.cpp +++ b/NorthstarDedicatedTest/modlocalisation.cpp @@ -3,14 +3,17 @@ #include "hookutils.h" #include "modmanager.h" -typedef char(*AddLocalisationFileType)(void* g_pVguiLocalize, const char* path, const char* pathId); +typedef bool(*AddLocalisationFileType)(void* g_pVguiLocalize, const char* path, const char* pathId, char unknown); AddLocalisationFileType AddLocalisationFile; bool loadModLocalisationFiles = true; -char AddLocalisationFileHook(void* g_pVguiLocalize, const char* path, char* pathId) +bool AddLocalisationFileHook(void* g_pVguiLocalize, const char* path, const char* pathId, char unknown) { - char ret = AddLocalisationFile(g_pVguiLocalize, path, pathId); + bool ret = AddLocalisationFile(g_pVguiLocalize, path, pathId, unknown); + + if (ret) + spdlog::info("Loaded localisation file {} successfully", path); if (!loadModLocalisationFiles) return ret; @@ -18,13 +21,8 @@ char AddLocalisationFileHook(void* g_pVguiLocalize, const char* path, char* path loadModLocalisationFiles = false; for (Mod* mod : g_ModManager->m_loadedMods) - { for (std::string& localisationFile : mod->LocalisationFiles) - { - spdlog::info("Adding mod localisation file {}", localisationFile); - AddLocalisationFile(g_pVguiLocalize, localisationFile.c_str(), pathId); - } - } + AddLocalisationFile(g_pVguiLocalize, localisationFile.c_str(), pathId, unknown); loadModLocalisationFiles = true; diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp index 68d98455..6dd44284 100644 --- a/NorthstarDedicatedTest/serverauthentication.cpp +++ b/NorthstarDedicatedTest/serverauthentication.cpp @@ -32,6 +32,7 @@ CGameClient__ExecuteStringCommandType CGameClient__ExecuteStringCommand; ServerAuthenticationManager* g_ServerAuthenticationManager; ConVar* Cvar_ns_player_auth_port; +ConVar* Cvar_ns_erase_auth_info; ConVar* CVar_ns_auth_allow_insecure; ConVar* CVar_ns_auth_allow_insecure_write; ConVar* CVar_sv_quota_stringcmdspersecond; @@ -150,6 +151,9 @@ bool ServerAuthenticationManager::AuthenticatePlayer(void* player, int64_t uid, bool ServerAuthenticationManager::RemovePlayerAuthData(void* player) { + if (!Cvar_ns_erase_auth_info->m_nValue) + return false; + // we don't have our auth token at this point, so lookup authdata by uid for (auto& auth : m_authData) { @@ -292,11 +296,12 @@ void InitialiseServerAuthentication(HMODULE baseAddress) { g_ServerAuthenticationManager = new ServerAuthenticationManager; + Cvar_ns_erase_auth_info = RegisterConVar("ns_erase_auth_info", "1", FCVAR_GAMEDLL, "Whether auth info should be erased from this server on disconnect or crash"); CVar_ns_auth_allow_insecure = RegisterConVar("ns_auth_allow_insecure", "0", FCVAR_GAMEDLL, "Whether this server will allow unauthenicated players to connect"); CVar_ns_auth_allow_insecure_write = RegisterConVar("ns_auth_allow_insecure_write", "0", FCVAR_GAMEDLL, "Whether the pdata of unauthenticated clients will be written to disk when changed"); // literally just stolen from a fix valve used in csgo CVar_sv_quota_stringcmdspersecond = RegisterConVar("sv_quota_stringcmdspersecond", "60", FCVAR_NONE, "How many string commands per second clients are allowed to submit, 0 to disallow all string commands"); - Cvar_ns_player_auth_port = RegisterConVar("Cvar_ns_player_auth_port", "8081", FCVAR_GAMEDLL, ""); + Cvar_ns_player_auth_port = RegisterConVar("ns_player_auth_port", "8081", FCVAR_GAMEDLL, ""); HookEnabler hook; ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x114430, &CBaseServer__ConnectClientHook, reinterpret_cast<LPVOID*>(&CBaseServer__ConnectClient)); diff --git a/R2Northstar.sln b/R2Northstar.sln index 8c259ed0..09004f71 100644 --- a/R2Northstar.sln +++ b/R2Northstar.sln @@ -9,6 +9,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InjectorTest", "InjectorTes EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Injector", "Injector", "{DEFD24BD-9918-4DC1-BAD5-3F3A49E467E9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LauncherInjector", "LauncherInjector\LauncherInjector.vcxproj", "{0EA82CB0-53FE-4D4C-96DF-47FA970513D0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameInjector", "GameInjector\GameInjector.vcxproj", "{B3554508-967E-49D2-BF87-586DD95D817C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InjectionProxy64", "InjectionProxy64\InjectionProxy64.vcxproj", "{A8CE6730-A6C7-441D-8C65-8A39EE5A01A2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -20,7 +26,6 @@ Global {CFAD2623-064F-453C-8196-79EE10292E32}.Debug|x64.ActiveCfg = Debug|x64 {CFAD2623-064F-453C-8196-79EE10292E32}.Debug|x64.Build.0 = Debug|x64 {CFAD2623-064F-453C-8196-79EE10292E32}.Debug|x86.ActiveCfg = Debug|Win32 - {CFAD2623-064F-453C-8196-79EE10292E32}.Debug|x86.Build.0 = Debug|Win32 {CFAD2623-064F-453C-8196-79EE10292E32}.Release|x64.ActiveCfg = Release|x64 {CFAD2623-064F-453C-8196-79EE10292E32}.Release|x64.Build.0 = Release|x64 {CFAD2623-064F-453C-8196-79EE10292E32}.Release|x86.ActiveCfg = Release|Win32 @@ -33,12 +38,39 @@ Global {3C3FC37C-D4B9-4413-AADF-C52FD2F428E6}.Release|x64.Build.0 = Release|x64 {3C3FC37C-D4B9-4413-AADF-C52FD2F428E6}.Release|x86.ActiveCfg = Release|Win32 {3C3FC37C-D4B9-4413-AADF-C52FD2F428E6}.Release|x86.Build.0 = Release|Win32 + {0EA82CB0-53FE-4D4C-96DF-47FA970513D0}.Debug|x64.ActiveCfg = Debug|Win32 + {0EA82CB0-53FE-4D4C-96DF-47FA970513D0}.Debug|x64.Build.0 = Debug|Win32 + {0EA82CB0-53FE-4D4C-96DF-47FA970513D0}.Debug|x86.ActiveCfg = Debug|Win32 + {0EA82CB0-53FE-4D4C-96DF-47FA970513D0}.Debug|x86.Build.0 = Debug|Win32 + {0EA82CB0-53FE-4D4C-96DF-47FA970513D0}.Release|x64.ActiveCfg = Release|Win32 + {0EA82CB0-53FE-4D4C-96DF-47FA970513D0}.Release|x64.Build.0 = Release|Win32 + {0EA82CB0-53FE-4D4C-96DF-47FA970513D0}.Release|x86.ActiveCfg = Release|Win32 + {0EA82CB0-53FE-4D4C-96DF-47FA970513D0}.Release|x86.Build.0 = Release|Win32 + {B3554508-967E-49D2-BF87-586DD95D817C}.Debug|x64.ActiveCfg = Debug|Win32 + {B3554508-967E-49D2-BF87-586DD95D817C}.Debug|x64.Build.0 = Debug|Win32 + {B3554508-967E-49D2-BF87-586DD95D817C}.Debug|x86.ActiveCfg = Debug|Win32 + {B3554508-967E-49D2-BF87-586DD95D817C}.Debug|x86.Build.0 = Debug|Win32 + {B3554508-967E-49D2-BF87-586DD95D817C}.Release|x64.ActiveCfg = Release|Win32 + {B3554508-967E-49D2-BF87-586DD95D817C}.Release|x64.Build.0 = Release|Win32 + {B3554508-967E-49D2-BF87-586DD95D817C}.Release|x86.ActiveCfg = Release|Win32 + {B3554508-967E-49D2-BF87-586DD95D817C}.Release|x86.Build.0 = Release|Win32 + {A8CE6730-A6C7-441D-8C65-8A39EE5A01A2}.Debug|x64.ActiveCfg = Debug|x64 + {A8CE6730-A6C7-441D-8C65-8A39EE5A01A2}.Debug|x64.Build.0 = Debug|x64 + {A8CE6730-A6C7-441D-8C65-8A39EE5A01A2}.Debug|x86.ActiveCfg = Debug|Win32 + {A8CE6730-A6C7-441D-8C65-8A39EE5A01A2}.Debug|x86.Build.0 = Debug|Win32 + {A8CE6730-A6C7-441D-8C65-8A39EE5A01A2}.Release|x64.ActiveCfg = Release|x64 + {A8CE6730-A6C7-441D-8C65-8A39EE5A01A2}.Release|x64.Build.0 = Release|x64 + {A8CE6730-A6C7-441D-8C65-8A39EE5A01A2}.Release|x86.ActiveCfg = Release|Win32 + {A8CE6730-A6C7-441D-8C65-8A39EE5A01A2}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {3C3FC37C-D4B9-4413-AADF-C52FD2F428E6} = {DEFD24BD-9918-4DC1-BAD5-3F3A49E467E9} + {0EA82CB0-53FE-4D4C-96DF-47FA970513D0} = {DEFD24BD-9918-4DC1-BAD5-3F3A49E467E9} + {B3554508-967E-49D2-BF87-586DD95D817C} = {DEFD24BD-9918-4DC1-BAD5-3F3A49E467E9} + {A8CE6730-A6C7-441D-8C65-8A39EE5A01A2} = {DEFD24BD-9918-4DC1-BAD5-3F3A49E467E9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E617E95C-9157-454C-84C5-8EEC2B5D1032} |