Skip to content

Commit

Permalink
Added security features to the loader
Browse files Browse the repository at this point in the history
  • Loading branch information
ccw808 committed Aug 1, 2016
1 parent fbc1628 commit dd0d929
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 61 deletions.
6 changes: 3 additions & 3 deletions Client/loader/CInstallManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ namespace
void UpdateSettingsForReportLog ( void )
{
UpdateMTAVersionApplicationSetting ();
SetApplicationSetting ( "os-version", GetOSVersion () );
SetApplicationSetting ( "real-os-version", GetRealOSVersion () );
SetApplicationSetting ( "os-version", SString ( "%d.%d", GetOSVersion ().dwMajor, GetOSVersion ().dwMinor ) );
SetApplicationSetting ( "real-os-version", SString ( "%d.%d", GetRealOSVersion ().dwMajor, GetRealOSVersion ().dwMinor ) );
SetApplicationSetting ( "is-admin", IsUserAdmin () ? "1" : "0" );
SetApplicationSettingInt ( "last-server-ip", 0 );
SetApplicationSetting ( "real-os-build", GetRealOSBuildNumber () );
SetApplicationSetting ( "real-os-build", SString ( "%d", GetRealOSVersion ().dwBuild ) );
SetApplicationSettingInt ( "vs2013-runtime-installed", IsVS2013RuntimeInstalled () ? 1 : 0 );
}

Expand Down
2 changes: 1 addition & 1 deletion Client/loader/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ int DoWinMain ( HINSTANCE hLauncherInstance, HINSTANCE hPrevInstance, LPSTR lpCm
// Maybe show help if trouble was encountered
ProcessPendingBrowseToSolution();

AddReportLog ( 1044, SString ( "* End (%d)* pid:%d", iReturnCode, GetCurrentProcessId() ) );
AddReportLog ( 1044, SString ( "* End (0x%X)* pid:%d", iReturnCode, GetCurrentProcessId() ) );

RemoveUtf8FileHooks();
return iReturnCode;
Expand Down
161 changes: 143 additions & 18 deletions Client/loader/MainFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,136 @@ void CheckLibVersions( void )
}


//////////////////////////////////////////////////////////
//
// CreateProcessWithMitigationPolicy
//
// Create process with extra security stuff
//
//////////////////////////////////////////////////////////
BOOL CreateProcessWithMitigationPolicy (
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPPROCESS_INFORMATION lpProcessInformation,
DWORD& dwOutError,
SString& strOutErrorContext
)
{
DWORD64 MitigationPolicy = 0;
STARTUPINFOEXW StartupInfoEx = { 0 };
StartupInfoEx.StartupInfo.cb = sizeof ( StartupInfoEx.StartupInfo );

if ( IsWindowsVistaOrGreater () )
{
// We can use extended startup info for Vista and up
StartupInfoEx.StartupInfo.cb = sizeof ( StartupInfoEx );
dwCreationFlags |= EXTENDED_STARTUPINFO_PRESENT;

// Win7 32 bit can only handle DWORD MitigationPolicy
size_t MitigationPolicySize = sizeof ( DWORD );
MitigationPolicy |= PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE
| PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE
| PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE;

if ( IsWindows8OrGreater () )
{
// We can use more bigger MitigationPolicy for Win8 and up
MitigationPolicySize = sizeof( DWORD64 );
MitigationPolicy |= PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON;
}

if ( IsWindows10OrGreater () )
{
// Win 10
MitigationPolicy |= PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_ALWAYS_ON;
}

if ( IsWindows10Threshold2OrGreater () )
{
// Win 10 build something
MitigationPolicy |= PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_ALWAYS_ON;
}

#if 0 // TODO
if ( IsWindows10FoamybananaOrGreater () )
{
// Win 10 build something else
MitigationPolicy |= PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON;
}
#endif

// Create AttributeList for mitigation policy application system
SIZE_T AttributeListSize;
if ( _InitializeProcThreadAttributeList ( nullptr, 1, 0, &AttributeListSize ) == FALSE )
{
dwOutError = GetLastError ();
if ( dwOutError != ERROR_INSUFFICIENT_BUFFER )
{
strOutErrorContext = "InitializeProcThreadAttributeList #1";
return false;
}
}
else
{
dwOutError = ERROR_SUCCESS;
strOutErrorContext = "InitializeProcThreadAttributeList #1 expected error";
return false;
}

StartupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc ( GetProcessHeap () ,0, AttributeListSize );

if ( _InitializeProcThreadAttributeList ( StartupInfoEx. lpAttributeList, 1, 0, &AttributeListSize ) == FALSE )
{
dwOutError = GetLastError ();
strOutErrorContext = "InitializeProcThreadAttributeList #2";
HeapFree ( GetProcessHeap (), 0, (LPVOID)StartupInfoEx.lpAttributeList );
return false;
}

if ( _UpdateProcThreadAttribute ( StartupInfoEx.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &MitigationPolicy, MitigationPolicySize, nullptr, nullptr ) == FALSE )
{
dwOutError = GetLastError ();
strOutErrorContext = "UpdateProcThreadAttribute";
_DeleteProcThreadAttributeList ( StartupInfoEx.lpAttributeList );
HeapFree ( GetProcessHeap (), 0, (LPVOID)StartupInfoEx.lpAttributeList );
return false;
}
}

// Start GTA
BOOL bResult = _CreateProcessW ( lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
nullptr,
lpCurrentDirectory,
(LPSTARTUPINFOW)&StartupInfoEx,
lpProcessInformation );

if ( bResult == FALSE )
{
dwOutError = GetLastError ();
strOutErrorContext = "CreateProcess";
}

if ( IsWindowsVistaOrGreater () )
{
// Clean up
_DeleteProcThreadAttributeList ( StartupInfoEx.lpAttributeList );
HeapFree ( GetProcessHeap (), 0, (LPVOID)StartupInfoEx.lpAttributeList );
}
return bResult;
}


//////////////////////////////////////////////////////////
//
// LaunchGame
Expand Down Expand Up @@ -948,17 +1078,6 @@ int LaunchGame ( SString strCmdLine )
SString strGTAEXEPath = GetInstallManager()->MaybeRenameExe( strGTAPath );
SetCurrentDirectory ( strGTAPath );

//////////////////////////////////////////////////////////
//
// Hook 'n' go
//
// Launch GTA using CreateProcess
PROCESS_INFORMATION piLoadee;
STARTUPINFOW siLoadee;
memset( &piLoadee, 0, sizeof ( PROCESS_INFORMATION ) );
memset( &siLoadee, 0, sizeof ( STARTUPINFO ) );
siLoadee.cb = sizeof ( STARTUPINFO );

WatchDogBeginSection ( "L2" ); // Gets closed when loading screen is shown
WatchDogBeginSection ( "L3" ); // Gets closed when loading screen is shown, or a startup problem is handled elsewhere
WatchDogBeginSection ( WD_SECTION_NOT_USED_MAIN_MENU ); // Gets closed when the main menu is used
Expand All @@ -974,20 +1093,26 @@ int LaunchGame ( SString strCmdLine )

WString wstrCmdLine = FromUTF8( strCmdLine );

// Start GTA
if ( 0 == _CreateProcessW( FromUTF8( strGTAEXEPath ),
//
// Launch GTA using CreateProcess
//
PROCESS_INFORMATION piLoadee = { 0 };
DWORD dwError;
SString strErrorContext;
if ( FALSE == CreateProcessWithMitigationPolicy (
FromUTF8( strGTAEXEPath ),
(LPWSTR)*wstrCmdLine,
NULL,
NULL,
FALSE,
CREATE_SUSPENDED,
NULL,
FromUTF8( strMtaDir ), // strMTASAPath\mta is used so pthreadVC2.dll can be found
&siLoadee,
&piLoadee ) )
&piLoadee,
dwError,
strErrorContext ) )
{
DWORD dwError = GetLastError ();
WriteDebugEvent( SString( "Loader - Process not created[%d]: %s", dwError, *strGTAEXEPath ) );
WriteDebugEvent( SString( "Loader - Process not created[%d (%s)]: %s", dwError, *strErrorContext, *strGTAEXEPath ) );

if ( dwError == ERROR_ELEVATION_REQUIRED && !bDoneAdmin )
{
Expand All @@ -999,7 +1124,7 @@ int LaunchGame ( SString strCmdLine )
else
{
// Otherwise, show error message
SString strError = GetSystemErrorMessage ( dwError );
SString strError = GetSystemErrorMessage ( dwError ) + " (" + strErrorContext + ")";
DisplayErrorMessageBox ( SString(_("Could not start Grand Theft Auto: San Andreas. "
"Please try restarting, or if the problem persists,"
"contact MTA at www.multitheftauto.com. \n\n[%s]"),*strError), _E("CL22"), "createprocess-fail&err=" + strError ); // Could not start GTA:SA
Expand Down
69 changes: 33 additions & 36 deletions Client/loader/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ HMODULE RemoteLoadLibrary(HANDLE hProcess, const WString& strLibPath)
// Ensure correct pthreadVC2.dll is gotted
CallRemoteFunction( hProcess, "SetDllDirectoryW", FromUTF8( ExtractPath( ToUTF8( strLibPath ) ) ) );
CallRemoteFunction( hProcess, "LoadLibraryW", strLibPath );
CheckService( CHECK_SERVICE_POST_CREATE );

// Allow GTA to continue
RemoveWinMainBlock( hProcess );
Expand Down Expand Up @@ -1060,13 +1061,13 @@ void MakeRandomIndexList ( int Size, std::vector < int >& outList )
// Affected by compatibility mode
//
///////////////////////////////////////////////////////////////
SString GetOSVersion ( void )
SOSVersionInfo GetOSVersion ( void )
{
OSVERSIONINFO versionInfo;
memset ( &versionInfo, 0, sizeof ( versionInfo ) );
versionInfo.dwOSVersionInfoSize = sizeof ( versionInfo );
GetVersionEx ( &versionInfo );
return SString ( "%d.%d", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion );
return { versionInfo.dwMajorVersion, versionInfo.dwMinorVersion, versionInfo.dwBuildNumber };
}


Expand All @@ -1077,48 +1078,37 @@ SString GetOSVersion ( void )
// Ignoring compatibility mode
//
///////////////////////////////////////////////////////////////
SString GetRealOSVersion ( void )
SOSVersionInfo GetRealOSVersion ( void )
{
SString strVersionAndBuild = GetWMIOSVersion ();
std::vector < SString > parts;
strVersionAndBuild.Split ( ".", parts );
uint uiMajor = parts.size () > 0 ? atoi ( parts[0] ) : 0;
uint uiMinor = parts.size () > 1 ? atoi ( parts[1] ) : 0;
static SOSVersionInfo versionInfo = { 0 };

if ( uiMajor == 0 )
// Try WMI first
if ( versionInfo.dwMajor == 0 )
{
SLibVersionInfo fileInfo;
if ( GetLibVersionInfo ( "ntdll.dll", &fileInfo ) )
SString strVersionAndBuild = GetWMIOSVersion ();
std::vector < SString > parts;
strVersionAndBuild.Split ( ".", parts );
if ( parts.size () == 3 )
{
uiMajor = HIWORD( fileInfo.dwFileVersionMS );
uiMinor = LOWORD( fileInfo.dwFileVersionMS );
versionInfo.dwMajor = atoi ( parts[0] );
versionInfo.dwMinor = atoi ( parts[1] );
versionInfo.dwBuild = atoi ( parts[2] );
}
}

return SString ( "%u.%u", uiMajor, uiMinor );
}


///////////////////////////////////////////////////////////////
//
// GetRealOSBuildNumber
//
// Ignoring compatibility mode
//
///////////////////////////////////////////////////////////////
SString GetRealOSBuildNumber( void )
{
uint uiBuild = 0;
uint uiRev = 0;

SLibVersionInfo fileInfo;
if ( GetLibVersionInfo( "ntdll.dll", &fileInfo ) )
// Fallback to checking file version of kernel32.dll
if ( versionInfo.dwMajor == 0 )
{
uiBuild = HIWORD( fileInfo.dwFileVersionLS );
uiRev = LOWORD( fileInfo.dwFileVersionLS );
SLibVersionInfo fileInfo;
if ( GetLibVersionInfo ( "kernel32.dll", &fileInfo ) )
{
versionInfo.dwMajor = HIWORD ( fileInfo.dwFileVersionMS );
versionInfo.dwMinor = LOWORD ( fileInfo.dwFileVersionMS );
versionInfo.dwBuild = HIWORD ( fileInfo.dwFileVersionLS );
}
}

return SString( "%u.%u", uiBuild, uiRev );
return versionInfo;
}


Expand All @@ -1129,9 +1119,16 @@ SString GetRealOSBuildNumber( void )
// Works around limit for applications not manifested for Windows 10
//
///////////////////////////////////////////////////////////////
bool IsWindows10OrGreater( void )
bool IsWindows10OrGreater ( void )
{
SOSVersionInfo info = GetRealOSVersion ();
return info.dwMajor >= 10;
}

bool IsWindows10Threshold2OrGreater ( void )
{
return atoi( GetRealOSVersion() ) >= 10;
SOSVersionInfo info = GetRealOSVersion ();
return info.dwMajor > 10 || ( info.dwMajor == 10 && info.dwBuild >= 10586 );
}


Expand Down

0 comments on commit dd0d929

Please sign in to comment.