diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2019-02-25 02:35:07 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-25 02:35:07 -0800 |
commit | f326539daa5bbd9153db79b508b6aaede731a154 (patch) | |
tree | 1b2b4c473155dae88dd8014259f802957509fad1 /psutil/arch/windows | |
parent | 7a2572268168e96c8841ca83ab1a89735ec02c3a (diff) | |
download | psutil-f326539daa5bbd9153db79b508b6aaede731a154.tar.gz |
Process SE DEBUG mode was not set on Windows (#1429)
Diffstat (limited to 'psutil/arch/windows')
-rw-r--r-- | psutil/arch/windows/security.c | 253 | ||||
-rw-r--r-- | psutil/arch/windows/security.h | 4 |
2 files changed, 85 insertions, 172 deletions
diff --git a/psutil/arch/windows/security.c b/psutil/arch/windows/security.c index d5f8f8d3..4e2c7435 100644 --- a/psutil/arch/windows/security.c +++ b/psutil/arch/windows/security.c @@ -4,134 +4,44 @@ * found in the LICENSE file. * * Security related functions for Windows platform (Set privileges such as - * SeDebug), as well as security helper functions. + * SE DEBUG). */ #include <windows.h> #include <Python.h> +#include "../../_psutil_common.h" -/* - * Convert a process handle to a process token handle. - */ -HANDLE -psutil_token_from_handle(HANDLE hProcess) { - HANDLE hToken = NULL; - - if (! OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) - return PyErr_SetFromWindowsErr(0); - return hToken; -} - - -/* - * http://www.ddj.com/windows/184405986 - * - * There's a way to determine whether we're running under the Local System - * account. However (you guessed it), we have to call more Win32 functions to - * determine this. Backing up through the code listing, we need to make another - * call to GetTokenInformation, but instead of passing through the TOKEN_USER - * constant, we pass through the TOKEN_PRIVILEGES constant. This value returns - * an array of privileges that the account has in the environment. Iterating - * through the array, we call the function LookupPrivilegeName looking for the - * string “SeTcbPrivilege. If the function returns this string, then this - * account has Local System privileges - */ -int -psutil_has_system_privilege(HANDLE hProcess) { - DWORD i; - DWORD dwSize = 0; - DWORD dwRetval = 0; - TCHAR privName[256]; - DWORD dwNameSize = 256; - // PTOKEN_PRIVILEGES tp = NULL; - BYTE *pBuffer = NULL; - TOKEN_PRIVILEGES *tp = NULL; - HANDLE hToken = psutil_token_from_handle(hProcess); - - if (NULL == hToken) - return -1; - // call GetTokenInformation first to get the buffer size - if (! GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize)) { - dwRetval = GetLastError(); - // if it failed for a reason other than the buffer, bail out - if (dwRetval != ERROR_INSUFFICIENT_BUFFER ) { - PyErr_SetFromWindowsErr(dwRetval); - return 0; - } - } - - // allocate buffer and call GetTokenInformation again - // tp = (PTOKEN_PRIVILEGES) GlobalAlloc(GPTR, dwSize); - pBuffer = (BYTE *) malloc(dwSize); - if (pBuffer == NULL) { - PyErr_NoMemory(); - return -1; - } - - if (! GetTokenInformation(hToken, TokenPrivileges, pBuffer, - dwSize, &dwSize)) - { - PyErr_SetFromWindowsErr(0); - free(pBuffer); - return -1; - } - - // convert the BYTE buffer to a TOKEN_PRIVILEGES struct pointer - tp = (TOKEN_PRIVILEGES *)pBuffer; - - // check all the privileges looking for SeTcbPrivilege - for (i = 0; i < tp->PrivilegeCount; i++) { - // reset the buffer contents and the buffer size - strcpy(privName, ""); - dwNameSize = sizeof(privName) / sizeof(TCHAR); - if (! LookupPrivilegeName(NULL, - &tp->Privileges[i].Luid, - (LPTSTR)privName, - &dwNameSize)) - { - PyErr_SetFromWindowsErr(0); - free(pBuffer); - return -1; - } - - // if we find the SeTcbPrivilege then it's a LocalSystem process - if (! lstrcmpi(privName, TEXT("SeTcbPrivilege"))) { - free(pBuffer); - return 1; - } - } - - free(pBuffer); - return 0; -} - - -BOOL +static BOOL psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; LUID luid; TOKEN_PRIVILEGES tpPrevious; DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); - if (!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE; + if (! LookupPrivilegeValue(NULL, Privilege, &luid)) { + PyErr_SetFromOSErrnoWithSyscall("LookupPrivilegeValue"); + return 1; + } // first pass. get current privilege setting tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = 0; - AdjustTokenPrivileges( - hToken, - FALSE, - &tp, - sizeof(TOKEN_PRIVILEGES), - &tpPrevious, - &cbPrevious - ); - - if (GetLastError() != ERROR_SUCCESS) return FALSE; - // second pass. set privilege based on previous setting + if (! AdjustTokenPrivileges( + hToken, + FALSE, + &tp, + sizeof(TOKEN_PRIVILEGES), + &tpPrevious, + &cbPrevious)) + { + PyErr_SetFromOSErrnoWithSyscall("AdjustTokenPrivileges"); + return 1; + } + + // Second pass. Set privilege based on previous setting. tpPrevious.PrivilegeCount = 1; tpPrevious.Privileges[0].Luid = luid; @@ -141,81 +51,88 @@ psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege) { tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes); - AdjustTokenPrivileges( - hToken, - FALSE, - &tpPrevious, - cbPrevious, - NULL, - NULL - ); - - if (GetLastError() != ERROR_SUCCESS) return FALSE; + if (! AdjustTokenPrivileges( + hToken, + FALSE, + &tpPrevious, + cbPrevious, + NULL, + NULL)) + { + PyErr_SetFromOSErrnoWithSyscall("AdjustTokenPrivileges"); + return 1; + } - return TRUE; + return 0; } -int -psutil_set_se_debug() { - HANDLE hToken; - if (!OpenProcessToken(GetCurrentProcess(), - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, - &hToken) - ) { - if (GetLastError() == ERROR_NO_TOKEN) { - if (!ImpersonateSelf(SecurityImpersonation)) { - CloseHandle(hToken); - return 0; +static HANDLE +psutil_get_thisproc_token() { + HANDLE hToken = NULL; + HANDLE me = GetCurrentProcess(); + + if (! OpenProcessToken( + me, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + { + if (GetLastError() == ERROR_NO_TOKEN) + { + if (! ImpersonateSelf(SecurityImpersonation)) { + PyErr_SetFromOSErrnoWithSyscall("ImpersonateSelf"); + return NULL; } - if (!OpenProcessToken(GetCurrentProcess(), - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, - &hToken) - ) { - RevertToSelf(); - CloseHandle(hToken); - return 0; + if (! OpenProcessToken( + me, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + { + PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken"); + return NULL; } } + else { + PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken"); + return NULL; + } } - // enable SeDebugPrivilege (open any process) - if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, TRUE)) { - RevertToSelf(); - CloseHandle(hToken); - return 0; - } + return hToken; +} - RevertToSelf(); - CloseHandle(hToken); - return 1; + +static void +psutil_print_err() { + char *msg = "psutil module couldn't set SE DEBUG mode for this process; " \ + "please file an issue against psutil bug tracker"; + psutil_debug(msg); + if (GetLastError() != ERROR_ACCESS_DENIED) + PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1); + PyErr_Clear(); } +/* + * Set this process in SE DEBUG mode so that we have more chances of + * querying processes owned by other users, including many owned by + * Administrator and Local System. + * https://docs.microsoft.com/windows-hardware/drivers/debugger/debug-privilege + * This is executed on module import and we don't crash on error. + */ int -psutil_unset_se_debug() { +psutil_set_se_debug() { HANDLE hToken; - if (!OpenProcessToken(GetCurrentProcess(), - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, - &hToken) - ) { - if (GetLastError() == ERROR_NO_TOKEN) { - if (! ImpersonateSelf(SecurityImpersonation)) - return 0; - if (!OpenProcessToken(GetCurrentProcess(), - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, - &hToken)) - { - return 0; - } - } - } + int err = 1; - // now disable SeDebug - if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, FALSE)) + if ((hToken = psutil_get_thisproc_token()) == NULL) { + // "return 1;" to get an exception + psutil_print_err(); return 0; + } + + if (psutil_set_privilege(hToken, SE_DEBUG_NAME, TRUE) != 0) { + // "return 1;" to get an exception + psutil_print_err(); + } + RevertToSelf(); CloseHandle(hToken); - return 1; + return 0; } - diff --git a/psutil/arch/windows/security.h b/psutil/arch/windows/security.h index aa8a22ad..8d4ddb00 100644 --- a/psutil/arch/windows/security.h +++ b/psutil/arch/windows/security.h @@ -9,9 +9,5 @@ #include <windows.h> -BOOL psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege); -HANDLE psutil_token_from_handle(HANDLE hProcess); -int psutil_has_system_privilege(HANDLE hProcess); int psutil_set_se_debug(); -int psutil_unset_se_debug(); |