/*++ Copyright (c) 2001 Microsoft Corporation Module Name: SecurityChecks.cpp Abstract: This AppVerifier shim hooks CreateProcess, CreateProcessAsUser, and WinExec and checks to see if some conditions exist that might allow trojan horse behavior to occur. Notes: This is a general purpose shim. History: 12/13/2001 rparsons Created --*/ #include "precomp.h" IMPLEMENT_SHIM_BEGIN(SecurityChecks) #include "ShimHookMacro.h" // // verifier log entries // BEGIN_DEFINE_VERIFIER_LOG(SecurityChecks) VERIFIER_LOG_ENTRY(VLOG_SECURITYCHECKS_BADARGUMENTS) VERIFIER_LOG_ENTRY(VLOG_SECURITYCHECKS_WINEXEC) VERIFIER_LOG_ENTRY(VLOG_SECURITYCHECKS_NULL_DACL) VERIFIER_LOG_ENTRY(VLOG_SECURITYCHECKS_WORLDWRITE_DACL) END_DEFINE_VERIFIER_LOG(SecurityChecks) INIT_VERIFIER_LOG(SecurityChecks); APIHOOK_ENUM_BEGIN APIHOOK_ENUM_ENTRY(CreateProcessA) APIHOOK_ENUM_ENTRY(CreateProcessW) APIHOOK_ENUM_ENTRY(CreateProcessAsUserA) APIHOOK_ENUM_ENTRY(CreateProcessAsUserW) APIHOOK_ENUM_ENTRY(WinExec) APIHOOK_ENUM_ENTRY(CreateFileA) APIHOOK_ENUM_ENTRY(CreateFileW) APIHOOK_ENUM_ENTRY(CreateDesktopA) APIHOOK_ENUM_ENTRY(CreateDesktopW) APIHOOK_ENUM_ENTRY(CreateWindowStationA) APIHOOK_ENUM_ENTRY(CreateWindowStationW) APIHOOK_ENUM_ENTRY(RegCreateKeyExA) APIHOOK_ENUM_ENTRY(RegCreateKeyExW) APIHOOK_ENUM_ENTRY(RegSaveKeyA) APIHOOK_ENUM_ENTRY(RegSaveKeyW) APIHOOK_ENUM_ENTRY(RegSaveKeyExA) APIHOOK_ENUM_ENTRY(RegSaveKeyExW) APIHOOK_ENUM_ENTRY(CreateFileMappingA) APIHOOK_ENUM_ENTRY(CreateFileMappingW) APIHOOK_ENUM_ENTRY(CreateJobObjectA) APIHOOK_ENUM_ENTRY(CreateJobObjectW) APIHOOK_ENUM_ENTRY(CreateThread) APIHOOK_ENUM_ENTRY(CreateRemoteThread) APIHOOK_ENUM_ENTRY(CreateDirectoryA) APIHOOK_ENUM_ENTRY(CreateDirectoryW) APIHOOK_ENUM_ENTRY(CreateDirectoryExA) APIHOOK_ENUM_ENTRY(CreateDirectoryExW) APIHOOK_ENUM_ENTRY(CreateHardLinkA) APIHOOK_ENUM_ENTRY(CreateHardLinkW) APIHOOK_ENUM_ENTRY(CreateMailslotA) APIHOOK_ENUM_ENTRY(CreateMailslotW) APIHOOK_ENUM_ENTRY(CreateNamedPipeA) APIHOOK_ENUM_ENTRY(CreateNamedPipeW) APIHOOK_ENUM_ENTRY(CreatePipe) APIHOOK_ENUM_ENTRY(CreateMutexA) APIHOOK_ENUM_ENTRY(CreateMutexW) APIHOOK_ENUM_ENTRY(CreateSemaphoreA) APIHOOK_ENUM_ENTRY(CreateSemaphoreW) APIHOOK_ENUM_ENTRY(CreateWaitableTimerA) APIHOOK_ENUM_ENTRY(CreateWaitableTimerW) //APIHOOK_ENUM_ENTRY(ClusterRegCreateKey) //APIHOOK_ENUM_ENTRY(CreateNtmsMediaPoolA) //APIHOOK_ENUM_ENTRY(CreateNtmsMediaPoolW) APIHOOK_ENUM_END BYTE g_ajSidBuffer[SECURITY_MAX_SID_SIZE]; PSID g_pWorldSid = NULL; WCHAR g_wszWinDir[MAX_PATH]; DWORD g_dwWinDirLen = 0; void InitWorldSid( void ) { DWORD dwSidSize = sizeof(g_ajSidBuffer); if (CreateWellKnownSid(WinWorldSid, NULL, g_ajSidBuffer, &dwSidSize)) { g_pWorldSid = g_ajSidBuffer; } else { g_pWorldSid = NULL; } } void CheckSecurityDescriptor( PSECURITY_DESCRIPTOR pSecurityDescriptor, LPCWSTR szCaller, LPCWSTR szParam, LPCWSTR szName ) { BOOL bDaclPresent = FALSE; BOOL bDaclDefaulted = FALSE; PACL pDacl = NULL; if (!pSecurityDescriptor || !szName || !szName[0]) { // // there's no attributes, so they get the default, which is fine, // or the object doesn't have a name, so it can't be highjacked // return; } if (GetSecurityDescriptorDacl(pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted)) { if (bDaclPresent) { if (!pDacl) { // // we have a NULL dacl -- log a problem // VLOG(VLOG_LEVEL_ERROR, VLOG_SECURITYCHECKS_NULL_DACL, "Called %ls, and specified a NULL DACL in %ls for object '%ls.'", szCaller, szParam, szName); return; } if (!g_pWorldSid) { // // we never were able to get the world Sid // return; } for (DWORD i = 0; i < pDacl->AceCount; ++i) { PACE_HEADER pAceHeader = NULL; PSID pSID; ACCESS_MASK dwAccessMask; if (!GetAce(pDacl, i, (LPVOID*)&pAceHeader)) { continue; } // // if it's not some form of ACCESS_ALLOWED ACE, we aren't interested // if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { pSID = &(((PACCESS_ALLOWED_ACE)pAceHeader)->SidStart); dwAccessMask = ((PACCESS_ALLOWED_ACE)pAceHeader)->Mask; } else if (pAceHeader->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE) { PACCESS_ALLOWED_OBJECT_ACE pAAOAce = (PACCESS_ALLOWED_OBJECT_ACE)pAceHeader; // // who the heck came up with this system? The Sid starts at a different place // depending on the flags. Anyone ever heard of multiple structs? Sigh. // if ((pAAOAce->Flags & ACE_OBJECT_TYPE_PRESENT) && (pAAOAce->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)) { pSID = &(pAAOAce->SidStart); } else if ((pAAOAce->Flags & ACE_OBJECT_TYPE_PRESENT) || (pAAOAce->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)){ pSID = (PSID)&(pAAOAce->InheritedObjectType); } else { pSID = (PSID)&(pAAOAce->ObjectType); } dwAccessMask = ((PACCESS_ALLOWED_OBJECT_ACE)pAceHeader)->Mask; } else { continue; } // // check the validity of the SID, just to be safe // if (!IsValidSid(pSID)) { continue; } // // if the SID is the world, and the access mask allows WRITE_DAC and WRITE_OWNER, we have a problem // if ((dwAccessMask & (WRITE_DAC | WRITE_OWNER)) && EqualSid(pSID, g_pWorldSid)) { VLOG(VLOG_LEVEL_ERROR, VLOG_SECURITYCHECKS_WORLDWRITE_DACL, "Called %ls, and specified a DACL with WRITE_DAC and/or WRITE_OWNER for WORLD in %ls for object '%ls.'", szCaller, szParam, szName); return; } } } } } void CheckSecurityAttributes( LPSECURITY_ATTRIBUTES pSecurityAttrib, LPCWSTR szCaller, LPCWSTR szParam, LPCWSTR szName ) { PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; if (!pSecurityAttrib) { // // there's no attributes, so they get the default, which is fine // return; } pSecurityDescriptor = (PSECURITY_DESCRIPTOR)pSecurityAttrib->lpSecurityDescriptor; CheckSecurityDescriptor(pSecurityDescriptor, szCaller, szParam, szName); } void CheckCreateProcess( LPCWSTR pwszApplicationName, LPCWSTR pwszCommandLine, LPCWSTR pwszCaller ) { // // if applicationname is non-null, there's no problem // if (pwszApplicationName) { return; } // // if there's no command line, there's a problem, but not one we want to solve // if (!pwszCommandLine) { return; } // // if there are no spaces, no problem // LPWSTR pSpaceLoc = wcschr(pwszCommandLine, L' '); if (!pSpaceLoc) { return; } // // if the beginning of the command line is quoted, no problem // if (pwszCommandLine[0] == L'\"') { return; } // // if the phrase '.exe ' appears before the first space, we'll call that good // LPWSTR pExeLoc = wcsistr(pwszCommandLine, L".exe "); if (pExeLoc && pExeLoc < pSpaceLoc) { return; } // // if the first part of the command line is windir, we'll call that good // if (g_dwWinDirLen && _wcsnicmp(pwszCommandLine, g_wszWinDir, g_dwWinDirLen) == 0) { return; } if (_wcsicmp(pwszCaller, L"winexec") == 0) { VLOG(VLOG_LEVEL_ERROR, VLOG_SECURITYCHECKS_BADARGUMENTS, "Called %ls with command line '%ls'. The command line has spaces, and the exe name is not in quotes.", pwszCaller, pwszCommandLine); } else { VLOG(VLOG_LEVEL_ERROR, VLOG_SECURITYCHECKS_BADARGUMENTS, "Called %ls with command line '%ls'. The lpApplicationName argument is NULL, lpCommandLine has spaces, and the exe name is not in quotes.", pwszCaller, pwszCommandLine); } } void CheckForNoPathInFileName( LPCWSTR pwszFilePath, LPCWSTR pwszCaller ) { if (!pwszFilePath || !pwszCaller) { return; } // // skip quotes and space if necessary // DWORD dwBegin = 0; while (pwszFilePath[dwBegin] == L'\"' || pwszFilePath[dwBegin] == L' ') { dwBegin++; } // // if there's nothing left of the string, get out // if (!pwszFilePath[dwBegin] || !pwszFilePath[dwBegin + 1]) { return; } // // check for DOS (x:...) and UNC (\\...) full paths // if (pwszFilePath[dwBegin + 1] == L':' || (pwszFilePath[dwBegin] == L'\\' && pwszFilePath[dwBegin + 1] == L'\\')) { // // full path // return; } VLOG(VLOG_LEVEL_ERROR, VLOG_SECURITYCHECKS_BADARGUMENTS, "Called '%ls' with '%ls' specified. Use a full path to the file to ensure that you get the executable you want, and not a malicious exe with the same name.", pwszCaller, pwszFilePath); } BOOL APIHOOK(CreateProcessA)( LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ) { LPWSTR pwszApplicationName = ToUnicode(lpApplicationName); LPWSTR pwszCommandLine = ToUnicode(lpCommandLine); CheckCreateProcess(pwszApplicationName, pwszCommandLine, L"CreateProcess"); if (pwszApplicationName) { CheckForNoPathInFileName(pwszApplicationName, L"CreateProcess"); CheckSecurityAttributes(lpProcessAttributes, L"CreateProcess", L"lpProcessAttributes", pwszApplicationName); CheckSecurityAttributes(lpThreadAttributes, L"CreateProcess", L"lpThreadAttributes", pwszApplicationName); } else { CheckForNoPathInFileName(pwszCommandLine, L"CreateProcess"); CheckSecurityAttributes(lpProcessAttributes, L"CreateProcess", L"lpProcessAttributes", pwszCommandLine); CheckSecurityAttributes(lpThreadAttributes, L"CreateProcess", L"lpThreadAttributes", pwszCommandLine); } if (pwszApplicationName) { free(pwszApplicationName); pwszApplicationName = NULL; } if (pwszCommandLine) { free(pwszCommandLine); pwszCommandLine = NULL; } return ORIGINAL_API(CreateProcessA)(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); } BOOL APIHOOK(CreateProcessW)( LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ) { CheckCreateProcess(lpApplicationName, lpCommandLine, L"CreateProcess"); if (lpApplicationName) { CheckForNoPathInFileName(lpApplicationName, L"CreateProcess"); CheckSecurityAttributes(lpProcessAttributes, L"CreateProcess", L"lpProcessAttributes", lpApplicationName); CheckSecurityAttributes(lpThreadAttributes, L"CreateProcess", L"lpThreadAttributes", lpApplicationName); } else { CheckForNoPathInFileName(lpCommandLine, L"CreateProcess"); CheckSecurityAttributes(lpProcessAttributes, L"CreateProcess", L"lpProcessAttributes", lpCommandLine); CheckSecurityAttributes(lpThreadAttributes, L"CreateProcess", L"lpThreadAttributes", lpCommandLine); } return ORIGINAL_API(CreateProcessW)(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); } BOOL APIHOOK(CreateProcessAsUserA)( HANDLE hToken, LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ) { LPWSTR pwszApplicationName = ToUnicode(lpApplicationName); LPWSTR pwszCommandLine = ToUnicode(lpCommandLine); CheckCreateProcess(pwszApplicationName, pwszCommandLine, L"CreateProcessAsUser"); if (pwszApplicationName) { CheckForNoPathInFileName(pwszApplicationName, L"CreateProcessAsUser"); CheckSecurityAttributes(lpProcessAttributes, L"CreateProcessAsUser", L"lpProcessAttributes", pwszApplicationName); CheckSecurityAttributes(lpThreadAttributes, L"CreateProcessAsUser", L"lpThreadAttributes", pwszApplicationName); } else { CheckForNoPathInFileName(pwszCommandLine, L"CreateProcessAsUser"); CheckSecurityAttributes(lpProcessAttributes, L"CreateProcessAsUser", L"lpProcessAttributes", pwszCommandLine); CheckSecurityAttributes(lpThreadAttributes, L"CreateProcessAsUser", L"lpThreadAttributes", pwszCommandLine); } if (pwszApplicationName) { free(pwszApplicationName); pwszApplicationName = NULL; } if (pwszCommandLine) { free(pwszCommandLine); pwszCommandLine = NULL; } return ORIGINAL_API(CreateProcessAsUserA)(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); } BOOL APIHOOK(CreateProcessAsUserW)( HANDLE hToken, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ) { CheckCreateProcess(lpApplicationName, lpCommandLine, L"CreateProcessAsUser"); if (lpApplicationName) { CheckForNoPathInFileName(lpApplicationName, L"CreateProcessAsUser"); CheckSecurityAttributes(lpProcessAttributes, L"CreateProcessAsUser", L"lpProcessAttributes", lpApplicationName); CheckSecurityAttributes(lpThreadAttributes, L"CreateProcessAsUser", L"lpThreadAttributes", lpApplicationName); } else { CheckForNoPathInFileName(lpCommandLine, L"CreateProcessAsUser"); CheckSecurityAttributes(lpProcessAttributes, L"CreateProcessAsUser", L"lpProcessAttributes", lpCommandLine); CheckSecurityAttributes(lpThreadAttributes, L"CreateProcessAsUser", L"lpThreadAttributes", lpCommandLine); } return ORIGINAL_API(CreateProcessAsUserW)(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); } UINT APIHOOK(WinExec)( LPCSTR lpCmdLine, UINT uCmdShow ) { LPWSTR pwszCmdLine = ToUnicode(lpCmdLine); VLOG(VLOG_LEVEL_ERROR, VLOG_SECURITYCHECKS_WINEXEC, "Called WinExec."); CheckForNoPathInFileName(pwszCmdLine, L"WinExec"); CheckCreateProcess(NULL, pwszCmdLine, L"WinExec"); if (pwszCmdLine) { free(pwszCmdLine); pwszCmdLine = NULL; } return ORIGINAL_API(WinExec)(lpCmdLine, uCmdShow); } HANDLE APIHOOK(CreateFileA)( LPCSTR lpFileName, // file name DWORD dwDesiredAccess, // access mode DWORD dwShareMode, // share mode LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD DWORD dwCreationDisposition, // how to create DWORD dwFlagsAndAttributes, // file attributes HANDLE hTemplateFile // handle to template file ) { LPWSTR pwszName = ToUnicode(lpFileName); CheckSecurityAttributes(lpSecurityAttributes, L"CreateFile", L"lpSecurityAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateFileA)(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } HANDLE APIHOOK(CreateFileW)( LPCWSTR lpFileName, // file name DWORD dwDesiredAccess, // access mode DWORD dwShareMode, // share mode LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD DWORD dwCreationDisposition, // how to create DWORD dwFlagsAndAttributes, // file attributes HANDLE hTemplateFile // handle to template file ) { CheckSecurityAttributes(lpSecurityAttributes, L"CreateFile", L"lpSecurityAttributes", lpFileName); return ORIGINAL_API(CreateFileW)(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } HDESK APIHOOK(CreateDesktopA)( LPCSTR lpszDesktop, // name of new desktop LPCSTR lpszDevice, // reserved; must be NULL LPDEVMODEA pDevmode, // reserved; must be NULL DWORD dwFlags, // desktop interaction ACCESS_MASK dwDesiredAccess, // access of returned handle LPSECURITY_ATTRIBUTES lpsa // security attributes ) { LPWSTR pwszName = ToUnicode(lpszDesktop); CheckSecurityAttributes(lpsa, L"CreateDesktop", L"lpsa", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateDesktopA)(lpszDesktop, lpszDevice, pDevmode, dwFlags, dwDesiredAccess, lpsa); } HDESK APIHOOK(CreateDesktopW)( LPCWSTR lpszDesktop, // name of new desktop LPCWSTR lpszDevice, // reserved; must be NULL LPDEVMODEW pDevmode, // reserved; must be NULL DWORD dwFlags, // desktop interaction ACCESS_MASK dwDesiredAccess, // access of returned handle LPSECURITY_ATTRIBUTES lpsa // security attributes ) { CheckSecurityAttributes(lpsa, L"CreateDesktop", L"lpsa", lpszDesktop); return ORIGINAL_API(CreateDesktopW)(lpszDesktop, lpszDevice, pDevmode, dwFlags, dwDesiredAccess, lpsa); } HWINSTA APIHOOK(CreateWindowStationA)( LPSTR lpwinsta, // new window station name DWORD dwReserved, // reserved; must be zero ACCESS_MASK dwDesiredAccess, // requested access LPSECURITY_ATTRIBUTES lpsa // security attributes ) { LPWSTR pwszName = ToUnicode(lpwinsta); CheckSecurityAttributes(lpsa, L"CreateWindowStation", L"lpsa", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateWindowStationA)(lpwinsta, dwReserved, dwDesiredAccess, lpsa); } HWINSTA APIHOOK(CreateWindowStationW)( LPWSTR lpwinsta, // new window station name DWORD dwReserved, // reserved; must be zero ACCESS_MASK dwDesiredAccess, // requested access LPSECURITY_ATTRIBUTES lpsa // security attributes ) { CheckSecurityAttributes(lpsa, L"CreateWindowStation", L"lpsa", lpwinsta); return ORIGINAL_API(CreateWindowStationW)(lpwinsta, dwReserved, dwDesiredAccess, lpsa); } LONG APIHOOK(RegCreateKeyExA)( HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition ) { LPWSTR pwszName = ToUnicode(lpSubKey); CheckSecurityAttributes(lpSecurityAttributes, L"RegCreateKeyEx", L"lpSecurityAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(RegCreateKeyExA)(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); } LONG APIHOOK(RegCreateKeyExW)( HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition ) { CheckSecurityAttributes(lpSecurityAttributes, L"RegCreateKeyEx", L"lpSecurityAttributes", lpSubKey); return ORIGINAL_API(RegCreateKeyExW)(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); } LONG APIHOOK(RegSaveKeyA)( HKEY hKey, // handle to key LPCSTR lpFile, // data file LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD ) { LPWSTR pwszName = ToUnicode(lpFile); CheckSecurityAttributes(lpSecurityAttributes, L"RegSaveKey", L"lpSecurityAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(RegSaveKeyA)(hKey, lpFile, lpSecurityAttributes); } LONG APIHOOK(RegSaveKeyW)( HKEY hKey, // handle to key LPCWSTR lpFile, // data file LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD ) { CheckSecurityAttributes(lpSecurityAttributes, L"RegSaveKey", L"lpSecurityAttributes", lpFile); return ORIGINAL_API(RegSaveKeyW)(hKey, lpFile, lpSecurityAttributes); } LONG APIHOOK(RegSaveKeyExA)( HKEY hKey, // handle to key LPCSTR lpFile, // data file LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD DWORD Flags ) { LPWSTR pwszName = ToUnicode(lpFile); CheckSecurityAttributes(lpSecurityAttributes, L"RegSaveKeyEx", L"lpSecurityAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(RegSaveKeyExA)(hKey, lpFile, lpSecurityAttributes, Flags); } LONG APIHOOK(RegSaveKeyExW)( HKEY hKey, // handle to key LPCWSTR lpFile, // data file LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD DWORD Flags ) { CheckSecurityAttributes(lpSecurityAttributes, L"RegSaveKeyEx", L"lpSecurityAttributes", lpFile); return ORIGINAL_API(RegSaveKeyExW)(hKey, lpFile, lpSecurityAttributes, Flags); } HANDLE APIHOOK(CreateFileMappingA)( HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName ) { LPWSTR pwszName = ToUnicode(lpName); CheckSecurityAttributes(lpAttributes, L"CreateFileMapping", L"lpAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateFileMappingA)(hFile, lpAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); } HANDLE APIHOOK(CreateFileMappingW)( HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName ) { CheckSecurityAttributes(lpAttributes, L"CreateFileMapping", L"lpAttributes", lpName); return ORIGINAL_API(CreateFileMappingW)(hFile, lpAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); } HANDLE APIHOOK(CreateJobObjectA)( LPSECURITY_ATTRIBUTES lpJobAttributes, // SD LPCSTR lpName // job name ) { LPWSTR pwszName = ToUnicode(lpName); CheckSecurityAttributes(lpJobAttributes, L"CreateJobObject", L"lpJobAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateJobObjectA)(lpJobAttributes, lpName); } HANDLE APIHOOK(CreateJobObjectW)( LPSECURITY_ATTRIBUTES lpJobAttributes, // SD LPCWSTR lpName // job name ) { CheckSecurityAttributes(lpJobAttributes, L"CreateJobObject", L"lpJobAttributes", lpName); return ORIGINAL_API(CreateJobObjectW)(lpJobAttributes, lpName); } HANDLE APIHOOK(CreateThread)( LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD SIZE_T dwStackSize, // initial stack size LPTHREAD_START_ROUTINE lpStartAddress, // thread function LPVOID lpParameter, // thread argument DWORD dwCreationFlags, // creation option LPDWORD lpThreadId // thread identifier ) { CheckSecurityAttributes(lpThreadAttributes, L"CreateThread", L"lpThreadAttributes", L"Unnamed thread"); return ORIGINAL_API(CreateThread)(lpThreadAttributes, (DWORD)dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId); } HANDLE APIHOOK(CreateRemoteThread)( HANDLE hProcess, // handle to process LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD SIZE_T dwStackSize, // initial stack size LPTHREAD_START_ROUTINE lpStartAddress, // thread function LPVOID lpParameter, // thread argument DWORD dwCreationFlags, // creation option LPDWORD lpThreadId // thread identifier ) { CheckSecurityAttributes(lpThreadAttributes, L"CreateRemoteThread", L"lpThreadAttributes", L"Unnamed thread"); return ORIGINAL_API(CreateRemoteThread)(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId); } BOOL APIHOOK(CreateDirectoryA)( LPCSTR lpPathName, // directory name LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD ) { LPWSTR pwszName = ToUnicode(lpPathName); CheckSecurityAttributes(lpSecurityAttributes, L"CreateDirectory", L"lpSecurityAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateDirectoryA)(lpPathName, lpSecurityAttributes); } BOOL APIHOOK(CreateDirectoryW)( LPCWSTR lpPathName, // directory name LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD ) { CheckSecurityAttributes(lpSecurityAttributes, L"CreateDirectory", L"lpSecurityAttributes", lpPathName); return ORIGINAL_API(CreateDirectoryW)(lpPathName, lpSecurityAttributes); } BOOL APIHOOK(CreateDirectoryExA)( LPCSTR lpTemplateDirectory, // template directory LPCSTR lpNewDirectory, // directory name LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD ) { LPWSTR pwszName = ToUnicode(lpNewDirectory); CheckSecurityAttributes(lpSecurityAttributes, L"CreateDirectoryEx", L"lpSecurityAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateDirectoryExA)(lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes); } BOOL APIHOOK(CreateDirectoryExW)( LPCWSTR lpTemplateDirectory, // template directory LPCWSTR lpNewDirectory, // directory name LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD ) { CheckSecurityAttributes(lpSecurityAttributes, L"CreateDirectoryEx", L"lpSecurityAttributes", lpNewDirectory); return ORIGINAL_API(CreateDirectoryExW)(lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes); } BOOL APIHOOK(CreateHardLinkA)( LPCSTR lpFileName, // link name name LPCSTR lpExistingFileName, // target file name LPSECURITY_ATTRIBUTES lpSecurityAttributes ) { LPWSTR pwszName = ToUnicode(lpFileName); CheckSecurityAttributes(lpSecurityAttributes, L"CreateHardLink", L"lpSecurityAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateHardLinkA)(lpFileName, lpExistingFileName, lpSecurityAttributes); } BOOL APIHOOK(CreateHardLinkW)( LPCWSTR lpFileName, // link name name LPCWSTR lpExistingFileName, // target file name LPSECURITY_ATTRIBUTES lpSecurityAttributes ) { CheckSecurityAttributes(lpSecurityAttributes, L"CreateHardLink", L"lpSecurityAttributes", lpFileName); return ORIGINAL_API(CreateHardLinkW)(lpFileName, lpExistingFileName, lpSecurityAttributes); } HANDLE APIHOOK(CreateMailslotA)( LPCSTR lpName, // mailslot name DWORD nMaxMessageSize, // maximum message size DWORD lReadTimeout, // read time-out interval LPSECURITY_ATTRIBUTES lpSecurityAttributes // inheritance option ) { LPWSTR pwszName = ToUnicode(lpName); CheckSecurityAttributes(lpSecurityAttributes, L"CreateMailslot", L"lpSecurityAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateMailslotA)(lpName, nMaxMessageSize, lReadTimeout, lpSecurityAttributes); } HANDLE APIHOOK(CreateMailslotW)( LPCWSTR lpName, // mailslot name DWORD nMaxMessageSize, // maximum message size DWORD lReadTimeout, // read time-out interval LPSECURITY_ATTRIBUTES lpSecurityAttributes // inheritance option ) { CheckSecurityAttributes(lpSecurityAttributes, L"CreateMailslot", L"lpSecurityAttributes", lpName); return ORIGINAL_API(CreateMailslotW)(lpName, nMaxMessageSize, lReadTimeout, lpSecurityAttributes); } HANDLE APIHOOK(CreateNamedPipeA)( LPCSTR lpName, // pipe name DWORD dwOpenMode, // pipe open mode DWORD dwPipeMode, // pipe-specific modes DWORD nMaxInstances, // maximum number of instances DWORD nOutBufferSize, // output buffer size DWORD nInBufferSize, // input buffer size DWORD nDefaultTimeOut, // time-out interval LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD ) { LPWSTR pwszName = ToUnicode(lpName); CheckSecurityAttributes(lpSecurityAttributes, L"CreateNamedPipe", L"lpSecurityAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateNamedPipeA)(lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut, lpSecurityAttributes); } HANDLE APIHOOK(CreateNamedPipeW)( LPCWSTR lpName, // pipe name DWORD dwOpenMode, // pipe open mode DWORD dwPipeMode, // pipe-specific modes DWORD nMaxInstances, // maximum number of instances DWORD nOutBufferSize, // output buffer size DWORD nInBufferSize, // input buffer size DWORD nDefaultTimeOut, // time-out interval LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD ) { CheckSecurityAttributes(lpSecurityAttributes, L"CreateNamedPipe", L"lpSecurityAttributes", lpName); return ORIGINAL_API(CreateNamedPipeW)(lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut, lpSecurityAttributes); } BOOL APIHOOK(CreatePipe)( PHANDLE hReadPipe, // read handle PHANDLE hWritePipe, // write handle LPSECURITY_ATTRIBUTES lpPipeAttributes, // security attributes DWORD nSize // pipe size ) { CheckSecurityAttributes(lpPipeAttributes, L"CreatePipe", L"lpPipeAttributes", L"Unnamed pipe"); return ORIGINAL_API(CreatePipe)(hReadPipe, hWritePipe, lpPipeAttributes, nSize); } HANDLE APIHOOK(CreateMutexA)( LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD BOOL bInitialOwner, // initial owner LPCSTR lpName // object name ) { LPWSTR pwszName = ToUnicode(lpName); CheckSecurityAttributes(lpMutexAttributes, L"CreateMutex", L"lpMutexAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateMutexA)(lpMutexAttributes, bInitialOwner, lpName); } HANDLE APIHOOK(CreateMutexW)( LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD BOOL bInitialOwner, // initial owner LPCWSTR lpName // object name ) { CheckSecurityAttributes(lpMutexAttributes, L"CreateMutex", L"lpMutexAttributes", lpName); return ORIGINAL_API(CreateMutexW)(lpMutexAttributes, bInitialOwner, lpName); } HANDLE APIHOOK(CreateSemaphoreA)( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // SD LONG lInitialCount, // initial count LONG lMaximumCount, // maximum count LPCSTR lpName // object name ) { LPWSTR pwszName = ToUnicode(lpName); CheckSecurityAttributes(lpSemaphoreAttributes, L"CreateSemaphore", L"lpSemaphoreAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateSemaphoreA)(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName); } HANDLE APIHOOK(CreateSemaphoreW)( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // SD LONG lInitialCount, // initial count LONG lMaximumCount, // maximum count LPCWSTR lpName // object name ) { CheckSecurityAttributes(lpSemaphoreAttributes, L"CreateSemaphore", L"lpSemaphoreAttributes", lpName); return ORIGINAL_API(CreateSemaphoreW)(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName); } HANDLE APIHOOK(CreateWaitableTimerA)( IN LPSECURITY_ATTRIBUTES lpTimerAttributes, IN BOOL bManualReset, IN LPCSTR lpTimerName ) { LPWSTR pwszName = ToUnicode(lpTimerName); CheckSecurityAttributes(lpTimerAttributes, L"CreateWaitableTimer", L"lpTimerAttributes", pwszName); if (pwszName) { free(pwszName); pwszName = NULL; } return ORIGINAL_API(CreateWaitableTimerA)(lpTimerAttributes, bManualReset, lpTimerName); } HANDLE APIHOOK(CreateWaitableTimerW)( IN LPSECURITY_ATTRIBUTES lpTimerAttributes, IN BOOL bManualReset, IN LPCWSTR lpTimerName ) { CheckSecurityAttributes(lpTimerAttributes, L"CreateWaitableTimer", L"lpTimerAttributes", lpTimerName); return ORIGINAL_API(CreateWaitableTimerW)(lpTimerAttributes, bManualReset, lpTimerName); } #if 0 LONG WINAPI APIHOOK(ClusterRegCreateKey)( HKEY hKey, LPCWSTR lpszSubKey, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition ) { CheckSecurityAttributes(lpSecurityAttributes, L"ClusterRegCreateKey", L"lpSecurityAttributes"); return ORIGINAL_API(ClusterRegCreateKey)(hKey, lpszSubKey, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); } DWORD WINAPI APIHOOK(CreateNtmsMediaPoolA)( HANDLE hSession, LPCSTR lpPoolName, LPNTMS_GUID lpMediaType, DWORD dwAction, LPSECURITY_ATTRIBUTES lpSecurityAttributes, LPNTMS_GUID lpPoolId // OUT ) { CheckSecurityAttributes(lpSecurityAttributes, L"CreateNtmsMediaPool", L"lpSecurityAttributes"); return ORIGINAL_API(CreateNtmsMediaPoolA)(hSession, lpPoolName, lpMediaType, dwAction, lpSecurityAttributes, lpPoolId); } DWORD WINAPI APIHOOK(CreateNtmsMediaPoolW)( HANDLE hSession, LPCWSTR lpPoolName, LPNTMS_GUID lpMediaType, DWORD dwAction, LPSECURITY_ATTRIBUTES lpSecurityAttributes, LPNTMS_GUID lpPoolId // OUT ) { CheckSecurityAttributes(lpSecurityAttributes, L"CreateNtmsMediaPool", L"lpSecurityAttributes"); return ORIGINAL_API(CreateNtmsMediaPoolW)(hSession, lpPoolName, lpMediaType, dwAction, lpSecurityAttributes, lpPoolId); } #endif SHIM_INFO_BEGIN() SHIM_INFO_DESCRIPTION(AVS_SECURITYCHECKS_DESC) SHIM_INFO_FRIENDLY_NAME(AVS_SECURITYCHECKS_FRIENDLY) SHIM_INFO_FLAGS(0) SHIM_INFO_GROUPS(0) SHIM_INFO_VERSION(2, 3) SHIM_INFO_INCLUDE_EXCLUDE("I:*") SHIM_INFO_END() /*++ Register hooked functions. --*/ HOOK_BEGIN if (fdwReason == DLL_PROCESS_ATTACH) { DWORD dwSize; InitWorldSid(); dwSize = GetSystemWindowsDirectoryW(g_wszWinDir, ARRAYSIZE(g_wszWinDir)); if (dwSize == 0 || dwSize > ARRAYSIZE(g_wszWinDir)) { g_wszWinDir[0] = 0; } g_dwWinDirLen = wcslen(g_wszWinDir); } DUMP_VERIFIER_LOG_ENTRY(VLOG_SECURITYCHECKS_BADARGUMENTS, AVS_SECURITYCHECKS_BADARGUMENTS, AVS_SECURITYCHECKS_BADARGUMENTS_R, AVS_SECURITYCHECKS_BADARGUMENTS_URL) DUMP_VERIFIER_LOG_ENTRY(VLOG_SECURITYCHECKS_WINEXEC, AVS_SECURITYCHECKS_WINEXEC, AVS_SECURITYCHECKS_WINEXEC_R, AVS_SECURITYCHECKS_WINEXEC_URL) DUMP_VERIFIER_LOG_ENTRY(VLOG_SECURITYCHECKS_NULL_DACL, AVS_SECURITYCHECKS_NULL_DACL, AVS_SECURITYCHECKS_NULL_DACL_R, AVS_SECURITYCHECKS_NULL_DACL_URL) DUMP_VERIFIER_LOG_ENTRY(VLOG_SECURITYCHECKS_WORLDWRITE_DACL, AVS_SECURITYCHECKS_WORLDWRITE_DACL, AVS_SECURITYCHECKS_WORLDWRITE_DACL_R, AVS_SECURITYCHECKS_WORLDWRITE_DACL_URL) APIHOOK_ENTRY(KERNEL32.DLL, CreateProcessA) APIHOOK_ENTRY(KERNEL32.DLL, CreateProcessW) APIHOOK_ENTRY(ADVAPI32.DLL, CreateProcessAsUserA) APIHOOK_ENTRY(ADVAPI32.DLL, CreateProcessAsUserW) APIHOOK_ENTRY(KERNEL32.DLL, WinExec) APIHOOK_ENTRY(KERNEL32.DLL, CreateFileA) APIHOOK_ENTRY(KERNEL32.DLL, CreateFileW) APIHOOK_ENTRY(USER32.DLL, CreateDesktopA) APIHOOK_ENTRY(USER32.DLL, CreateDesktopW) APIHOOK_ENTRY(USER32.DLL, CreateWindowStationA) APIHOOK_ENTRY(USER32.DLL, CreateWindowStationW) APIHOOK_ENTRY(ADVAPI32.DLL, RegCreateKeyExA) APIHOOK_ENTRY(ADVAPI32.DLL, RegCreateKeyExW) APIHOOK_ENTRY(ADVAPI32.DLL, RegSaveKeyA) APIHOOK_ENTRY(ADVAPI32.DLL, RegSaveKeyW) APIHOOK_ENTRY(ADVAPI32.DLL, RegSaveKeyExA) APIHOOK_ENTRY(ADVAPI32.DLL, RegSaveKeyExW) APIHOOK_ENTRY(KERNEL32.DLL, CreateFileMappingA) APIHOOK_ENTRY(KERNEL32.DLL, CreateFileMappingW) APIHOOK_ENTRY(KERNEL32.DLL, CreateJobObjectA) APIHOOK_ENTRY(KERNEL32.DLL, CreateJobObjectW) APIHOOK_ENTRY(KERNEL32.DLL, CreateThread) APIHOOK_ENTRY(KERNEL32.DLL, CreateRemoteThread) APIHOOK_ENTRY(KERNEL32.DLL, CreateDirectoryA) APIHOOK_ENTRY(KERNEL32.DLL, CreateDirectoryW) APIHOOK_ENTRY(KERNEL32.DLL, CreateDirectoryExA) APIHOOK_ENTRY(KERNEL32.DLL, CreateDirectoryExW) APIHOOK_ENTRY(KERNEL32.DLL, CreateHardLinkA) APIHOOK_ENTRY(KERNEL32.DLL, CreateHardLinkW) APIHOOK_ENTRY(KERNEL32.DLL, CreateMailslotA) APIHOOK_ENTRY(KERNEL32.DLL, CreateMailslotW) APIHOOK_ENTRY(KERNEL32.DLL, CreateNamedPipeA) APIHOOK_ENTRY(KERNEL32.DLL, CreateNamedPipeW) APIHOOK_ENTRY(KERNEL32.DLL, CreatePipe) APIHOOK_ENTRY(KERNEL32.DLL, CreateMutexA) APIHOOK_ENTRY(KERNEL32.DLL, CreateMutexW) APIHOOK_ENTRY(KERNEL32.DLL, CreateSemaphoreA) APIHOOK_ENTRY(KERNEL32.DLL, CreateSemaphoreW) APIHOOK_ENTRY(KERNEL32.DLL, CreateWaitableTimerA) APIHOOK_ENTRY(KERNEL32.DLL, CreateWaitableTimerW) HOOK_END IMPLEMENT_SHIM_END