1 /*
2 * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 *
6 * Security related functions for Windows platform (Set privileges such as
7 * SE DEBUG).
8 */
9
10 #include <windows.h>
11 #include <Python.h>
12
13 #include "../../_psutil_common.h"
14
15
16 static BOOL
psutil_set_privilege(HANDLE hToken,LPCTSTR Privilege,BOOL bEnablePrivilege)17 psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege) {
18 TOKEN_PRIVILEGES tp;
19 LUID luid;
20 TOKEN_PRIVILEGES tpPrevious;
21 DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
22
23 if (! LookupPrivilegeValue(NULL, Privilege, &luid)) {
24 PyErr_SetFromOSErrnoWithSyscall("LookupPrivilegeValue");
25 return 1;
26 }
27
28 // first pass. get current privilege setting
29 tp.PrivilegeCount = 1;
30 tp.Privileges[0].Luid = luid;
31 tp.Privileges[0].Attributes = 0;
32
33 if (! AdjustTokenPrivileges(
34 hToken,
35 FALSE,
36 &tp,
37 sizeof(TOKEN_PRIVILEGES),
38 &tpPrevious,
39 &cbPrevious))
40 {
41 PyErr_SetFromOSErrnoWithSyscall("AdjustTokenPrivileges");
42 return 1;
43 }
44
45 // Second pass. Set privilege based on previous setting.
46 tpPrevious.PrivilegeCount = 1;
47 tpPrevious.Privileges[0].Luid = luid;
48
49 if (bEnablePrivilege)
50 tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
51 else
52 tpPrevious.Privileges[0].Attributes ^=
53 (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
54
55 if (! AdjustTokenPrivileges(
56 hToken,
57 FALSE,
58 &tpPrevious,
59 cbPrevious,
60 NULL,
61 NULL))
62 {
63 PyErr_SetFromOSErrnoWithSyscall("AdjustTokenPrivileges");
64 return 1;
65 }
66
67 return 0;
68 }
69
70
71 static HANDLE
psutil_get_thisproc_token()72 psutil_get_thisproc_token() {
73 HANDLE hToken = NULL;
74 HANDLE me = GetCurrentProcess();
75
76 if (! OpenProcessToken(
77 me, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
78 {
79 if (GetLastError() == ERROR_NO_TOKEN)
80 {
81 if (! ImpersonateSelf(SecurityImpersonation)) {
82 PyErr_SetFromOSErrnoWithSyscall("ImpersonateSelf");
83 return NULL;
84 }
85 if (! OpenProcessToken(
86 me, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
87 {
88 PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken");
89 return NULL;
90 }
91 }
92 else {
93 PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken");
94 return NULL;
95 }
96 }
97
98 return hToken;
99 }
100
101
102 static void
psutil_print_err()103 psutil_print_err() {
104 char *msg = "psutil module couldn't set SE DEBUG mode for this process; " \
105 "please file an issue against psutil bug tracker";
106 psutil_debug(msg);
107 if (GetLastError() != ERROR_ACCESS_DENIED)
108 PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1);
109 PyErr_Clear();
110 }
111
112
113 /*
114 * Set this process in SE DEBUG mode so that we have more chances of
115 * querying processes owned by other users, including many owned by
116 * Administrator and Local System.
117 * https://docs.microsoft.com/windows-hardware/drivers/debugger/debug-privilege
118 * This is executed on module import and we don't crash on error.
119 */
120 int
psutil_set_se_debug()121 psutil_set_se_debug() {
122 HANDLE hToken;
123
124 if ((hToken = psutil_get_thisproc_token()) == NULL) {
125 // "return 1;" to get an exception
126 psutil_print_err();
127 return 0;
128 }
129
130 if (psutil_set_privilege(hToken, SE_DEBUG_NAME, TRUE) != 0) {
131 // "return 1;" to get an exception
132 psutil_print_err();
133 }
134
135 RevertToSelf();
136 CloseHandle(hToken);
137 return 0;
138 }
139