Skip to content

Commit dd0d929

Browse files
committed
Added security features to the loader
1 parent fbc1628 commit dd0d929

File tree

5 files changed

+235
-61
lines changed

5 files changed

+235
-61
lines changed

Client/loader/CInstallManager.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ namespace
2626
void UpdateSettingsForReportLog ( void )
2727
{
2828
UpdateMTAVersionApplicationSetting ();
29-
SetApplicationSetting ( "os-version", GetOSVersion () );
30-
SetApplicationSetting ( "real-os-version", GetRealOSVersion () );
29+
SetApplicationSetting ( "os-version", SString ( "%d.%d", GetOSVersion ().dwMajor, GetOSVersion ().dwMinor ) );
30+
SetApplicationSetting ( "real-os-version", SString ( "%d.%d", GetRealOSVersion ().dwMajor, GetRealOSVersion ().dwMinor ) );
3131
SetApplicationSetting ( "is-admin", IsUserAdmin () ? "1" : "0" );
3232
SetApplicationSettingInt ( "last-server-ip", 0 );
33-
SetApplicationSetting ( "real-os-build", GetRealOSBuildNumber () );
33+
SetApplicationSetting ( "real-os-build", SString ( "%d", GetRealOSVersion ().dwBuild ) );
3434
SetApplicationSettingInt ( "vs2013-runtime-installed", IsVS2013RuntimeInstalled () ? 1 : 0 );
3535
}
3636

Client/loader/Main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ int DoWinMain ( HINSTANCE hLauncherInstance, HINSTANCE hPrevInstance, LPSTR lpCm
120120
// Maybe show help if trouble was encountered
121121
ProcessPendingBrowseToSolution();
122122

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

125125
RemoveUtf8FileHooks();
126126
return iReturnCode;

Client/loader/MainFunctions.cpp

Lines changed: 143 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,136 @@ void CheckLibVersions( void )
920920
}
921921

922922

923+
//////////////////////////////////////////////////////////
924+
//
925+
// CreateProcessWithMitigationPolicy
926+
//
927+
// Create process with extra security stuff
928+
//
929+
//////////////////////////////////////////////////////////
930+
BOOL CreateProcessWithMitigationPolicy (
931+
LPCWSTR lpApplicationName,
932+
LPWSTR lpCommandLine,
933+
LPSECURITY_ATTRIBUTES lpProcessAttributes,
934+
LPSECURITY_ATTRIBUTES lpThreadAttributes,
935+
BOOL bInheritHandles,
936+
DWORD dwCreationFlags,
937+
LPVOID lpEnvironment,
938+
LPCWSTR lpCurrentDirectory,
939+
LPPROCESS_INFORMATION lpProcessInformation,
940+
DWORD& dwOutError,
941+
SString& strOutErrorContext
942+
)
943+
{
944+
DWORD64 MitigationPolicy = 0;
945+
STARTUPINFOEXW StartupInfoEx = { 0 };
946+
StartupInfoEx.StartupInfo.cb = sizeof ( StartupInfoEx.StartupInfo );
947+
948+
if ( IsWindowsVistaOrGreater () )
949+
{
950+
// We can use extended startup info for Vista and up
951+
StartupInfoEx.StartupInfo.cb = sizeof ( StartupInfoEx );
952+
dwCreationFlags |= EXTENDED_STARTUPINFO_PRESENT;
953+
954+
// Win7 32 bit can only handle DWORD MitigationPolicy
955+
size_t MitigationPolicySize = sizeof ( DWORD );
956+
MitigationPolicy |= PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE
957+
| PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE
958+
| PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE;
959+
960+
if ( IsWindows8OrGreater () )
961+
{
962+
// We can use more bigger MitigationPolicy for Win8 and up
963+
MitigationPolicySize = sizeof( DWORD64 );
964+
MitigationPolicy |= PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON;
965+
}
966+
967+
if ( IsWindows10OrGreater () )
968+
{
969+
// Win 10
970+
MitigationPolicy |= PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_ALWAYS_ON;
971+
}
972+
973+
if ( IsWindows10Threshold2OrGreater () )
974+
{
975+
// Win 10 build something
976+
MitigationPolicy |= PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_ALWAYS_ON;
977+
}
978+
979+
#if 0 // TODO
980+
if ( IsWindows10FoamybananaOrGreater () )
981+
{
982+
// Win 10 build something else
983+
MitigationPolicy |= PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON;
984+
}
985+
#endif
986+
987+
// Create AttributeList for mitigation policy application system
988+
SIZE_T AttributeListSize;
989+
if ( _InitializeProcThreadAttributeList ( nullptr, 1, 0, &AttributeListSize ) == FALSE )
990+
{
991+
dwOutError = GetLastError ();
992+
if ( dwOutError != ERROR_INSUFFICIENT_BUFFER )
993+
{
994+
strOutErrorContext = "InitializeProcThreadAttributeList #1";
995+
return false;
996+
}
997+
}
998+
else
999+
{
1000+
dwOutError = ERROR_SUCCESS;
1001+
strOutErrorContext = "InitializeProcThreadAttributeList #1 expected error";
1002+
return false;
1003+
}
1004+
1005+
StartupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc ( GetProcessHeap () ,0, AttributeListSize );
1006+
1007+
if ( _InitializeProcThreadAttributeList ( StartupInfoEx. lpAttributeList, 1, 0, &AttributeListSize ) == FALSE )
1008+
{
1009+
dwOutError = GetLastError ();
1010+
strOutErrorContext = "InitializeProcThreadAttributeList #2";
1011+
HeapFree ( GetProcessHeap (), 0, (LPVOID)StartupInfoEx.lpAttributeList );
1012+
return false;
1013+
}
1014+
1015+
if ( _UpdateProcThreadAttribute ( StartupInfoEx.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &MitigationPolicy, MitigationPolicySize, nullptr, nullptr ) == FALSE )
1016+
{
1017+
dwOutError = GetLastError ();
1018+
strOutErrorContext = "UpdateProcThreadAttribute";
1019+
_DeleteProcThreadAttributeList ( StartupInfoEx.lpAttributeList );
1020+
HeapFree ( GetProcessHeap (), 0, (LPVOID)StartupInfoEx.lpAttributeList );
1021+
return false;
1022+
}
1023+
}
1024+
1025+
// Start GTA
1026+
BOOL bResult = _CreateProcessW ( lpApplicationName,
1027+
lpCommandLine,
1028+
lpProcessAttributes,
1029+
lpThreadAttributes,
1030+
bInheritHandles,
1031+
dwCreationFlags,
1032+
nullptr,
1033+
lpCurrentDirectory,
1034+
(LPSTARTUPINFOW)&StartupInfoEx,
1035+
lpProcessInformation );
1036+
1037+
if ( bResult == FALSE )
1038+
{
1039+
dwOutError = GetLastError ();
1040+
strOutErrorContext = "CreateProcess";
1041+
}
1042+
1043+
if ( IsWindowsVistaOrGreater () )
1044+
{
1045+
// Clean up
1046+
_DeleteProcThreadAttributeList ( StartupInfoEx.lpAttributeList );
1047+
HeapFree ( GetProcessHeap (), 0, (LPVOID)StartupInfoEx.lpAttributeList );
1048+
}
1049+
return bResult;
1050+
}
1051+
1052+
9231053
//////////////////////////////////////////////////////////
9241054
//
9251055
// LaunchGame
@@ -948,17 +1078,6 @@ int LaunchGame ( SString strCmdLine )
9481078
SString strGTAEXEPath = GetInstallManager()->MaybeRenameExe( strGTAPath );
9491079
SetCurrentDirectory ( strGTAPath );
9501080

951-
//////////////////////////////////////////////////////////
952-
//
953-
// Hook 'n' go
954-
//
955-
// Launch GTA using CreateProcess
956-
PROCESS_INFORMATION piLoadee;
957-
STARTUPINFOW siLoadee;
958-
memset( &piLoadee, 0, sizeof ( PROCESS_INFORMATION ) );
959-
memset( &siLoadee, 0, sizeof ( STARTUPINFO ) );
960-
siLoadee.cb = sizeof ( STARTUPINFO );
961-
9621081
WatchDogBeginSection ( "L2" ); // Gets closed when loading screen is shown
9631082
WatchDogBeginSection ( "L3" ); // Gets closed when loading screen is shown, or a startup problem is handled elsewhere
9641083
WatchDogBeginSection ( WD_SECTION_NOT_USED_MAIN_MENU ); // Gets closed when the main menu is used
@@ -974,20 +1093,26 @@ int LaunchGame ( SString strCmdLine )
9741093

9751094
WString wstrCmdLine = FromUTF8( strCmdLine );
9761095

977-
// Start GTA
978-
if ( 0 == _CreateProcessW( FromUTF8( strGTAEXEPath ),
1096+
//
1097+
// Launch GTA using CreateProcess
1098+
//
1099+
PROCESS_INFORMATION piLoadee = { 0 };
1100+
DWORD dwError;
1101+
SString strErrorContext;
1102+
if ( FALSE == CreateProcessWithMitigationPolicy (
1103+
FromUTF8( strGTAEXEPath ),
9791104
(LPWSTR)*wstrCmdLine,
9801105
NULL,
9811106
NULL,
9821107
FALSE,
9831108
CREATE_SUSPENDED,
9841109
NULL,
9851110
FromUTF8( strMtaDir ), // strMTASAPath\mta is used so pthreadVC2.dll can be found
986-
&siLoadee,
987-
&piLoadee ) )
1111+
&piLoadee,
1112+
dwError,
1113+
strErrorContext ) )
9881114
{
989-
DWORD dwError = GetLastError ();
990-
WriteDebugEvent( SString( "Loader - Process not created[%d]: %s", dwError, *strGTAEXEPath ) );
1115+
WriteDebugEvent( SString( "Loader - Process not created[%d (%s)]: %s", dwError, *strErrorContext, *strGTAEXEPath ) );
9911116

9921117
if ( dwError == ERROR_ELEVATION_REQUIRED && !bDoneAdmin )
9931118
{
@@ -999,7 +1124,7 @@ int LaunchGame ( SString strCmdLine )
9991124
else
10001125
{
10011126
// Otherwise, show error message
1002-
SString strError = GetSystemErrorMessage ( dwError );
1127+
SString strError = GetSystemErrorMessage ( dwError ) + " (" + strErrorContext + ")";
10031128
DisplayErrorMessageBox ( SString(_("Could not start Grand Theft Auto: San Andreas. "
10041129
"Please try restarting, or if the problem persists,"
10051130
"contact MTA at www.multitheftauto.com. \n\n[%s]"),*strError), _E("CL22"), "createprocess-fail&err=" + strError ); // Could not start GTA:SA

Client/loader/Utils.cpp

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ HMODULE RemoteLoadLibrary(HANDLE hProcess, const WString& strLibPath)
114114
// Ensure correct pthreadVC2.dll is gotted
115115
CallRemoteFunction( hProcess, "SetDllDirectoryW", FromUTF8( ExtractPath( ToUTF8( strLibPath ) ) ) );
116116
CallRemoteFunction( hProcess, "LoadLibraryW", strLibPath );
117+
CheckService( CHECK_SERVICE_POST_CREATE );
117118

118119
// Allow GTA to continue
119120
RemoveWinMainBlock( hProcess );
@@ -1060,13 +1061,13 @@ void MakeRandomIndexList ( int Size, std::vector < int >& outList )
10601061
// Affected by compatibility mode
10611062
//
10621063
///////////////////////////////////////////////////////////////
1063-
SString GetOSVersion ( void )
1064+
SOSVersionInfo GetOSVersion ( void )
10641065
{
10651066
OSVERSIONINFO versionInfo;
10661067
memset ( &versionInfo, 0, sizeof ( versionInfo ) );
10671068
versionInfo.dwOSVersionInfoSize = sizeof ( versionInfo );
10681069
GetVersionEx ( &versionInfo );
1069-
return SString ( "%d.%d", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion );
1070+
return { versionInfo.dwMajorVersion, versionInfo.dwMinorVersion, versionInfo.dwBuildNumber };
10701071
}
10711072

10721073

@@ -1077,48 +1078,37 @@ SString GetOSVersion ( void )
10771078
// Ignoring compatibility mode
10781079
//
10791080
///////////////////////////////////////////////////////////////
1080-
SString GetRealOSVersion ( void )
1081+
SOSVersionInfo GetRealOSVersion ( void )
10811082
{
1082-
SString strVersionAndBuild = GetWMIOSVersion ();
1083-
std::vector < SString > parts;
1084-
strVersionAndBuild.Split ( ".", parts );
1085-
uint uiMajor = parts.size () > 0 ? atoi ( parts[0] ) : 0;
1086-
uint uiMinor = parts.size () > 1 ? atoi ( parts[1] ) : 0;
1083+
static SOSVersionInfo versionInfo = { 0 };
10871084

1088-
if ( uiMajor == 0 )
1085+
// Try WMI first
1086+
if ( versionInfo.dwMajor == 0 )
10891087
{
1090-
SLibVersionInfo fileInfo;
1091-
if ( GetLibVersionInfo ( "ntdll.dll", &fileInfo ) )
1088+
SString strVersionAndBuild = GetWMIOSVersion ();
1089+
std::vector < SString > parts;
1090+
strVersionAndBuild.Split ( ".", parts );
1091+
if ( parts.size () == 3 )
10921092
{
1093-
uiMajor = HIWORD( fileInfo.dwFileVersionMS );
1094-
uiMinor = LOWORD( fileInfo.dwFileVersionMS );
1093+
versionInfo.dwMajor = atoi ( parts[0] );
1094+
versionInfo.dwMinor = atoi ( parts[1] );
1095+
versionInfo.dwBuild = atoi ( parts[2] );
10951096
}
10961097
}
10971098

1098-
return SString ( "%u.%u", uiMajor, uiMinor );
1099-
}
1100-
1101-
1102-
///////////////////////////////////////////////////////////////
1103-
//
1104-
// GetRealOSBuildNumber
1105-
//
1106-
// Ignoring compatibility mode
1107-
//
1108-
///////////////////////////////////////////////////////////////
1109-
SString GetRealOSBuildNumber( void )
1110-
{
1111-
uint uiBuild = 0;
1112-
uint uiRev = 0;
1113-
1114-
SLibVersionInfo fileInfo;
1115-
if ( GetLibVersionInfo( "ntdll.dll", &fileInfo ) )
1099+
// Fallback to checking file version of kernel32.dll
1100+
if ( versionInfo.dwMajor == 0 )
11161101
{
1117-
uiBuild = HIWORD( fileInfo.dwFileVersionLS );
1118-
uiRev = LOWORD( fileInfo.dwFileVersionLS );
1102+
SLibVersionInfo fileInfo;
1103+
if ( GetLibVersionInfo ( "kernel32.dll", &fileInfo ) )
1104+
{
1105+
versionInfo.dwMajor = HIWORD ( fileInfo.dwFileVersionMS );
1106+
versionInfo.dwMinor = LOWORD ( fileInfo.dwFileVersionMS );
1107+
versionInfo.dwBuild = HIWORD ( fileInfo.dwFileVersionLS );
1108+
}
11191109
}
11201110

1121-
return SString( "%u.%u", uiBuild, uiRev );
1111+
return versionInfo;
11221112
}
11231113

11241114

@@ -1129,9 +1119,16 @@ SString GetRealOSBuildNumber( void )
11291119
// Works around limit for applications not manifested for Windows 10
11301120
//
11311121
///////////////////////////////////////////////////////////////
1132-
bool IsWindows10OrGreater( void )
1122+
bool IsWindows10OrGreater ( void )
1123+
{
1124+
SOSVersionInfo info = GetRealOSVersion ();
1125+
return info.dwMajor >= 10;
1126+
}
1127+
1128+
bool IsWindows10Threshold2OrGreater ( void )
11331129
{
1134-
return atoi( GetRealOSVersion() ) >= 10;
1130+
SOSVersionInfo info = GetRealOSVersion ();
1131+
return info.dwMajor > 10 || ( info.dwMajor == 10 && info.dwBuild >= 10586 );
11351132
}
11361133

11371134

0 commit comments

Comments
 (0)