diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index bc63bf139..a1bfcb0c0 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 Lennart Glauer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,7 +27,8 @@ #include #ifdef Q_OS_WIN -#include // for Sleep(), SetDllDirectoryA() and SetSearchPathMode() +#include // for Sleep(), SetDllDirectoryA(), SetSearchPathMode(), ... +#include // for SetSecurityInfo() #endif #ifdef Q_OS_UNIX @@ -226,6 +228,10 @@ void disableCoreDumps() success = success && (ptrace(PT_DENY_ATTACH, 0, 0, 0) == 0); #endif +#ifdef Q_OS_WIN + success = success && createWindowsDACL(); +#endif + if (!success) { qWarning("Unable to disable core dumps."); } @@ -240,4 +246,114 @@ void setupSearchPaths() #endif } +// +// This function grants the user associated with the process token minimal access rights and +// denies everything else on Windows. This includes PROCESS_QUERY_INFORMATION and +// PROCESS_VM_READ access rights that are required for MiniDumpWriteDump() or ReadProcessMemory(). +// We do this using a discretionary access control list (DACL). Effectively this prevents +// crash dumps and disallows other processes from accessing our memory. This works as long +// as you do not have admin privileges, since then you are able to grant yourself the +// SeDebugPrivilege or SeTakeOwnershipPrivilege and circumvent the DACL. +// +bool createWindowsDACL() +{ + bool bSuccess = false; + +#ifdef Q_OS_WIN + // Process token and user + HANDLE hToken = nullptr; + PTOKEN_USER pTokenUser = nullptr; + DWORD cbBufferSize = 0; + + // Access control list + PACL pACL = nullptr; + DWORD cbACL = 0; + + // Open the access token associated with the calling process + if (!OpenProcessToken( + GetCurrentProcess(), + TOKEN_QUERY, + &hToken + )) { + goto Cleanup; + } + + // Retrieve the token information in a TOKEN_USER structure + GetTokenInformation( + hToken, + TokenUser, + nullptr, + 0, + &cbBufferSize + ); + + pTokenUser = static_cast(HeapAlloc(GetProcessHeap(), 0, cbBufferSize)); + if (pTokenUser == nullptr) { + goto Cleanup; + } + + if (!GetTokenInformation( + hToken, + TokenUser, + pTokenUser, + cbBufferSize, + &cbBufferSize + )) { + goto Cleanup; + } + + if (!IsValidSid(pTokenUser->User.Sid)) { + goto Cleanup; + } + + // Calculate the amount of memory that must be allocated for the DACL + cbACL = sizeof(ACL) + + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid); + + // Create and initialize an ACL + pACL = static_cast(HeapAlloc(GetProcessHeap(), 0, cbACL)); + if (pACL == nullptr) { + goto Cleanup; + } + + if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) { + goto Cleanup; + } + + // Add allowed access control entries, everything else is denied + if (!AddAccessAllowedAce( + pACL, + ACL_REVISION, + SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process + pTokenUser->User.Sid // pointer to the trustee's SID + )) { + goto Cleanup; + } + + // Set discretionary access control list + bSuccess = ERROR_SUCCESS == SetSecurityInfo( + GetCurrentProcess(), // object handle + SE_KERNEL_OBJECT, // type of object + DACL_SECURITY_INFORMATION, // change only the objects DACL + nullptr, nullptr, // do not change owner or group + pACL, // DACL specified + nullptr // do not change SACL + ); + +Cleanup: + + if (pACL != nullptr) { + HeapFree(GetProcessHeap(), 0, pACL); + } + if (pTokenUser != nullptr) { + HeapFree(GetProcessHeap(), 0, pTokenUser); + } + if (hToken != nullptr) { + CloseHandle(hToken); + } +#endif + + return bSuccess; +} + } // namespace Tools diff --git a/src/core/Tools.h b/src/core/Tools.h index 65df1ea4e..ba55054a8 100644 --- a/src/core/Tools.h +++ b/src/core/Tools.h @@ -41,6 +41,7 @@ void sleep(int ms); void wait(int ms); void disableCoreDumps(); void setupSearchPaths(); +bool createWindowsDACL(); template RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value)