├── .manifest
├── .rc2
├── Pause.png
├── Play.png
├── Reload-icon.png
├── aclui.cpp
├── black.png
├── blue.png
├── green.png
├── impersonate.cpp
├── impersonate.h
├── red.png
├── resource.h
├── security.cpp
├── security.png
├── services.rc
├── srv.cpp
├── srv.ico
├── stdafx.cpp
├── stdafx.h
├── stop.png
├── token.cpp
├── x64
└── srvs.exe
├── x86
└── srvs.exe
└── yellow.png
/.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | True
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.rc2:
--------------------------------------------------------------------------------
1 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
2 |
3 | 1 RT_MANIFEST ".manifest"
4 |
5 | ID_MAIN ICON "srv.ico"
6 |
7 |
8 | ID_B RCDATA "blue.png"
9 | ID_G RCDATA "green.png"
10 | ID_R RCDATA "red.png"
11 | ID_Y RCDATA "yellow.png"
12 | ID_K RCDATA "black.png"
13 |
14 | ID_START RCDATA "play.png"
15 | ID_PAUSE RCDATA "pause.png"
16 | ID_STOP RCDATA "stop.png"
17 | ID_SD RCDATA "security.png"
18 | ID_RELOAD RCDATA "Reload-icon.png"
19 |
20 |
--------------------------------------------------------------------------------
/Pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/Pause.png
--------------------------------------------------------------------------------
/Play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/Play.png
--------------------------------------------------------------------------------
/Reload-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/Reload-icon.png
--------------------------------------------------------------------------------
/aclui.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include
3 |
4 | _NT_BEGIN
5 |
6 | #include "impersonate.h"
7 |
8 | #define SERVICE_GENERIC_READ STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS
9 | #define SERVICE_GENERIC_WRITE STANDARD_RIGHTS_WRITE | SERVICE_CHANGE_CONFIG
10 | #define SERVICE_GENERIC_EXECUTE STANDARD_RIGHTS_EXECUTE | SERVICE_START | SERVICE_STOP |SERVICE_PAUSE_CONTINUE | SERVICE_USER_DEFINED_CONTROL
11 |
12 | class CSecurityInformation : public ISecurityInformation
13 | {
14 | SC_HANDLE _hService;
15 | PCWSTR _lpServiceName;
16 | HANDLE _hSystemToken;
17 | LONG _dwRef = 1;
18 |
19 | ~CSecurityInformation()
20 | {
21 | if (SC_HANDLE hService = _hService)
22 | {
23 | CloseServiceHandle(hService);
24 | }
25 | }
26 |
27 | public:
28 |
29 | HRESULT Init(_In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName, _In_ HANDLE hSystemToken)
30 | {
31 | HRESULT hr = SetTokenForService(hSCManager, lpServiceName, hSystemToken, READ_CONTROL|WRITE_DAC|WRITE_OWNER);
32 | if (0 <= hr)
33 | {
34 | if (SC_HANDLE hService = OpenServiceW(hSCManager, lpServiceName, READ_CONTROL|WRITE_DAC|WRITE_OWNER ))
35 | {
36 | hr = S_OK, _hService = hService, _lpServiceName = lpServiceName, _hSystemToken = hSystemToken;
37 | }
38 | else
39 | {
40 | hr = GetLastError();
41 | }
42 | SetToken();
43 | }
44 |
45 | return HRESULT_FROM_WIN32(hr);
46 | }
47 |
48 | // *** IUnknown methods ***
49 | virtual HRESULT STDAPICALLTYPE QueryInterface(_In_ REFIID riid, _Outptr_ void **ppvObj)
50 | {
51 | if (riid == __uuidof(IUnknown) || riid == __uuidof(ISecurityInformation))
52 | {
53 | *ppvObj = static_cast(this);
54 | AddRef();
55 | return S_OK;
56 | }
57 |
58 | return E_NOINTERFACE;
59 | }
60 |
61 | virtual ULONG STDAPICALLTYPE AddRef()
62 | {
63 | return InterlockedIncrementNoFence(&_dwRef);
64 | }
65 |
66 | virtual ULONG STDAPICALLTYPE Release()
67 | {
68 | ULONG dwRef = InterlockedDecrement(&_dwRef);
69 | if (!dwRef)
70 | {
71 | delete this;
72 | }
73 | return dwRef;
74 | }
75 |
76 | // *** ISecurityInformation methods ***
77 | virtual HRESULT STDAPICALLTYPE GetObjectInformation ( PSI_OBJECT_INFO pObjectInfo )
78 | {
79 | RtlZeroMemory(pObjectInfo, sizeof(SI_OBJECT_INFO));
80 | pObjectInfo->dwFlags = SI_ADVANCED|SI_EDIT_OWNER;
81 | pObjectInfo->pszObjectName = const_cast(_lpServiceName);
82 | return S_OK;
83 | }
84 |
85 | virtual HRESULT STDAPICALLTYPE GetSecurity (SECURITY_INFORMATION RequestedInformation,
86 | PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
87 | BOOL /*fDefault*/ )
88 | {
89 | ULONG dwError, cb = 0x100;
90 | do
91 | {
92 | if (PSECURITY_DESCRIPTOR pSecurityDescriptor = LocalAlloc(0, cb))
93 | {
94 | if (NOERROR == (dwError = BOOL_TO_ERROR(QueryServiceObjectSecurity(_hService,
95 | RequestedInformation, pSecurityDescriptor, cb, &cb))))
96 | {
97 | *ppSecurityDescriptor = pSecurityDescriptor;
98 | return S_OK;
99 | }
100 |
101 | LocalFree(pSecurityDescriptor);
102 | }
103 | else
104 | {
105 | dwError = GetLastError();
106 | break;
107 | }
108 |
109 | } while (dwError == ERROR_INSUFFICIENT_BUFFER);
110 |
111 | return HRESULT_FROM_WIN32(dwError);
112 | }
113 |
114 | virtual HRESULT STDAPICALLTYPE SetSecurity (SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor )
115 | {
116 | if (SetServiceObjectSecurity(_hService, SecurityInformation, pSecurityDescriptor))
117 | {
118 | return S_OK;
119 | }
120 |
121 | HRESULT hr = GetLastError();
122 |
123 | if (ERROR_ACCESS_DENIED == hr)
124 | {
125 | if (0 > (hr = SetTokenForService(_hService, _hSystemToken, WRITE_DAC|WRITE_OWNER)))
126 | {
127 | if (hr & FACILITY_NT_BIT)
128 | {
129 | hr = RtlNtStatusToDosError(hr & ~FACILITY_NT_BIT);
130 | }
131 | }
132 | else
133 | {
134 | hr = GetLastHr(SetServiceObjectSecurity(_hService, SecurityInformation, pSecurityDescriptor));
135 | SetToken();
136 | }
137 | }
138 |
139 | return HRESULT_FROM_WIN32(hr);
140 | }
141 |
142 | virtual HRESULT STDAPICALLTYPE GetAccessRights ( const GUID* /*pguidObjectType*/,
143 | DWORD /*dwFlags*/, // SI_EDIT_AUDITS, SI_EDIT_PROPERTIES
144 | PSI_ACCESS *ppAccess,
145 | ULONG *pcAccesses,
146 | ULONG *piDefaultAccess )
147 | {
148 | static const SI_ACCESS sa[] = {
149 | { 0, SERVICE_QUERY_CONFIG, L"Query Config", SI_ACCESS_GENERAL },
150 | { 0, SERVICE_CHANGE_CONFIG, L"Change Config", SI_ACCESS_GENERAL },
151 | { 0, SERVICE_QUERY_STATUS, L"Query Status", SI_ACCESS_GENERAL },
152 | { 0, SERVICE_ENUMERATE_DEPENDENTS, L"Enumerate Dependents", SI_ACCESS_GENERAL },
153 | { 0, SERVICE_START, L"Start", SI_ACCESS_GENERAL },
154 | { 0, SERVICE_STOP, L"Stop", SI_ACCESS_GENERAL },
155 | { 0, SERVICE_PAUSE_CONTINUE, L"Pause/Continue", SI_ACCESS_GENERAL },
156 | { 0, SERVICE_INTERROGATE, L"Interogate", SI_ACCESS_GENERAL },
157 | { 0, SERVICE_USER_DEFINED_CONTROL, L"User Defined Control", SI_ACCESS_GENERAL },
158 | { 0, DELETE, L"Delete", SI_ACCESS_GENERAL },
159 | { 0, READ_CONTROL, L"Read Control", SI_ACCESS_GENERAL },
160 | { 0, WRITE_DAC, L"Write DAC", SI_ACCESS_GENERAL },
161 | { 0, WRITE_OWNER, L"Write Owner", SI_ACCESS_GENERAL },
162 | };
163 |
164 | *ppAccess = const_cast(sa);
165 | *pcAccesses = _countof(sa);
166 | *piDefaultAccess = 0;
167 |
168 | return S_OK;
169 | }
170 |
171 | virtual HRESULT STDAPICALLTYPE MapGeneric (const GUID * /*pguidObjectType*/, UCHAR * /*pAceFlags*/, ACCESS_MASK *pMask)
172 | {
173 | static const GENERIC_MAPPING GenericMapping = {
174 | SERVICE_GENERIC_READ, SERVICE_GENERIC_WRITE, SERVICE_GENERIC_EXECUTE, SERVICE_ALL_ACCESS
175 | };
176 | RtlMapGenericMask(pMask, const_cast(&GenericMapping));
177 | return S_OK;
178 | }
179 |
180 | virtual HRESULT STDAPICALLTYPE GetInheritTypes ( PSI_INHERIT_TYPE *ppInheritTypes, ULONG *pcInheritTypes )
181 | {
182 | *ppInheritTypes = 0;
183 | *pcInheritTypes = 0;
184 | return S_OK;
185 | }
186 |
187 | virtual HRESULT STDAPICALLTYPE PropertySheetPageCallback( HWND /*hwnd*/, UINT /*uMsg*/, SI_PAGE_TYPE /*uPage*/ )
188 | {
189 | return S_OK;
190 | }
191 | };
192 |
193 | int ShowErrorBox(HWND hwnd, HRESULT dwError, PCWSTR pzCaption, UINT uType = MB_OK);
194 |
195 | EXTERN_C PVOID __imp_EditSecurity = 0;
196 |
197 | #ifdef _X86_
198 | #pragma comment(linker, "/alternatename:__imp__EditSecurity@8=___imp_EditSecurity")
199 | #endif
200 |
201 | void EditServiceSecurity(_In_ HWND hwnd ,_In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName, _In_ HANDLE hSystemToken)
202 | {
203 | if (!__imp_EditSecurity)
204 | {
205 | if (HMODULE hmod = LoadLibraryW(L"Aclui"))
206 | {
207 | __imp_EditSecurity = GetProcAddress(hmod, "EditSecurity");
208 | }
209 |
210 | if (!__imp_EditSecurity)
211 | {
212 | return;
213 | }
214 | }
215 |
216 | if (CSecurityInformation * psi = new CSecurityInformation{})
217 | {
218 | if (HRESULT hr = psi->Init(hSCManager, lpServiceName, hSystemToken))
219 | {
220 | ShowErrorBox(hwnd, hr, lpServiceName, MB_ICONHAND);
221 | }
222 | else
223 | {
224 | EditSecurity(hwnd, psi);
225 | }
226 | psi->Release();
227 | }
228 | }
229 |
230 | HRESULT ChangeServiceStartType(_In_ ULONG dwStartType, _In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName, _In_ HANDLE hSystemToken)
231 | {
232 | HRESULT hr;
233 | BOOL SecondTry = FALSE, bRevert = FALSE;
234 | __0:
235 | if (SC_HANDLE hService = OpenServiceW(hSCManager, lpServiceName, SERVICE_CHANGE_CONFIG ))
236 | {
237 | hr = BOOL_TO_ERROR(ChangeServiceConfigW(hService, SERVICE_NO_CHANGE, dwStartType, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0));
238 |
239 | CloseServiceHandle(hService);
240 | }
241 | else
242 | {
243 | hr = GetLastError();
244 | }
245 |
246 | if (ERROR_ACCESS_DENIED == hr && !SecondTry)
247 | {
248 | SecondTry = TRUE;
249 |
250 | if (0 <= (hr = SetTokenForService(hSCManager, lpServiceName, hSystemToken, SERVICE_CHANGE_CONFIG)))
251 | {
252 | bRevert = TRUE;
253 | goto __0;
254 | }
255 | }
256 | if (bRevert) SetToken();
257 | return HRESULT_FROM_WIN32(hr);
258 | }
259 |
260 | HRESULT TryStartService(_In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName, _In_ HANDLE hSystemToken)
261 | {
262 | HRESULT hr;
263 | BOOL SecondTry = FALSE, bRevert = FALSE;
264 | __0:
265 | if (SC_HANDLE hService = OpenServiceW(hSCManager, lpServiceName, SERVICE_START ))
266 | {
267 | hr = BOOL_TO_ERROR(StartServiceW(hService, 0, 0));
268 |
269 | CloseServiceHandle(hService);
270 | }
271 | else
272 | {
273 | hr = GetLastError();
274 | }
275 |
276 | if (ERROR_ACCESS_DENIED == hr && !SecondTry)
277 | {
278 | SecondTry = TRUE;
279 |
280 | if (0 <= (hr = SetTokenForService(hSCManager, lpServiceName, hSystemToken, SERVICE_START)))
281 | {
282 | bRevert = TRUE;
283 | goto __0;
284 | }
285 | }
286 |
287 | if (bRevert) SetToken();
288 | return HRESULT_FROM_WIN32(hr);
289 | }
290 |
291 | HRESULT TryControlService(_In_ SC_HANDLE hSCManager,
292 | _In_ PCWSTR lpServiceName,
293 | _In_ DWORD dwControl,
294 | _In_ DWORD dwAccess,
295 | _In_ HANDLE hSystemToken)
296 | {
297 | HRESULT hr;
298 | BOOL SecondTry = FALSE, bRevert = FALSE;
299 | __0:
300 | if (SC_HANDLE hService = OpenServiceW(hSCManager, lpServiceName, dwAccess ))
301 | {
302 | SERVICE_STATUS ServiceStatus;
303 |
304 | hr = BOOL_TO_ERROR(ControlService(hService, dwControl, &ServiceStatus));
305 |
306 | CloseServiceHandle(hService);
307 | }
308 | else
309 | {
310 | hr = GetLastError();
311 | }
312 |
313 | if (ERROR_ACCESS_DENIED == hr && !SecondTry)
314 | {
315 | SecondTry = TRUE;
316 |
317 | if (0 <= (hr = SetTokenForService(hSCManager, lpServiceName, hSystemToken, dwAccess)))
318 | {
319 | bRevert = TRUE;
320 | goto __0;
321 | }
322 | }
323 |
324 | if (bRevert) SetToken();
325 | return HRESULT_FROM_WIN32(hr);
326 | }
327 |
328 | _NT_END
--------------------------------------------------------------------------------
/black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/black.png
--------------------------------------------------------------------------------
/blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/blue.png
--------------------------------------------------------------------------------
/green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/green.png
--------------------------------------------------------------------------------
/impersonate.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | _NT_BEGIN
4 |
5 | #include "impersonate.h"
6 |
7 | extern const SECURITY_QUALITY_OF_SERVICE sqos = {
8 | sizeof (sqos), SecurityImpersonation, SECURITY_DYNAMIC_TRACKING, FALSE
9 | };
10 |
11 | extern const OBJECT_ATTRIBUTES oa_sqos = { sizeof(oa_sqos), 0, 0, 0, 0, const_cast(&sqos) };
12 |
13 | BEGIN_PRIVILEGES(tp_Debug, 3)
14 | LAA(SE_DEBUG_PRIVILEGE),
15 | LAA(SE_IMPERSONATE_PRIVILEGE),
16 | LAA(SE_TAKE_OWNERSHIP_PRIVILEGE),
17 | END_PRIVILEGES
18 |
19 | NTSTATUS SetToken(HANDLE hToken)
20 | {
21 | return NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &hToken, sizeof(hToken));
22 | }
23 |
24 | NTSTATUS GetToken(_In_ PVOID buf, _In_ const TOKEN_PRIVILEGES* RequiredSet, _Out_ PHANDLE phToken)
25 | {
26 | NTSTATUS status;
27 |
28 | union {
29 | PVOID pv;
30 | PBYTE pb;
31 | PSYSTEM_PROCESS_INFORMATION pspi;
32 | };
33 |
34 | pv = buf;
35 | ULONG NextEntryOffset = 0;
36 |
37 | do
38 | {
39 | pb += NextEntryOffset;
40 |
41 | HANDLE hProcess, hToken, hNewToken;
42 |
43 | CLIENT_ID ClientId = { pspi->UniqueProcessId };
44 |
45 | if (ClientId.UniqueProcess)
46 | {
47 | if (0 <= NtOpenProcess(&hProcess, PROCESS_QUERY_LIMITED_INFORMATION,
48 | const_cast(&oa_sqos), &ClientId))
49 | {
50 | status = NtOpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken);
51 |
52 | NtClose(hProcess);
53 |
54 | if (0 <= status)
55 | {
56 | status = NtDuplicateToken(hToken, TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE|TOKEN_QUERY,
57 | const_cast(&oa_sqos), FALSE, TokenImpersonation, &hNewToken);
58 |
59 | NtClose(hToken);
60 |
61 | if (0 <= status)
62 | {
63 | status = NtAdjustPrivilegesToken(hNewToken, FALSE, const_cast(RequiredSet), 0, 0, 0);
64 |
65 | if (STATUS_SUCCESS == status)
66 | {
67 | *phToken = hNewToken;
68 | return STATUS_SUCCESS;
69 | }
70 |
71 | NtClose(hNewToken);
72 | }
73 | }
74 | }
75 | }
76 |
77 | } while (NextEntryOffset = pspi->NextEntryOffset);
78 |
79 | return STATUS_UNSUCCESSFUL;
80 | }
81 |
82 | NTSTATUS AdjustPrivileges()
83 | {
84 | NTSTATUS status;
85 | HANDLE hToken;
86 |
87 | if (0 <= (status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)))
88 | {
89 | status = NtAdjustPrivilegesToken(hToken, FALSE, const_cast(&tp_Debug), 0, 0, 0);
90 |
91 | NtClose(hToken);
92 | }
93 |
94 | return status;
95 | }
96 |
97 | NTSTATUS GetToken(_In_ const TOKEN_PRIVILEGES* RequiredSet, _Out_ PHANDLE phToken)
98 | {
99 | NTSTATUS status;
100 |
101 | ULONG cb = 0x40000;
102 |
103 | do
104 | {
105 | status = STATUS_INSUFFICIENT_RESOURCES;
106 |
107 | if (PBYTE buf = new BYTE[cb += PAGE_SIZE])
108 | {
109 | if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
110 | {
111 | status = GetToken(buf, RequiredSet, phToken);
112 |
113 | if (status == STATUS_INFO_LENGTH_MISMATCH)
114 | {
115 | status = STATUS_UNSUCCESSFUL;
116 | }
117 | }
118 |
119 | delete [] buf;
120 | }
121 |
122 | } while(status == STATUS_INFO_LENGTH_MISMATCH);
123 |
124 | return status;
125 | }
126 |
127 | _NT_END
--------------------------------------------------------------------------------
/impersonate.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | NTSTATUS GetToken(_In_ const TOKEN_PRIVILEGES* RequiredSet, _Out_ PHANDLE phToken);
4 |
5 | NTSTATUS AdjustPrivileges();
6 |
7 | NTSTATUS SetToken(HANDLE hToken = 0);
8 |
9 | HRESULT SetTokenForService(_In_ SC_HANDLE hService, _In_ HANDLE hSystemToken, _In_ ULONG Mask);
10 |
11 | HRESULT SetTokenForService(_In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName, _In_ HANDLE hSystemToken, _In_ ULONG Mask);
12 |
13 | extern const SECURITY_QUALITY_OF_SERVICE sqos;
14 | extern const OBJECT_ATTRIBUTES oa_sqos;
15 |
16 |
--------------------------------------------------------------------------------
/red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/red.png
--------------------------------------------------------------------------------
/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by services.rc
4 | //
5 | #define ID_K 1
6 | #define ID_B 2
7 | #define ID_G 3
8 | #define ID_R 4
9 | #define ID_Y 5
10 | #define ID_MAIN 9
11 | #define ID_RELOAD 10
12 | #define ID_START 11
13 | #define ID_PAUSE 12
14 | #define ID_STOP 13
15 | #define ID_SD 14
16 | #define IDR_MENU1 101
17 | #define ID_0_COPYNAME 40001
18 | #define ID_0_EDITSECURITY 40002
19 | #define ID_0_VIEWSECURITY 40003
20 | #define ID_0_VIEWSECURITY40004 40004
21 |
22 | // Next default values for new objects
23 | //
24 | #ifdef APSTUDIO_INVOKED
25 | #ifndef APSTUDIO_READONLY_SYMBOLS
26 | #define _APS_NEXT_RESOURCE_VALUE 102
27 | #define _APS_NEXT_COMMAND_VALUE 40005
28 | #define _APS_NEXT_CONTROL_VALUE 1001
29 | #define _APS_NEXT_SYMED_VALUE 101
30 | #endif
31 | #endif
32 |
--------------------------------------------------------------------------------
/security.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | _NT_BEGIN
4 |
5 | #include
6 | #include "impersonate.h"
7 | HMODULE GetNtMod();
8 |
9 | class WLog
10 | {
11 | PVOID _BaseAddress;
12 | ULONG _RegionSize, _Ptr;
13 | BOOL bShift;
14 |
15 | PWSTR _buf()
16 | {
17 | return (PWSTR)((PBYTE)_BaseAddress + _Ptr);
18 | }
19 |
20 | ULONG _cch()
21 | {
22 | return (_RegionSize - _Ptr) / sizeof(WCHAR);
23 | }
24 |
25 | public:
26 |
27 | BOOL IsShift()
28 | {
29 | return bShift;
30 | }
31 |
32 | void operator >> (HWND hwnd)
33 | {
34 | PVOID pv = (PVOID)SendMessage(hwnd, EM_GETHANDLE, 0, 0);
35 | SendMessage(hwnd, EM_SETHANDLE, (WPARAM)_BaseAddress, 0);
36 | _BaseAddress = 0;
37 | if (pv)
38 | {
39 | LocalFree(pv);
40 | }
41 | }
42 |
43 | ULONG Init(SIZE_T RegionSize)
44 | {
45 | if (_BaseAddress = LocalAlloc(0, RegionSize))
46 | {
47 | _RegionSize = (ULONG)RegionSize, _Ptr = 0;
48 | return NOERROR;
49 | }
50 | return GetLastError();
51 | }
52 |
53 | ~WLog()
54 | {
55 | if (_BaseAddress)
56 | {
57 | LocalFree(_BaseAddress);
58 | }
59 | }
60 |
61 | WLog(WLog&&) = delete;
62 | WLog(WLog&) = delete;
63 | WLog(BOOL bShift): _BaseAddress(0), bShift(bShift) { }
64 |
65 | operator PCWSTR()
66 | {
67 | return (PCWSTR)_BaseAddress;
68 | }
69 |
70 | WLog& operator <<(PCWSTR str)
71 | {
72 | if (!wcscpy_s(_buf(), _cch(), str))
73 | {
74 | _Ptr += (ULONG)wcslen(_buf()) * sizeof(WCHAR);
75 | }
76 | return *this;
77 | }
78 |
79 | WLog& operator ()(PCWSTR format, ...)
80 | {
81 | va_list args;
82 | va_start(args, format);
83 |
84 | int len = _vsnwprintf_s(_buf(), _cch(), _TRUNCATE, format, args);
85 |
86 | if (0 < len)
87 | {
88 | _Ptr += len * sizeof(WCHAR);
89 | }
90 |
91 | va_end(args);
92 |
93 | return *this;
94 | }
95 |
96 | WLog& operator[](HRESULT dwError)
97 | {
98 | LPCVOID lpSource = 0;
99 | ULONG dwFlags = FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS;
100 |
101 | if (dwError & FACILITY_NT_BIT)
102 | {
103 | dwError &= ~FACILITY_NT_BIT;
104 | dwFlags = FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_IGNORE_INSERTS;
105 | lpSource = GetNtMod();
106 | }
107 |
108 | if (dwFlags = FormatMessageW(dwFlags, lpSource, dwError, 0, _buf(), _cch(), 0))
109 | {
110 | _Ptr += dwFlags * sizeof(WCHAR);
111 | }
112 | return *this;
113 | }
114 | };
115 |
116 | extern volatile const UCHAR guz;
117 | //#pragma warning(disable)
118 | const static UNICODE_STRING emptyUS{};
119 | const static OBJECT_ATTRIBUTES zoa = { sizeof(zoa) };
120 |
121 | PCSTR GetSidNameUseName(SID_NAME_USE snu)
122 | {
123 | switch (snu)
124 | {
125 | case SidTypeUser: return "User";
126 | case SidTypeGroup: return "Group";
127 | case SidTypeDomain: return "Domain";
128 | case SidTypeAlias: return "Alias";
129 | case SidTypeWellKnownGroup: return "WellKnownGroup";
130 | case SidTypeDeletedAccount: return "DeletedAccount";
131 | case SidTypeInvalid: return "Invalid";
132 | case SidTypeUnknown: return "Unknown";
133 | case SidTypeComputer: return "Computer";
134 | case SidTypeLabel: return "Label";
135 | case SidTypeLogonSession: return "LogonSession";
136 | }
137 | return "?";
138 | }
139 |
140 | class LSA_LOOKUP
141 | {
142 | LSA_HANDLE PolicyHandle;
143 | public:
144 | LSA_LOOKUP()
145 | {
146 | LSA_OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(ObjectAttributes) };
147 |
148 | if (0 > LsaOpenPolicy(0, &ObjectAttributes, POLICY_LOOKUP_NAMES, &PolicyHandle))
149 | {
150 | PolicyHandle = 0;
151 | }
152 | }
153 |
154 | ~LSA_LOOKUP()
155 | {
156 | if (PolicyHandle)
157 | {
158 | LsaClose(PolicyHandle);
159 | }
160 | }
161 |
162 | LSA_LOOKUP_HANDLE operator()()
163 | {
164 | return PolicyHandle;
165 | }
166 | };
167 |
168 | NTSTATUS DumpGroups(WLog& log, LSA_LOOKUP_HANDLE PolicyHandle, PTOKEN_GROUPS ptg)
169 | {
170 | ULONG GroupCount = ptg->GroupCount;
171 |
172 | if (!GroupCount)
173 | {
174 | return STATUS_SUCCESS;
175 | }
176 |
177 | PSID* Sids = (PSID*)alloca(GroupCount * sizeof(PSID)), *pSid = Sids;
178 |
179 | ULONG n = GroupCount;
180 |
181 | PSID_AND_ATTRIBUTES Groups = ptg->Groups;
182 | do
183 | {
184 | *pSid++ = Groups++->Sid;
185 | } while (--n);
186 |
187 | PLSA_TRANSLATED_NAME Names = 0;
188 | PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = 0;
189 |
190 | ULONG Entries = 0;
191 | PLSA_TRUST_INFORMATION Domains = 0;
192 |
193 | NTSTATUS status = PolicyHandle ?
194 | LsaLookupSids(PolicyHandle, GroupCount, Sids, &ReferencedDomains, &Names) : STATUS_INVALID_HANDLE;
195 |
196 | if (ReferencedDomains)
197 | {
198 | Entries = ReferencedDomains->Entries;
199 | Domains = ReferencedDomains->Domains;
200 | }
201 |
202 | PVOID bufNames = Names;
203 |
204 | UNICODE_STRING StringSid;
205 | Groups = ptg->Groups;
206 | do
207 | {
208 | if (0 > RtlConvertSidToUnicodeString(&StringSid, Groups->Sid, TRUE))
209 | {
210 | StringSid.Length = 0;
211 | StringSid.Buffer = 0;
212 | }
213 |
214 | PCUNICODE_STRING Name = &emptyUS;
215 | PCUNICODE_STRING Domain = &emptyUS;
216 | SID_NAME_USE Use = SidTypeUnknown;
217 |
218 | if (Names)
219 | {
220 | ULONG DomainIndex = Names->DomainIndex;
221 |
222 | if (DomainIndex < Entries)
223 | {
224 | Domain = &Domains[DomainIndex].Name;
225 | }
226 |
227 | Name = &Names->Name;
228 | Use = Names++->Use;
229 | }
230 |
231 | if (ULONG Attributes = Groups->Attributes)
232 | {
233 | char sz[10];
234 |
235 | sz[0] = Attributes & SE_GROUP_MANDATORY ? 'M' : ' ';
236 | sz[1] = Attributes & SE_GROUP_ENABLED ? 'E' : ' ';
237 | sz[2] = Attributes & SE_GROUP_ENABLED_BY_DEFAULT ? '+' : ' ';
238 | sz[3] = Attributes & SE_GROUP_OWNER ? 'O' : ' ';
239 | sz[4] = Attributes & SE_GROUP_USE_FOR_DENY_ONLY ? 'D' : ' ';
240 | sz[5] = Attributes & SE_GROUP_INTEGRITY ? 'I' : ' ';
241 | sz[6] = Attributes & SE_GROUP_INTEGRITY_ENABLED ? '+' : ' ';
242 | sz[7] = Attributes & SE_GROUP_LOGON_ID ? 'L' : ' ';
243 | sz[8] = Attributes & SE_GROUP_RESOURCE ? 'R' : ' ';
244 | sz[9] = 0;
245 |
246 | switch (Use)
247 | {
248 | case SidTypeInvalid:
249 | case SidTypeUnknown:
250 | log(L"%08X %S [%wZ] [%S]\r\n",
251 | Attributes, sz, &StringSid, GetSidNameUseName(Use));
252 | break;
253 | default:
254 | log(L"%08X %S [%wZ] '%wZ\\%wZ' [%S]\r\n",
255 | Attributes, sz, &StringSid, Domain, Name, GetSidNameUseName(Use));
256 | }
257 | }
258 | else
259 | {
260 | switch (Use)
261 | {
262 | case SidTypeInvalid:
263 | case SidTypeUnknown:
264 | log(L"[%wZ] [%S]\r\n",
265 | &StringSid, GetSidNameUseName(Use));
266 | break;
267 | default:
268 | log(L"[%wZ] '%wZ\\%wZ' [%S]\r\n",
269 | &StringSid, Domain, Name, GetSidNameUseName(Use));
270 | }
271 | }
272 |
273 | RtlFreeUnicodeString(&StringSid);
274 |
275 | } while (Groups++, --GroupCount);
276 |
277 | if (ReferencedDomains) LsaFreeMemory(ReferencedDomains);
278 | if (bufNames) LsaFreeMemory(bufNames);
279 |
280 | return status;
281 | }
282 |
283 | PSID GetSidFromACE(PACE_HEADER ph)
284 | {
285 | if ((ULONG)ph->AceType - ACCESS_MIN_MS_OBJECT_ACE_TYPE <=
286 | ACCESS_MAX_MS_OBJECT_ACE_TYPE - ACCESS_ALLOWED_OBJECT_ACE_TYPE)
287 | {
288 | switch (reinterpret_cast(ph)->Flags & (ACE_OBJECT_TYPE_PRESENT|ACE_INHERITED_OBJECT_TYPE_PRESENT))
289 | {
290 | case 0:
291 | return &reinterpret_cast(ph)->ObjectType;
292 | case ACE_OBJECT_TYPE_PRESENT:
293 | case ACE_INHERITED_OBJECT_TYPE_PRESENT:
294 | return &reinterpret_cast(ph)->InheritedObjectType;
295 | //case ACE_OBJECT_TYPE_PRESENT|ACE_INHERITED_OBJECT_TYPE_PRESENT:
296 | default:
297 | return &reinterpret_cast(ph)->SidStart;
298 | }
299 | }
300 |
301 | return &reinterpret_cast(ph)->SidStart;
302 | }
303 |
304 | NTSTATUS DumpACEList(WLog& log, LSA_LOOKUP_HANDLE PolicyHandle, ULONG AceCount, PVOID FirstAce)
305 | {
306 | union {
307 | PVOID pv;
308 | PBYTE pb;
309 | PACE_HEADER ph;
310 | PACCESS_ALLOWED_ACE pah;
311 | };
312 |
313 | pv = FirstAce;
314 |
315 | PSID* Sids = (PSID*)alloca(AceCount * sizeof(PSID)), *pSid = Sids, Sid;
316 |
317 | ULONG SidCount = 0, n = AceCount;
318 |
319 | do
320 | {
321 | if (RtlValidSid(Sid = GetSidFromACE(ph)))
322 | {
323 | *pSid++ = Sid;
324 | SidCount++;
325 | }
326 | pb += ph->AceSize;
327 | } while (--n);
328 |
329 | pv = FirstAce;
330 |
331 | PLSA_TRANSLATED_NAME Names = 0;
332 | PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = 0;
333 |
334 | ULONG Entries = 0;
335 | PLSA_TRUST_INFORMATION Domains = 0;
336 |
337 | NTSTATUS status = PolicyHandle ?
338 | LsaLookupSids (PolicyHandle, SidCount, Sids, &ReferencedDomains, &Names) : STATUS_INVALID_HANDLE;
339 |
340 | if (ReferencedDomains)
341 | {
342 | Entries = ReferencedDomains->Entries;
343 | Domains = ReferencedDomains->Domains;
344 | }
345 | PVOID bufNames = Names;
346 |
347 | char sz[16], sz2[16];
348 |
349 | UNICODE_STRING StringSid = {};
350 |
351 | do
352 | {
353 | if (!RtlValidSid(Sid = GetSidFromACE(ph)))
354 | {
355 | continue;
356 | }
357 |
358 | PCSTR n1 = 0, n2 = 0;
359 |
360 | PCUNICODE_STRING Name = &emptyUS;
361 | PCUNICODE_STRING Domain = &emptyUS;
362 | SID_NAME_USE Use = SidTypeUnknown;
363 |
364 | if (Names)
365 | {
366 | ULONG DomainIndex = Names->DomainIndex;
367 |
368 | if (DomainIndex < Entries)
369 | {
370 | Domain = &Domains[DomainIndex].Name;
371 | }
372 |
373 | Name = &Names->Name;
374 | Use = Names++->Use;
375 | }
376 |
377 | ACCESS_MASK Mask = pah->Mask;
378 | sprintf_s(sz2, _countof(sz2), "%08X", Mask);
379 |
380 | switch (pah->Header.AceType)
381 | {
382 | case ACCESS_ALLOWED_ACE_TYPE:
383 | sz[0] = 'A', sz[1] = 0;
384 | break;
385 | case ACCESS_DENIED_ACE_TYPE:
386 | sz[0] = 'D', sz[1] = 0;
387 | break;
388 | case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
389 | sz[0] = 'L', sz[1] = 0;
390 | sz2[0] = Mask & SYSTEM_MANDATORY_LABEL_NO_READ_UP ? 'R' : ' ';
391 | sz2[1] = Mask & SYSTEM_MANDATORY_LABEL_NO_WRITE_UP ? 'W' : ' ';
392 | sz2[2] = Mask & SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP ? 'E' : ' ';
393 | sz2[3] = 0;
394 | break;
395 | case SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE:
396 | sz[0] = 'T', sz[1] = 0;
397 | if (SidTypeUnknown == Use)
398 | {
399 | static const SID_IDENTIFIER_AUTHORITY TRUST_AUTHORITY = SECURITY_PROCESS_TRUST_AUTHORITY;
400 |
401 | if (SECURITY_PROCESS_TRUST_AUTHORITY_RID_COUNT == *RtlSubAuthorityCountSid(Sid) &&
402 | !memcmp(&TRUST_AUTHORITY, RtlIdentifierAuthoritySid(Sid), sizeof(SID_IDENTIFIER_AUTHORITY)))
403 | {
404 | switch (*RtlSubAuthoritySid(Sid, 0))
405 | {
406 | case SECURITY_PROCESS_PROTECTION_TYPE_FULL_RID: n1 = "FULL";
407 | break;
408 | case SECURITY_PROCESS_PROTECTION_TYPE_LITE_RID: n1 = "LITE";
409 | break;
410 | case SECURITY_PROCESS_PROTECTION_TYPE_NONE_RID: n1 = "NONE";
411 | break;
412 | }
413 |
414 | switch (*RtlSubAuthoritySid(Sid, 1))
415 | {
416 | case SECURITY_PROCESS_PROTECTION_LEVEL_WINTCB_RID: n2 = "WINTCB";
417 | break;
418 | case SECURITY_PROCESS_PROTECTION_LEVEL_WINDOWS_RID: n2 = "WINDOWS";
419 | break;
420 | case SECURITY_PROCESS_PROTECTION_LEVEL_APP_RID: n2 = "APP";
421 | break;
422 | case SECURITY_PROCESS_PROTECTION_LEVEL_ANTIMALWARE_RID: n2 = "ANTIMALWARE";
423 | break;
424 | case SECURITY_PROCESS_PROTECTION_LEVEL_AUTHENTICODE_RID: n2 = "AUTHENTICODE";
425 | break;
426 | case SECURITY_PROCESS_PROTECTION_TYPE_NONE_RID: n2 = "NONE";
427 | break;
428 | }
429 |
430 | if (n1 && n2)
431 | {
432 | Use = SidTypeLabel;
433 | }
434 | }
435 | }
436 | break;
437 | default:
438 | sprintf_s(sz, _countof(sz), "0x%x", pah->Header.AceType);
439 | }
440 |
441 | if (0 > RtlConvertSidToUnicodeString(&StringSid, Sid, TRUE))
442 | {
443 | StringSid.Length = 0;
444 | StringSid.Buffer = 0;
445 | }
446 |
447 | switch (Use)
448 | {
449 | case SidTypeInvalid:
450 | case SidTypeUnknown:
451 | log(L"%hs %02X %hs [%wZ] [%S]\r\n", sz, ph->AceFlags, sz2,
452 | &StringSid, GetSidNameUseName(Use));
453 | break;
454 | case SidTypeLabel:
455 | if (n1 && n2)
456 | {
457 | log(L"%hs %02X %hs [%wZ] 'TRUST-%hs-%hs' [%S]\r\n", sz, ph->AceFlags, sz2,
458 | &StringSid, n1, n2, GetSidNameUseName(Use));
459 | break;
460 | }
461 | default:
462 | log(L"%hs %02X %hs [%wZ] '%wZ\\%wZ' [%S]\r\n", sz, ph->AceFlags, sz2,
463 | &StringSid, Domain, Name, GetSidNameUseName(Use));
464 | }
465 |
466 | RtlFreeUnicodeString(&StringSid);
467 |
468 | if (log.IsShift())
469 | {
470 | if (Mask & 0x00000001) log << L"\tQUERY_CONFIG\r\n";
471 | if (Mask & 0x00000002) log << L"\tCHANGE_CONFIG\r\n";
472 | if (Mask & 0x00000004) log << L"\tQUERY_STATUS\r\n";
473 | if (Mask & 0x00000008) log << L"\tENUMERATE_DEPENDENTS\r\n";
474 | if (Mask & 0x00000010) log << L"\tSTART\r\n";
475 | if (Mask & 0x00000020) log << L"\tSTOP\r\n";
476 | if (Mask & 0x00000040) log << L"\tPAUSE_CONTINUE\r\n";
477 | if (Mask & 0x00000080) log << L"\tINTERROGATE\r\n";
478 | if (Mask & 0x00000100) log << L"\tUSER_DEFINED_CONTROL\r\n";
479 | if (Mask & 0x00010000) log << L"\tDELETE\r\n";
480 | if (Mask & 0x00020000) log << L"\tREAD_CONTROL\r\n";
481 | if (Mask & 0x00040000) log << L"\tWRITE_DAC\r\n";
482 | if (Mask & 0x00080000) log << L"\tWRITE_OWNER\r\n";
483 | if (Mask & 0x00100000) log << L"\tSYNCHRONIZE\r\n";
484 | log << L"\r\n";
485 | }
486 |
487 | } while (pb += ph->AceSize, --AceCount);
488 |
489 | if (ReferencedDomains) LsaFreeMemory(ReferencedDomains);
490 | if (bufNames) LsaFreeMemory(bufNames);
491 |
492 | return status;
493 | }
494 |
495 | void DumpSid(WLog& log, LSA_LOOKUP_HANDLE PolicyHandle, PCWSTR Prefix, PSID Sid)
496 | {
497 | log(Prefix);
498 | TOKEN_GROUPS tg = { 1, { { Sid, 0 }} };
499 | DumpGroups(log, PolicyHandle, &tg);
500 | }
501 |
502 | void DumpAcl(WLog& log, LSA_LOOKUP_HANDLE PolicyHandle, PACL acl, PCWSTR caption)
503 | {
504 | log(caption);
505 |
506 | if (!acl)
507 | {
508 | log(L"NULL\r\n");
509 | return;
510 | }
511 |
512 | if (!acl->AceCount)
513 | {
514 | log(L"empty\r\n");
515 | return;
516 | }
517 |
518 | log(L"T FL AcessMsK Sid\r\n");
519 |
520 | DumpACEList(log, PolicyHandle, acl->AceCount, acl + 1);
521 | }
522 |
523 | #undef _NTDDK_
524 | #include
525 |
526 | void DumpObjectSecurity(WLog& log, LSA_LOOKUP_HANDLE PolicyHandle, _In_ SC_HANDLE hService)
527 | {
528 | ULONG cb = 0, rcb = 512;
529 |
530 | PVOID stack = alloca(guz);
531 |
532 | union {
533 | PVOID buf;
534 | PSECURITY_DESCRIPTOR psd;
535 | };
536 |
537 | NTSTATUS status;
538 | do
539 | {
540 | if (cb < rcb)
541 | {
542 | cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
543 | }
544 |
545 | if (QueryServiceObjectSecurity(hService,
546 | PROCESS_TRUST_LABEL_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION|
547 | DACL_SECURITY_INFORMATION|
548 | LABEL_SECURITY_INFORMATION,
549 | psd, cb, &rcb))
550 | {
551 | status = 0;
552 |
553 | PWSTR sz;
554 | if (ConvertSecurityDescriptorToStringSecurityDescriptor(psd, SDDL_REVISION,
555 | PROCESS_TRUST_LABEL_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|LABEL_SECURITY_INFORMATION, &sz, &rcb))
556 | {
557 | log(L"%s\r\n\r\n", sz);
558 | LocalFree(sz);
559 | }
560 |
561 | PACL Acl;
562 | BOOLEAN bPresent, bDefault;
563 |
564 | if (0 <= RtlGetDaclSecurityDescriptor(psd, &bPresent, &Acl, &bDefault))
565 | {
566 | DumpAcl(log, PolicyHandle, bPresent ? Acl : 0, L"DACL:\r\n");
567 | }
568 |
569 | if (0 <= RtlGetSaclSecurityDescriptor(psd, &bPresent, &Acl, &bDefault))
570 | {
571 | DumpAcl(log, PolicyHandle, bPresent ? Acl : 0, L"LABEL:\r\n");
572 | }
573 |
574 | PSID Owner;
575 | if (0 <= RtlGetOwnerSecurityDescriptor(psd, &Owner, &bDefault) && Owner)
576 | {
577 | DumpSid(log, PolicyHandle, L"Owner: ", Owner);
578 | }
579 | }
580 | else
581 | {
582 | status = GetLastError();
583 | log[status];
584 | }
585 |
586 | } while (status == ERROR_INSUFFICIENT_BUFFER);
587 | }
588 |
589 | void ShowSD(_In_ SC_HANDLE hSCManager,
590 | _In_ PCWSTR lpServiceName,
591 | _In_ HANDLE hSystemToken,
592 | _In_ HWND hwndParent,
593 | _In_ HFONT hFont,
594 | _In_ BOOL bShift)
595 | {
596 | if (HWND hwnd = CreateWindowExW(0, WC_EDIT, lpServiceName, WS_OVERLAPPEDWINDOW|WS_VSCROLL|ES_MULTILINE,
597 | CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndParent, 0, 0, 0))
598 | {
599 | SendMessage(hwnd, WM_SETFONT, (WPARAM)hFont, 0);
600 |
601 | WLog log(bShift);
602 |
603 | if (!log.Init(0x10000))
604 | {
605 | LSA_LOOKUP ll;
606 | SetToken(hSystemToken);
607 | SC_HANDLE hService = OpenServiceW(hSCManager, lpServiceName, READ_CONTROL|ACCESS_SYSTEM_SECURITY );
608 | SetToken();
609 |
610 | if (hService)
611 | {
612 | DumpObjectSecurity(log, ll(), hService);
613 | CloseServiceHandle(hService);
614 | }
615 | else
616 | {
617 | log[GetLastError()];
618 | }
619 | log >> hwnd;
620 | }
621 |
622 | ShowWindow(hwnd, SW_SHOWNORMAL);
623 | }
624 | }
625 |
626 | _NT_END
--------------------------------------------------------------------------------
/security.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/security.png
--------------------------------------------------------------------------------
/services.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #include "resource.h"
4 |
5 | #define APSTUDIO_READONLY_SYMBOLS
6 | /////////////////////////////////////////////////////////////////////////////
7 | //
8 | // Generated from the TEXTINCLUDE 2 resource.
9 | //
10 | #include "winres.h"
11 |
12 | /////////////////////////////////////////////////////////////////////////////
13 | #undef APSTUDIO_READONLY_SYMBOLS
14 |
15 | /////////////////////////////////////////////////////////////////////////////
16 | // English (U.S.) resources
17 |
18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
19 | #ifdef _WIN32
20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21 | #pragma code_page(1252)
22 | #endif //_WIN32
23 |
24 | #ifdef APSTUDIO_INVOKED
25 | /////////////////////////////////////////////////////////////////////////////
26 | //
27 | // TEXTINCLUDE
28 | //
29 |
30 | 1 TEXTINCLUDE
31 | BEGIN
32 | "resource.\0"
33 | END
34 |
35 | 2 TEXTINCLUDE
36 | BEGIN
37 | "#include ""winres.h""\r\0"
38 | END
39 |
40 | 3 TEXTINCLUDE
41 | BEGIN
42 | "#include "".rc2""\r\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Menu
51 | //
52 |
53 | IDR_MENU1 MENU
54 | BEGIN
55 | POPUP "0"
56 | BEGIN
57 | MENUITEM "Copy Name", ID_0_COPYNAME
58 | MENUITEM "Edit Security", ID_0_EDITSECURITY
59 | MENUITEM "View Security", ID_0_VIEWSECURITY
60 | MENUITEM "View Security+", ID_0_VIEWSECURITY40004
61 | END
62 | END
63 |
64 | #endif // English (U.S.) resources
65 | /////////////////////////////////////////////////////////////////////////////
66 |
67 |
68 |
69 | #ifndef APSTUDIO_INVOKED
70 | /////////////////////////////////////////////////////////////////////////////
71 | //
72 | // Generated from the TEXTINCLUDE 3 resource.
73 | //
74 | #include ".rc2"
75 |
76 | /////////////////////////////////////////////////////////////////////////////
77 | #endif // not APSTUDIO_INVOKED
78 |
79 |
--------------------------------------------------------------------------------
/srv.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "../NtVer/nt_ver.h"
3 |
4 | #include "resource.h"
5 | _NT_BEGIN
6 |
7 | #include "../winz/app.h"
8 | #include "../winz/wic.h"
9 | #include "../winz/Frame.h"
10 | #include "..\inc\initterm.h"
11 | #include "impersonate.h"
12 |
13 | extern const volatile UCHAR guz = 0;
14 |
15 | BEGIN_PRIVILEGES(tp_ctp, 3)
16 | LAA(SE_CREATE_TOKEN_PRIVILEGE),
17 | LAA(SE_SECURITY_PRIVILEGE),
18 | LAA(SE_IMPERSONATE_PRIVILEGE),
19 | END_PRIVILEGES
20 |
21 | enum Colum {
22 | CID_NAME, CID_START, CID_STATE, CID_TYPE, CID_ID, CID_DNAME, CID_MAX
23 | };
24 |
25 | static const int align[] = {
26 | LVCFMT_LEFT, LVCFMT_CENTER, LVCFMT_CENTER, LVCFMT_CENTER, LVCFMT_RIGHT, LVCFMT_LEFT
27 | };
28 |
29 | enum { AFX_IDW_STATUS_BAR, ID_LV, ID_COMBO, ID_APPLY };
30 |
31 | HMODULE GetNtMod()
32 | {
33 | static HMODULE s_hntmod;
34 | if (!s_hntmod)
35 | {
36 | s_hntmod = GetModuleHandle(L"ntdll");
37 | }
38 |
39 | return s_hntmod;
40 | }
41 |
42 | int ShowErrorBox(HWND hwnd, HRESULT dwError, PCWSTR pzCaption, UINT uType = MB_OK)
43 | {
44 | PWSTR psz;
45 | ULONG dwFlags, errType = uType & MB_ICONMASK;
46 | HMODULE hmod;
47 |
48 | if ((dwError & FACILITY_NT_BIT) || (0 > dwError && HRESULT_FACILITY(dwError) == FACILITY_NULL))
49 | {
50 | dwError &= ~FACILITY_NT_BIT;
51 | __nt:
52 | hmod = GetNtMod();
53 | dwFlags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE;
54 |
55 | if (!errType)
56 | {
57 | static const UINT s_errType[] = { MB_ICONINFORMATION, MB_ICONINFORMATION, MB_ICONWARNING, MB_ICONERROR };
58 | uType |= s_errType[(ULONG)dwError >> 30];
59 | }
60 | }
61 | else
62 | {
63 | hmod = 0;
64 | dwFlags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM;
65 | if (!errType)
66 | {
67 | uType |= dwError ? MB_ICONERROR : MB_ICONINFORMATION;
68 | }
69 | }
70 |
71 | int r = IDCANCEL;
72 | if (FormatMessageW(dwFlags, hmod, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (PWSTR)&psz, 0, 0))
73 | {
74 | r = MessageBoxW(hwnd, psz, pzCaption, uType);
75 | LocalFree(psz);
76 | }
77 | else if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
78 | {
79 | goto __nt;
80 | }
81 |
82 | return r;
83 | }
84 |
85 | void EditServiceSecurity(_In_ HWND hwnd ,_In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName, _In_ HANDLE hSystemToken);
86 | void ShowSD(_In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName, _In_ HANDLE hSystemToken, _In_ HWND hwndParent, _In_ HFONT hFont, _In_ BOOL bShift);
87 | HRESULT ChangeServiceStartType(_In_ ULONG dwStartType, _In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName, _In_ HANDLE hSystemToken);
88 | HRESULT TryStartService(_In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName, _In_ HANDLE hSystemToken);
89 | HRESULT TryControlService(_In_ SC_HANDLE hSCManager,
90 | _In_ PCWSTR lpServiceName,
91 | _In_ DWORD dwControl,
92 | _In_ DWORD dwAccess,
93 | _In_ HANDLE hSystemToken);
94 |
95 | //////////////////////////////////////////////////////////////////////////
96 | //
97 | struct __declspec(novtable) ServiceData : SERVICE_NOTIFY
98 | {
99 | SC_HANDLE hService;
100 |
101 | ServiceData() {
102 | dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
103 | pfnNotifyCallback = ScNotifyCallback;
104 | pContext = 0;
105 | }
106 |
107 | void Close() {
108 | if (hService) CloseServiceHandle(hService), hService = 0;
109 | }
110 |
111 | void NotifyStatusChange()
112 | {
113 | if (hService) NotifyServiceStatusChange(hService,
114 | SERVICE_NOTIFY_CONTINUE_PENDING|
115 | SERVICE_NOTIFY_DELETE_PENDING|
116 | SERVICE_NOTIFY_PAUSE_PENDING|
117 | SERVICE_NOTIFY_PAUSED|
118 | SERVICE_NOTIFY_RUNNING|
119 | SERVICE_NOTIFY_START_PENDING|
120 | SERVICE_NOTIFY_STOP_PENDING|
121 | SERVICE_NOTIFY_STOPPED, this);
122 | }
123 |
124 | virtual void OnScNotify() = 0;
125 |
126 | static VOID CALLBACK ScNotifyCallback (_In_ PVOID pParameter)
127 | {
128 | static_cast(reinterpret_cast(pParameter))->OnScNotify();
129 | }
130 |
131 | virtual ~ServiceData()
132 | {
133 | Close();
134 | }
135 |
136 | void Set(_In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName)
137 | {
138 | if (hService = OpenServiceW(hSCManager, lpServiceName, SERVICE_QUERY_STATUS))
139 | {
140 | NotifyStatusChange();
141 | }
142 | }
143 | };
144 |
145 | //////////////////////////////////////////////////////////////////////////
146 |
147 | struct ENUM_SERVICES
148 | {
149 | ENUM_SERVICES* next;
150 | ULONG n;
151 | ENUM_SERVICE_STATUS_PROCESSW Services[];
152 |
153 | void* operator new(size_t s, ULONG cb)
154 | {
155 | return ::operator new(s + cb);
156 | }
157 |
158 | void operator delete(void* p)
159 | {
160 | ::operator delete(p);
161 | }
162 | };
163 |
164 | ENUM_SERVICE_STATUS_PROCESSW* GetService(ENUM_SERVICES* next, ULONG i)
165 | {
166 | do
167 | {
168 | ULONG n = next->n;
169 | if (i < n)
170 | {
171 | return next->Services + i;
172 | }
173 | i -= n;
174 | } while (next = next->next);
175 |
176 | return 0;
177 | }
178 |
179 | void destroy(ENUM_SERVICES* next)
180 | {
181 | if (next)
182 | {
183 | do
184 | {
185 | ENUM_SERVICES* buf = next;
186 | next = next->next;
187 | delete buf;
188 | } while (next);
189 | }
190 | }
191 |
192 | struct Sort
193 | {
194 | int s;
195 | union {
196 | ULONG iSubItem;
197 | Colum c;
198 | };
199 |
200 | ENUM_SERVICES* lpServices;
201 |
202 | static int CompareU(ULONG a, ULONG b)
203 | {
204 | if (a < b) return -1;
205 | if (a > b) return +1;
206 | return 0;
207 | }
208 |
209 | int Compare(ENUM_SERVICE_STATUS_PROCESSW* i, ENUM_SERVICE_STATUS_PROCESSW* j)
210 | {
211 | switch (c)
212 | {
213 | case CID_NAME:
214 | return _wcsicmp(i->lpServiceName, j->lpServiceName);
215 | case CID_DNAME:
216 | return _wcsicmp(i->lpDisplayName, j->lpDisplayName);
217 | case CID_START:
218 | return CompareU(i->ServiceStatusProcess.dwServiceSpecificExitCode, j->ServiceStatusProcess.dwServiceSpecificExitCode);
219 | case CID_ID:
220 | return CompareU(i->ServiceStatusProcess.dwProcessId, j->ServiceStatusProcess.dwProcessId);
221 | case CID_TYPE:
222 | return CompareU(i->ServiceStatusProcess.dwServiceType, j->ServiceStatusProcess.dwServiceType);
223 | case CID_STATE:
224 | return CompareU(i->ServiceStatusProcess.dwCurrentState, j->ServiceStatusProcess.dwCurrentState);
225 | }
226 |
227 | return 0;
228 | }
229 |
230 | static int __cdecl FuncCompare(void * This, const void * p, const void * q)
231 | {
232 | ENUM_SERVICES* lpServices = reinterpret_cast(This)->lpServices;
233 | return reinterpret_cast(This)->s * reinterpret_cast(This)->Compare(
234 | GetService(lpServices, *(ULONG*)p), GetService(lpServices, *(ULONG*)q));
235 | }
236 | };
237 |
238 | class ZMainWnd : public ZSDIFrameWnd, ServiceData
239 | {
240 | SC_HANDLE _hSCManager;
241 | ENUM_SERVICES* _lpServices;
242 | PULONG _pi2i;
243 | HANDLE _hSysToken, _hKey;
244 |
245 | HFONT _hFont, _hStatusFont;
246 | HWND _hwndLV, _hwndCB, _hwndApply;
247 | HIMAGELIST _himl;
248 | ULONG _iItem = MAXULONG;
249 | ULONG _iSubItem = CID_NAME;
250 | ULONG _ItemCount;
251 | LONG _sortbits = ~0;
252 | ULONG _dwStartType = MAXULONG;
253 | BOOL _bTimerActive;
254 |
255 | //////////////////////////////////////////////////////////////////////////
256 | //ULONG _iTop = MINLONG, _iCount = 0;
257 | //////////////////////////////////////////////////////////////////////////
258 |
259 | enum { nTimerID = 1 };
260 |
261 | virtual PCUNICODE_STRING getPosName()
262 | {
263 | STATIC_UNICODE_STRING_(MainWnd);
264 | return &MainWnd;
265 | }
266 |
267 | BOOL CreateImageList();
268 |
269 | virtual BOOL CreateClient(HWND hwnd, int x, int y, int nWidth, int nHeight);
270 | virtual BOOL CreateTB(HWND hwnd);
271 | virtual BOOL CreateSB(HWND hwnd);
272 |
273 | void OnDispInfo(LVITEMW* item);
274 | void OnItemChanged(HWND hwnd, NMLISTVIEW* pnm);
275 | void OnStartTypeChanged(ULONG dwStartType);
276 |
277 | void OnRClk(HWND hwnd, NMITEMACTIVATE* lpnmitem );
278 | void OnDblClk(HWND hwnd, NMITEMACTIVATE* lpnmitem );
279 | void SortColum(HWND hwndLV, ULONG iSubItem);
280 |
281 | void Refresh(HWND hwnd);
282 |
283 | void UpdateItem(ULONG i)
284 | {
285 | RECT rc {LVIR_BOUNDS};
286 | if (SendMessageW(_hwndLV, LVM_GETITEMRECT, i, (LPARAM)&rc))
287 | {
288 | InvalidateRect(_hwndLV, &rc, 0);
289 | }
290 | }
291 |
292 | BOOL OnApply(HWND hwnd);
293 | void OnStart(HWND hwnd);
294 | void OnStop(HWND hwnd);
295 | void OnPause(HWND hwnd);
296 |
297 | ENUM_SERVICE_STATUS_PROCESSW* GetServiceI(ULONG iItem)
298 | {
299 | return iItem < _ItemCount ? GetService(_lpServices, _pi2i[iItem]) : 0;
300 | }
301 |
302 | void OnSD(HWND hwnd);
303 |
304 | void OnTimer();
305 |
306 | void SetStatus(ULONG iItem);
307 | void GetInfoTip(NMLVGETINFOTIP* pit);
308 |
309 | virtual void OnScNotify();
310 |
311 | void UpdateStartStop(ENUM_SERVICE_STATUS_PROCESSW* lpService);
312 |
313 | HRESULT Init(SC_HANDLE hSCManager);
314 |
315 | LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
316 | public:
317 | ~ZMainWnd();
318 |
319 | HRESULT Init();
320 | };
321 |
322 | void ZMainWnd::OnScNotify()
323 | {
324 | //DbgPrint("OnScNotify(%x %08x {%x %x %x}])\n", dwNotificationStatus, dwNotificationTriggered,
325 | // ServiceStatus.dwCurrentState, ServiceStatus.dwControlsAccepted, ServiceStatus.dwWin32ExitCode);
326 |
327 | if (0 <= dwNotificationStatus)
328 | {
329 | ULONG iItem = _iItem;
330 |
331 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(iItem))
332 | {
333 | if (ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR)
334 | {
335 | ServiceStatus.dwWin32ExitCode = ServiceStatus.dwServiceSpecificExitCode;
336 | }
337 |
338 | ServiceStatus.dwServiceSpecificExitCode = lpService->ServiceStatusProcess.dwServiceSpecificExitCode;
339 |
340 | int i = memcmp(&ServiceStatus, &lpService->ServiceStatusProcess, sizeof(SERVICE_STATUS_PROCESS));
341 |
342 | lpService->ServiceStatusProcess = ServiceStatus;
343 |
344 | if (i)
345 | {
346 | UpdateStartStop(lpService);
347 | UpdateItem(iItem);
348 | SetStatus(iItem);
349 | }
350 |
351 | if (dwNotificationTriggered) NotifyStatusChange();
352 | }
353 | }
354 | }
355 |
356 | void ZMainWnd::SortColum(HWND hwndLV, ULONG iSubItem)
357 | {
358 | if (iSubItem < CID_MAX)
359 | {
360 | Sort s { _bittestandcomplement(&_sortbits, iSubItem) ? +1 : -1, iSubItem, _lpServices };
361 | qsort_s(_pi2i, _ItemCount, sizeof(ULONG), Sort::FuncCompare, &s);
362 |
363 | LVCOLUMN lc = { LVCF_FMT, LVCFMT_LEFT };
364 | if (_iSubItem != iSubItem)
365 | {
366 | ListView_SetColumn(hwndLV, _iSubItem, &lc);
367 | _iSubItem = iSubItem;
368 | }
369 |
370 | lc.fmt = align[iSubItem] | (0 < s.s ? HDF_SORTUP : HDF_SORTDOWN);
371 |
372 | ListView_SetColumn(hwndLV, iSubItem, &lc);
373 | InvalidateRect(hwndLV, 0, FALSE);
374 | }
375 | }
376 |
377 | ZMainWnd::~ZMainWnd()
378 | {
379 | destroy(_lpServices), _lpServices = 0;
380 |
381 | union {
382 | SC_HANDLE hSCManager;
383 | HANDLE h;
384 | };
385 |
386 | if (hSCManager = _hSCManager)
387 | {
388 | CloseServiceHandle(hSCManager);
389 | }
390 |
391 | if (h = _hKey)
392 | {
393 | NtClose(h);
394 | }
395 |
396 | if (h = _hSysToken)
397 | {
398 | NtClose(h);
399 | }
400 | }
401 |
402 | #define _TEST_
403 | #ifdef _TEST_
404 |
405 | EXTERN_C PVOID __imp_RtlGetPersistedStateLocation = 0;
406 |
407 | void QuerySD(LPWSTR lpServiceName, PSECURITY_DESCRIPTOR lpSecurityDescriptor)
408 | {
409 | BOOLEAN bpresent, bDefaulted;
410 | PACL Dacl;
411 |
412 | if (0 <= RtlGetDaclSecurityDescriptor(lpSecurityDescriptor, &bpresent, &Dacl, &bDefaulted) && bpresent && Dacl)
413 | {
414 | BOOL b = FALSE;
415 | PACCESS_ALLOWED_ACE pBestAce = 0;
416 |
417 | if (USHORT AceCount = Dacl->AceCount)
418 | {
419 | union {
420 | PACCESS_ALLOWED_ACE pAce;
421 | PACE_HEADER pHead;
422 | PVOID pv;
423 | PBYTE pb;
424 | };
425 |
426 | pv = ++Dacl;
427 |
428 | do
429 | {
430 | if (pHead->AceType == ACCESS_ALLOWED_ACE_TYPE)
431 | {
432 | if ((pAce->Mask & (SERVICE_CHANGE_CONFIG|SERVICE_STOP|SERVICE_START)) ==
433 | (SERVICE_CHANGE_CONFIG|SERVICE_STOP|SERVICE_START))
434 | {
435 | b = TRUE;
436 | }
437 |
438 | if (!pBestAce || !(~pAce->Mask & pBestAce->Mask))
439 | {
440 | pBestAce = pAce;
441 | }
442 | }
443 |
444 | } while (pb += pHead->AceSize, --AceCount);
445 | }
446 |
447 | if (!b || !pBestAce)
448 | {
449 | DbgPrint("!!!!!");
450 | }
451 |
452 | if (pBestAce)
453 | {
454 | UNICODE_STRING us;
455 | if (0 <= RtlConvertSidToUnicodeString(&us, &pBestAce->SidStart, TRUE))
456 | {
457 | DbgPrint("%08x %wZ | %S\n", pBestAce->Mask, &us, lpServiceName);
458 | RtlFreeUnicodeString(&us);
459 | }
460 | }
461 | }
462 | else
463 | {
464 | __nop();
465 | }
466 | }
467 | #endif//_TEST_
468 |
469 | #undef _NTDDK_
470 | #include
471 |
472 | void InitS(HANDLE hKey, PUNICODE_STRING Id, ULONG n, ENUM_SERVICE_STATUS_PROCESSW Services[])
473 | {
474 | UNICODE_STRING ObjectName;
475 | OBJECT_ATTRIBUTES oa = { sizeof(oa), hKey, &ObjectName, OBJ_CASE_INSENSITIVE };
476 | STATIC_UNICODE_STRING_(StartOverride);
477 | OBJECT_ATTRIBUTES oa2 = { sizeof(oa2), 0, const_cast(&StartOverride), OBJ_CASE_INSENSITIVE };
478 |
479 | #ifdef _TEST_
480 | STATIC_UNICODE_STRING_(Security);
481 | OBJECT_ATTRIBUTES oa3 = { sizeof(oa3), 0, const_cast(&Security), OBJ_CASE_INSENSITIVE };
482 | #endif
483 |
484 | do
485 | {
486 | if (Services->ServiceStatusProcess.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR)
487 | {
488 | Services->ServiceStatusProcess.dwWin32ExitCode = Services->ServiceStatusProcess.dwServiceSpecificExitCode;
489 | }
490 |
491 | Services->ServiceStatusProcess.dwServiceSpecificExitCode = MAXULONG;
492 |
493 | RtlInitUnicodeString(&ObjectName, Services->lpServiceName);
494 |
495 | if (0 <= ZwOpenKey(&oa2.RootDirectory, KEY_QUERY_VALUE, &oa))
496 | {
497 | union {
498 | KEY_VALUE_PARTIAL_INFORMATION kvpi;
499 | UCHAR buf [0x200];
500 | };
501 | STATIC_UNICODE_STRING_(Start);
502 |
503 | if (0 <= ZwQueryValueKey(oa2.RootDirectory, &Start, KeyValuePartialInformation, &kvpi, sizeof(kvpi), &kvpi.TitleIndex) &&
504 | kvpi.Type == REG_DWORD)
505 | {
506 | Services->ServiceStatusProcess.dwServiceSpecificExitCode = (ULONG&)kvpi.Data;
507 |
508 | if (Id && (ULONG&)kvpi.Data == BootLoad)
509 | {
510 | if (0 <= ZwOpenKey(&hKey, KEY_QUERY_VALUE, &oa2))
511 | {
512 | if (0 <= ZwQueryValueKey(hKey, Id, KeyValuePartialInformation, &kvpi, sizeof(kvpi), &kvpi.TitleIndex) &&
513 | kvpi.Type == REG_DWORD)
514 | {
515 | Services->ServiceStatusProcess.dwServiceSpecificExitCode = (ULONG&)kvpi.Data;
516 | }
517 | NtClose(hKey);
518 | }
519 | }
520 |
521 | #ifdef _TEST_
522 | oa3.RootDirectory = oa2.RootDirectory;
523 | if (0 <= ZwOpenKey(&hKey, KEY_QUERY_VALUE, &oa3))
524 | {
525 | if (0 <= ZwQueryValueKey(hKey, &Security, KeyValuePartialInformation, &kvpi, sizeof(buf), &kvpi.TitleIndex) &&
526 | kvpi.Type == REG_BINARY)
527 | {
528 | if (RtlValidSecurityDescriptor(kvpi.Data))
529 | {
530 | PWSTR psz;
531 | if (ConvertSecurityDescriptorToStringSecurityDescriptorW(kvpi.Data,
532 | SDDL_REVISION, DACL_SECURITY_INFORMATION, &psz, 0))
533 | {
534 | DbgPrint("%S: %S\n", Services->lpServiceName, psz);
535 | LocalFree(psz);
536 | }
537 | //QuerySD(Services->lpServiceName, kvpi.Data);
538 | }
539 | }
540 | NtClose(hKey);
541 | }
542 | #endif
543 | }
544 |
545 | NtClose(oa2.RootDirectory);
546 | }
547 |
548 | } while (Services++, --n);
549 | }
550 |
551 | NTSTATUS HwCfgGetCurrentConfiguration(PULONG pId)
552 | {
553 | NTSTATUS status = STATUS_SUCCESS;
554 | STATIC_OBJECT_ATTRIBUTES(oa, "\\Registry\\MACHINE\\SYSTEM\\HardwareConfig\\Current");
555 |
556 | HANDLE hKey;
557 | if (0 <= ZwOpenKey(&hKey, KEY_QUERY_VALUE, &oa))
558 | {
559 | KEY_VALUE_PARTIAL_INFORMATION kvpi;
560 | STATIC_UNICODE_STRING_(Id);
561 | if (0 <= ZwQueryValueKey(hKey, &Id, KeyValuePartialInformation, &kvpi, sizeof(kvpi), &kvpi.TitleIndex) &&
562 | kvpi.Type == REG_DWORD)
563 | {
564 | *pId = (ULONG&)kvpi.Data;
565 | }
566 | NtClose(hKey);
567 | }
568 |
569 | return status;
570 | }
571 |
572 | HRESULT ZMainWnd::Init(SC_HANDLE hSCManager)
573 | {
574 | union {
575 | ULONG Id;
576 | WCHAR sz[16];
577 | };
578 | UNICODE_STRING uID, *puID = 0;
579 | if (0 <= HwCfgGetCurrentConfiguration(&Id))
580 | {
581 | if (0 < swprintf_s(sz, _countof(sz), L"%d", Id))
582 | {
583 | RtlInitUnicodeString(puID = &uID, sz);
584 | }
585 | }
586 |
587 | ULONG dwError;
588 |
589 | ULONG cbBytesNeeded = 0x40000 - FIELD_OFFSET(ENUM_SERVICES, Services), ResumeHandle = 0, ItemCount = 0, n;
590 |
591 | ENUM_SERVICES* lpServices = 0;
592 | do
593 | {
594 | dwError = ERROR_OUTOFMEMORY;
595 |
596 | DWORD dwServiceType = g_nt_ver.Version < _WIN32_WINNT_WIN10 ?
597 | SERVICE_WIN32|SERVICE_ADAPTER |SERVICE_DRIVER|SERVICE_INTERACTIVE_PROCESS: SERVICE_TYPE_ALL;
598 |
599 | if (ENUM_SERVICES* next = new(cbBytesNeeded) ENUM_SERVICES)
600 | {
601 | switch (dwError = BOOL_TO_ERROR(EnumServicesStatusEx(hSCManager,
602 | SC_ENUM_PROCESS_INFO, dwServiceType, SERVICE_STATE_ALL,
603 | (PBYTE)next->Services, cbBytesNeeded, &cbBytesNeeded, &n, &ResumeHandle, 0)))
604 | {
605 | case NOERROR:
606 | case ERROR_MORE_DATA:
607 | InitS(_hKey, puID, n, next->Services);
608 | next->next = lpServices, lpServices = next, ItemCount += n, next->n = n;
609 | break;
610 | default:
611 | delete [] next;
612 | }
613 | }
614 |
615 | } while (dwError == ERROR_MORE_DATA);
616 |
617 | if (dwError == NOERROR)
618 | {
619 | if (PULONG pi2i = new ULONG[ItemCount])
620 | {
621 | _pi2i = pi2i;
622 | _lpServices = lpServices, _ItemCount = ItemCount;
623 | do
624 | {
625 | *pi2i++ = --ItemCount;
626 | } while (ItemCount);
627 |
628 | return S_OK;
629 | }
630 | }
631 |
632 | destroy(lpServices);
633 |
634 | return HRESULT_FROM_WIN32(dwError);
635 | }
636 |
637 | HRESULT ZMainWnd::Init()
638 | {
639 | HRESULT hr = AdjustPrivileges();
640 |
641 | STATIC_OBJECT_ATTRIBUTES(oa, "\\Registry\\MACHINE\\SYSTEM\\CurrentControlSet\\Services");
642 | if (hr || 0 > (hr = GetToken(&tp_ctp, &_hSysToken)) || 0 > (hr = ZwOpenKey(&_hKey, KEY_READ, &oa)))
643 | {
644 | return HRESULT_FROM_NT(hr);
645 | }
646 |
647 | if (SC_HANDLE hSCManager = OpenSCManagerW(0, 0, SC_MANAGER_ENUMERATE_SERVICE ))
648 | {
649 | if (0 <= (hr = Init(hSCManager)))
650 | {
651 | _hSCManager = hSCManager;
652 | return S_OK;
653 | }
654 |
655 | CloseServiceHandle(hSCManager);
656 | }
657 |
658 | return GetLastHr();
659 | }
660 |
661 | void ZMainWnd::UpdateStartStop(ENUM_SERVICE_STATUS_PROCESSW* lpService)
662 | {
663 | LONG m = 0;
664 | DWORD dwControlsAccepted = lpService->ServiceStatusProcess.dwControlsAccepted;
665 |
666 | if (dwControlsAccepted & SERVICE_ACCEPT_STOP)
667 | {
668 | _bittestandset(&m, 2);
669 | }
670 |
671 | switch (lpService->ServiceStatusProcess.dwCurrentState)
672 | {
673 | case SERVICE_STOPPED:
674 | switch (lpService->ServiceStatusProcess.dwServiceSpecificExitCode)
675 | {
676 | case SystemLoad:
677 | case AutoLoad:
678 | case DemandLoad:
679 | m = 1;
680 | break;
681 | }
682 | break;
683 |
684 | case SERVICE_PAUSED:
685 | if (dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE)
686 | {
687 | _bittestandset(&m, 0);
688 | }
689 | break;
690 |
691 | case SERVICE_RUNNING:
692 | if (dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE)
693 | {
694 | _bittestandset(&m, 1);
695 | }
696 | break;
697 | }
698 |
699 | EnableCmd(ID_START, _bittest(&m, 0));
700 | EnableCmd(ID_PAUSE, _bittest(&m, 1));
701 | EnableCmd(ID_STOP, _bittest(&m, 2));
702 | }
703 |
704 | void ZMainWnd::OnItemChanged(HWND hwnd, NMLISTVIEW* pnm)
705 | {
706 | if (LVIF_STATE & pnm->uChanged)
707 | {
708 | UINT uNewState = pnm->uNewState & LVIS_SELECTED;
709 | UINT uOldState = pnm->uOldState & LVIS_SELECTED;
710 |
711 | if (uNewState != uOldState)
712 | {
713 | ServiceData::Close();
714 |
715 | BOOL bNeedTimer = FALSE;
716 |
717 | ULONG iItem = pnm->iItem;
718 | _iItem = iItem;
719 | _dwStartType = MAXULONG;
720 |
721 | ULONG dwStartType = MAXULONG;
722 | BOOL bNewItemSelected = FALSE;
723 | if (uNewState)
724 | {
725 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(iItem))
726 | {
727 | bNewItemSelected = TRUE;
728 |
729 | ServiceData::Set(_hSCManager, lpService->lpServiceName);
730 |
731 | UpdateStartStop(lpService);
732 |
733 | dwStartType = lpService->ServiceStatusProcess.dwServiceSpecificExitCode;
734 |
735 | bNeedTimer = lpService->ServiceStatusProcess.dwServiceType & SERVICE_DRIVER;
736 | }
737 | }
738 |
739 | EnableCmd(ID_SD, bNewItemSelected);
740 |
741 | EnableWindow(_hwndCB, dwStartType != MAXULONG && 0 <= ComboBox_SetCurSel(_hwndCB, dwStartType));
742 | EnableWindow(_hwndApply, FALSE);
743 |
744 | if (ZStatusBar::getHWND())
745 | {
746 | SetStatus(iItem);
747 | }
748 |
749 | if (_bTimerActive != bNeedTimer)
750 | {
751 | if (bNeedTimer)
752 | {
753 | _bTimerActive = SetTimer(hwnd, nTimerID, 1000, 0) != 0;
754 | }
755 | else
756 | {
757 | KillTimer(hwnd, nTimerID);
758 | _bTimerActive = FALSE;
759 | }
760 | }
761 | }
762 | }
763 | }
764 |
765 | BOOL IsValidNewStartType(ULONG dwStartType, ENUM_SERVICE_STATUS_PROCESSW* lpService)
766 | {
767 | return dwStartType <= SERVICE_DISABLED &&
768 | (dwStartType != lpService->ServiceStatusProcess.dwServiceSpecificExitCode) &&
769 | (dwStartType > SERVICE_SYSTEM_START || lpService->ServiceStatusProcess.dwServiceType < SERVICE_WIN32_OWN_PROCESS);
770 | }
771 |
772 | void ZMainWnd::OnStartTypeChanged(ULONG dwStartType)
773 | {
774 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(_iItem))
775 | {
776 | _dwStartType = dwStartType;
777 | EnableWindow(_hwndApply, IsValidNewStartType(dwStartType, lpService));
778 | }
779 | }
780 |
781 | BOOL ZMainWnd::OnApply(HWND hwnd)
782 | {
783 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(_iItem))
784 | {
785 | ULONG dwStartType = _dwStartType;
786 | if (IsValidNewStartType(dwStartType, lpService))
787 | {
788 | if (HRESULT hr = ChangeServiceStartType(dwStartType, _hSCManager, lpService->lpServiceName, _hSysToken))
789 | {
790 | ShowErrorBox(hwnd, hr, 0, MB_ICONHAND);
791 | }
792 | else
793 | {
794 | lpService->ServiceStatusProcess.dwServiceSpecificExitCode = dwStartType;
795 | UpdateItem(_iItem);
796 | UpdateStartStop(lpService);
797 | return TRUE;
798 | }
799 | }
800 | }
801 |
802 | return FALSE;
803 | }
804 |
805 | void ZMainWnd::OnStart(HWND hwnd)
806 | {
807 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(_iItem))
808 | {
809 | HRESULT hr;
810 | switch (lpService->ServiceStatusProcess.dwCurrentState)
811 | {
812 | case SERVICE_STOPPED:
813 | hr = TryStartService(_hSCManager, lpService->lpServiceName, _hSysToken);
814 | break;
815 | case SERVICE_PAUSED:
816 | hr = TryControlService(_hSCManager, lpService->lpServiceName,
817 | SERVICE_CONTROL_CONTINUE, SERVICE_PAUSE_CONTINUE, _hSysToken);
818 | break;
819 | default: return;
820 | }
821 |
822 | if (hr)
823 | {
824 | ShowErrorBox(hwnd, hr, 0, MB_ICONHAND);
825 | }
826 | }
827 | }
828 |
829 | void ZMainWnd::OnStop(HWND hwnd)
830 | {
831 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(_iItem))
832 | {
833 | if (HRESULT hr = TryControlService(_hSCManager, lpService->lpServiceName,
834 | SERVICE_CONTROL_STOP, SERVICE_STOP, _hSysToken))
835 | {
836 | ShowErrorBox(hwnd, hr, 0, MB_ICONHAND);
837 | }
838 | }
839 | }
840 |
841 | void ZMainWnd::OnPause(HWND hwnd)
842 | {
843 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(_iItem))
844 | {
845 | if (HRESULT hr = TryControlService(_hSCManager, lpService->lpServiceName,
846 | SERVICE_CONTROL_PAUSE, SERVICE_PAUSE_CONTINUE, _hSysToken))
847 | {
848 | ShowErrorBox(hwnd, hr, 0, MB_ICONHAND);
849 | }
850 | }
851 | }
852 |
853 | void ZMainWnd::OnSD(HWND hwnd)
854 | {
855 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(_iItem))
856 | {
857 | 0 > GetKeyState(VK_LSHIFT) ?
858 | EditServiceSecurity(hwnd, _hSCManager, lpService->lpServiceName, _hSysToken) :
859 | ShowSD(_hSCManager, lpService->lpServiceName, _hSysToken, hwnd, _hFont, 0 > GetKeyState(VK_RSHIFT));
860 | }
861 | }
862 |
863 | void ZMainWnd::OnTimer()
864 | {
865 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(_iItem))
866 | {
867 | if (lpService->ServiceStatusProcess.dwServiceType & SERVICE_DRIVER)
868 | {
869 | if (hService && QueryServiceStatus(hService, (SERVICE_STATUS*)&ServiceStatus ))
870 | {
871 | dwNotificationStatus = 0;
872 | dwNotificationTriggered = 0;
873 | OnScNotify();
874 | }
875 | }
876 | }
877 | }
878 |
879 | void SetStringToClipboard(HWND hwnd, PCWSTR lpsz)
880 | {
881 | if (OpenClipboard(hwnd))
882 | {
883 | EmptyClipboard();
884 | size_t cb = (wcslen(lpsz) + 1) * sizeof(WCHAR);
885 | if (HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE, cb))
886 | {
887 | memcpy(GlobalLock(hg), lpsz, cb);
888 | GlobalUnlock(hg);
889 | if (!SetClipboardData(CF_UNICODETEXT, hg)) GlobalFree(hg);
890 | }
891 | CloseClipboard();
892 | }
893 | }
894 |
895 | void ZMainWnd::OnRClk(HWND hwnd, NMITEMACTIVATE* lpnmitem )
896 | {
897 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(lpnmitem->iItem))
898 | {
899 | if (HMENU hmenu = LoadMenuW((HINSTANCE)&__ImageBase, MAKEINTRESOURCEW(IDR_MENU1)))
900 | {
901 | ClientToScreen(_hwndLV, &lpnmitem->ptAction);
902 |
903 | ULONG cmd = TrackPopupMenu(GetSubMenu(hmenu, 0), TPM_NONOTIFY|TPM_RETURNCMD,
904 | lpnmitem->ptAction.x, lpnmitem->ptAction.y, 0, hwnd, 0);
905 |
906 | DestroyMenu(hmenu);
907 |
908 | switch (cmd)
909 | {
910 | case ID_0_EDITSECURITY:
911 | EditServiceSecurity(hwnd, _hSCManager, lpService->lpServiceName, _hSysToken);
912 | break;
913 | case ID_0_VIEWSECURITY:
914 | ShowSD(_hSCManager, lpService->lpServiceName, _hSysToken, hwnd, _hFont, FALSE);
915 | break;
916 | case ID_0_VIEWSECURITY40004:
917 | ShowSD(_hSCManager, lpService->lpServiceName, _hSysToken, hwnd, _hFont, TRUE);
918 | break;
919 | case ID_0_COPYNAME:
920 | SetStringToClipboard(hwnd, lpService->lpDisplayName);
921 | break;
922 | }
923 | }
924 | }
925 | }
926 |
927 | LRESULT ZMainWnd::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
928 | {
929 | switch (uMsg)
930 | {
931 | case WM_DESTROY:
932 | if (_himl) ImageList_Destroy(_himl);
933 | if (_hFont) DeleteObject(_hFont);
934 | if (_bTimerActive) KillTimer(hwnd, nTimerID);
935 | break;
936 |
937 | case WM_COMMAND:
938 | switch (wParam)
939 | {
940 | case MAKEWPARAM(ID_COMBO, CBN_SELCHANGE):
941 | OnStartTypeChanged(ComboBox_GetCurSel((HWND)lParam));
942 | return 0;
943 |
944 | case ID_SD:
945 | OnSD(hwnd);
946 | return 0;
947 |
948 | case ID_RELOAD:
949 | destroy(_lpServices), _lpServices = 0;
950 | Init(_hSCManager);
951 | ListView_SetItemCountEx(_hwndLV, _ItemCount, 0);
952 | _sortbits = ~0;
953 | SortColum(_hwndLV, CID_NAME);
954 | return 0;
955 |
956 | case ID_APPLY:
957 | if (OnApply(hwnd))
958 | {
959 | EnableWindow((HWND)lParam, FALSE);
960 | }
961 | return 0;
962 |
963 | case ID_START:
964 | OnStart(hwnd);
965 | return 0;
966 |
967 | case ID_STOP:
968 | OnStop(hwnd);
969 | return 0;
970 |
971 | case ID_PAUSE:
972 | OnPause(hwnd);
973 | return 0;
974 | }
975 | break;
976 |
977 | case WM_TIMER:
978 | OnTimer();
979 | break;
980 |
981 | case WM_NOTIFY:
982 | switch (((NMHDR*)lParam)->idFrom)
983 | {
984 | case ID_LV:
985 | switch (((NMHDR*)lParam)->code)
986 | {
987 | case LVN_GETDISPINFO:
988 | OnDispInfo(&reinterpret_cast(lParam)->item);
989 | break;
990 |
991 | case LVN_GETINFOTIP:
992 | GetInfoTip(reinterpret_cast(lParam));
993 | break;
994 |
995 | case LVN_COLUMNCLICK:
996 | SortColum(reinterpret_cast(lParam)->hdr.hwndFrom, reinterpret_cast(lParam)->iSubItem);
997 | break;
998 |
999 | case NM_RCLICK:
1000 | OnRClk(hwnd, reinterpret_cast(lParam));
1001 | break;
1002 | case NM_DBLCLK:
1003 | //OnDblClk(hwnd, reinterpret_cast(lParam));
1004 | break;
1005 |
1006 | case LVN_ITEMCHANGED:
1007 | OnItemChanged(hwnd, reinterpret_cast(lParam));
1008 | break;
1009 |
1010 | //case LVN_ODCACHEHINT:
1011 | // reinterpret_cast(lParam)->iTo -= reinterpret_cast(lParam)->iFrom - 1;
1012 | // if (_iCount < (ULONG)reinterpret_cast(lParam)->iTo)
1013 | // {
1014 | // _iCount = reinterpret_cast(lParam)->iTo;
1015 | // }
1016 |
1017 | // if ((ULONG)(reinterpret_cast(lParam)->iFrom - _iTop) >= _iCount)
1018 | // {
1019 | // _iTop = reinterpret_cast(lParam)->iFrom;
1020 |
1021 | // DbgPrint("====%u, %u\n",
1022 | // reinterpret_cast(lParam)->iFrom,reinterpret_cast(lParam)->iTo);
1023 | // }
1024 | // break;
1025 |
1026 | //case NM_CUSTOMDRAW:
1027 | // DbgPrint("************\n");
1028 | // break;
1029 |
1030 | //default:
1031 | // ULONG i = LVN_FIRST - ((NMHDR*)lParam)->code;
1032 | // if (i < (LVN_FIRST - LVN_LAST))
1033 | // {
1034 | // switch (i)
1035 | // {
1036 | // case LVN_FIRST - LVN_HOTTRACK:
1037 | // __nop();
1038 | // break;
1039 | // default:
1040 | // DbgPrint(":: %u\n", i);
1041 | // }
1042 | // }
1043 | // break;
1044 | }
1045 | break;
1046 | }
1047 | break;
1048 | }
1049 | return ZSDIFrameWnd::WindowProc(hwnd, uMsg, wParam, lParam);
1050 | }
1051 |
1052 | BOOL IsSz(PKEY_VALUE_PARTIAL_INFORMATION pkvpi)
1053 | {
1054 | switch (pkvpi->Type)
1055 | {
1056 | case REG_SZ:
1057 | case REG_EXPAND_SZ:
1058 | ULONG Length = pkvpi->DataLength;
1059 | return Length && !(Length & (sizeof(WCHAR) - 1)) && !*(PWSTR)(pkvpi->Data + Length - sizeof(WCHAR));
1060 | }
1061 |
1062 | return FALSE;
1063 | }
1064 |
1065 | void ZMainWnd::GetInfoTip(NMLVGETINFOTIP* pit)
1066 | {
1067 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(pit->iItem))
1068 | {
1069 | UNICODE_STRING ObjectName;
1070 | STATIC_UNICODE_STRING_(ImagePath);
1071 | STATIC_UNICODE_STRING_(Parameters);
1072 | STATIC_UNICODE_STRING_(ServiceDll);
1073 | OBJECT_ATTRIBUTES oa = { sizeof(oa), _hKey, &ObjectName, OBJ_CASE_INSENSITIVE };
1074 | OBJECT_ATTRIBUTES oa2 = { sizeof(oa2), 0, const_cast(&Parameters), OBJ_CASE_INSENSITIVE };
1075 | RtlInitUnicodeString(&ObjectName, lpService->lpServiceName);
1076 |
1077 | BOOL b = FALSE;
1078 | PKEY_VALUE_PARTIAL_INFORMATION kvpi = (PKEY_VALUE_PARTIAL_INFORMATION)pit->pszText;
1079 |
1080 | if (0 <= ZwOpenKey(&oa2.RootDirectory, KEY_QUERY_VALUE, &oa))
1081 | {
1082 | ULONG cb = pit->cchTextMax * sizeof(WCHAR);
1083 |
1084 | HANDLE hKey;
1085 | if (0 <= ZwOpenKey(&hKey, KEY_QUERY_VALUE, &oa2))
1086 | {
1087 | if (0 <= ZwQueryValueKey(hKey, &ServiceDll, KeyValuePartialInformation, kvpi, cb, &kvpi->TitleIndex))
1088 | {
1089 | b = IsSz(kvpi);
1090 | }
1091 | NtClose(hKey);
1092 | }
1093 |
1094 | if (!b && 0 <= ZwQueryValueKey(oa2.RootDirectory, &ImagePath, KeyValuePartialInformation, kvpi, cb, &kvpi->TitleIndex))
1095 | {
1096 | b = IsSz(kvpi);
1097 | }
1098 | NtClose(oa2.RootDirectory);
1099 | }
1100 |
1101 | if (b)
1102 | {
1103 | wcscpy(pit->pszText, (PCWSTR)kvpi->Data);
1104 | return;
1105 | }
1106 |
1107 | if (lpService->ServiceStatusProcess.dwServiceType & SERVICE_DRIVER)
1108 | {
1109 | swprintf_s(pit->pszText, pit->cchTextMax, L"%s.sys", lpService->lpServiceName);
1110 | return;
1111 | }
1112 | }
1113 | swprintf_s(pit->pszText, pit->cchTextMax, L"??");
1114 | }
1115 |
1116 | void ZMainWnd::SetStatus(ULONG iItem)
1117 | {
1118 | WCHAR txt[256], *psz = txt;
1119 | *txt = 0;
1120 |
1121 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(iItem))
1122 | {
1123 | int len = 0;
1124 | ULONG cch = _countof(txt);
1125 |
1126 | DWORD dwServiceType = lpService->ServiceStatusProcess.dwServiceType;
1127 |
1128 | static const PCWSTR ssz[] = {
1129 | L"KERNEL_DRIVER",
1130 | L"FILE_SYSTEM_DRIVER",
1131 | L"ADAPTER",
1132 | L"RECOGNIZER_DRIVER",
1133 | L"OWN_PROCESS",
1134 | L"SHARE_PROCESS",
1135 | L"USER_SERVICE",
1136 | L"USERSERVICE_INSTANCE",
1137 | L"INTERACTIVE_PROCESS",
1138 | L"PKG_SERVICE",
1139 | };
1140 |
1141 | static const ULONG stt[] {
1142 | SERVICE_KERNEL_DRIVER,
1143 | SERVICE_FILE_SYSTEM_DRIVER,
1144 | SERVICE_ADAPTER,
1145 | SERVICE_RECOGNIZER_DRIVER,
1146 | SERVICE_WIN32_OWN_PROCESS,
1147 | SERVICE_WIN32_SHARE_PROCESS,
1148 | SERVICE_USER_SERVICE,
1149 | SERVICE_USERSERVICE_INSTANCE,
1150 | SERVICE_INTERACTIVE_PROCESS,
1151 | SERVICE_PKG_SERVICE,
1152 | };
1153 |
1154 | ULONG n = _countof(stt);
1155 |
1156 | do
1157 | {
1158 | if (dwServiceType & stt[--n])
1159 | {
1160 | if (0 > (len = swprintf_s(psz, cch, L"%s | ", ssz[n])))
1161 | {
1162 | break;
1163 | }
1164 | psz += len, cch -= len;
1165 | }
1166 |
1167 | } while (n);
1168 |
1169 | if (0 <= len && lpService->ServiceStatusProcess.dwCurrentState == SERVICE_STOPPED)
1170 | {
1171 | HRESULT dwExitCode = lpService->ServiceStatusProcess.dwWin32ExitCode;
1172 | ULONG dwFlags;
1173 | HMODULE hmod;
1174 |
1175 | if ((dwExitCode & FACILITY_NT_BIT) || (0 > dwExitCode && HRESULT_FACILITY(dwExitCode) == FACILITY_NULL))
1176 | {
1177 | dwExitCode &= ~FACILITY_NT_BIT;
1178 | __nt:
1179 | hmod = GetNtMod();
1180 | dwFlags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE;
1181 | }
1182 | else
1183 | {
1184 | hmod = 0;
1185 | dwFlags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM;
1186 | }
1187 |
1188 | if (FormatMessageW(dwFlags, hmod, dwExitCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), psz, cch, 0))
1189 | {
1190 | }
1191 | else if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
1192 | {
1193 | goto __nt;
1194 | }
1195 | else
1196 | {
1197 | swprintf_s(psz, cch, L"[%x]", lpService->ServiceStatusProcess.dwWin32ExitCode);
1198 | }
1199 | }
1200 | }
1201 |
1202 | SetStatusText(SB_SIMPLEID, txt);
1203 | }
1204 |
1205 | PCWSTR GetStartTypeName(ULONG dwStartType)
1206 | {
1207 | switch (dwStartType)
1208 | {
1209 | case BootLoad: return L"Boot";
1210 | case SystemLoad: return L"System";
1211 | case AutoLoad: return L"Automatic";
1212 | case DemandLoad: return L"Manual";
1213 | case DisableLoad: return L"Disabled";
1214 | default: return L"?";
1215 | }
1216 | }
1217 |
1218 | PCWSTR GetStateName(ULONG dwCurrentState)
1219 | {
1220 | switch (dwCurrentState)
1221 | {
1222 | case SERVICE_STOPPED: return L"Stoped";
1223 | case SERVICE_START_PENDING: return L"Starting ...";
1224 | case SERVICE_STOP_PENDING: return L"Stoping ...";
1225 | case SERVICE_RUNNING: return L"Running";
1226 | case SERVICE_CONTINUE_PENDING: return L"Continuing ...";
1227 | case SERVICE_PAUSE_PENDING: return L"Pausing ...";
1228 | case SERVICE_PAUSED: return L"Paused";
1229 | default: return L"?";
1230 | }
1231 | }
1232 |
1233 | void ZMainWnd::OnDispInfo(LVITEMW* item)
1234 | {
1235 | if (ENUM_SERVICE_STATUS_PROCESSW* lpService = GetServiceI(item->iItem))
1236 | {
1237 | if (item->mask & LVIF_TEXT)
1238 | {
1239 | PWSTR pszText = item->pszText;
1240 | ULONG cchTextMax = item->cchTextMax;
1241 |
1242 | if (cchTextMax)
1243 | {
1244 | *pszText = 0;
1245 | }
1246 |
1247 | switch (item->iSubItem)
1248 | {
1249 | case CID_NAME:
1250 | swprintf_s(pszText, cchTextMax, L"%s", lpService->lpServiceName);
1251 | break;
1252 | case CID_START:
1253 | swprintf_s(pszText, cchTextMax, L"%s", GetStartTypeName(lpService->ServiceStatusProcess.dwServiceSpecificExitCode));
1254 | break;
1255 | case CID_TYPE:
1256 | swprintf_s(pszText, cchTextMax, L"%s", lpService->ServiceStatusProcess.dwServiceType & SERVICE_DRIVER ? L"K" : L"U");
1257 | break;
1258 | case CID_STATE:
1259 | swprintf_s(pszText, cchTextMax, L"%s", GetStateName(lpService->ServiceStatusProcess.dwCurrentState));
1260 | break;
1261 | case CID_ID:
1262 | swprintf_s(pszText, cchTextMax, L"%x", lpService->ServiceStatusProcess.dwProcessId);
1263 | break;
1264 | case CID_DNAME:
1265 | swprintf_s(pszText, cchTextMax, L"%s", lpService->lpDisplayName);
1266 | break;
1267 | }
1268 | }
1269 |
1270 | if (item->mask & LVIF_IMAGE)
1271 | {
1272 | //ID_A(7), ID_B(6), ID_E(5), ID_G(4), ID_M(3), ID_P(2), ID_R(1), ID_Y(0),
1273 | ULONG i = lpService->ServiceStatusProcess.dwServiceSpecificExitCode;
1274 |
1275 | item->iImage = i > SERVICE_DISABLED ? I_IMAGENONE : i;
1276 | }
1277 | }
1278 | }
1279 |
1280 | BOOL ZMainWnd::CreateImageList()
1281 | {
1282 | LIC c {0, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON) };
1283 |
1284 | static const UINT cc[] = {
1285 | ID_K, ID_G, ID_R, ID_Y, ID_B,
1286 | };
1287 |
1288 | if (HIMAGELIST himl = ImageList_Create(c._cx, c._cy, ILC_COLOR32, _countof(cc), 0))
1289 | {
1290 |
1291 | ULONG n = _countof(cc);
1292 | int i;
1293 | do
1294 | {
1295 | i = -1;
1296 | if (0 <= c.CreateBMPFromPNG(MAKEINTRESOURCE(cc[--n])))
1297 | {
1298 | i = ImageList_Add(himl, c._hbmp, 0);
1299 | DeleteObject(c._hbmp), c._hbmp = 0;
1300 | }
1301 |
1302 | } while (0 <= i && n);
1303 |
1304 | if (0 <= i)
1305 | {
1306 | _himl = himl;
1307 | return TRUE;
1308 | }
1309 |
1310 | ImageList_Destroy(himl);
1311 | }
1312 |
1313 | return FALSE;
1314 | }
1315 |
1316 | BOOL ZMainWnd::CreateSB(HWND hwnd)
1317 | {
1318 | if (hwnd = ZStatusBar::Create(hwnd))
1319 | {
1320 | _hStatusFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);
1321 | SendMessage(hwnd, SB_SIMPLE, TRUE, 0);
1322 | return TRUE;
1323 | }
1324 | return FALSE;
1325 | }
1326 |
1327 | BOOL ZMainWnd::CreateTB(HWND hwnd)
1328 | {
1329 | int cc = 32 < GetSystemMetrics(SM_CYICON) ? 48 : 32;
1330 |
1331 | static const TBBUTTON g_btns[] = {
1332 | {IMAGE_ENHMETAFILE, ID_RELOAD, TBSTATE_ENABLED, BTNS_AUTOSIZE, {}, (DWORD_PTR)L" Refresh ", -1},
1333 | {IMAGE_ENHMETAFILE, ID_SD, 0, BTNS_AUTOSIZE, {}, (DWORD_PTR)L" Security Descriptor (hold left shift for edit) ", -1},
1334 | {IMAGE_ENHMETAFILE, ID_START, 0, BTNS_AUTOSIZE, {}, (DWORD_PTR)L" start ", -1},
1335 | {IMAGE_ENHMETAFILE, ID_PAUSE, 0, BTNS_AUTOSIZE, {}, (DWORD_PTR)L" pause ", -1},
1336 | {IMAGE_ENHMETAFILE, ID_STOP, 0, BTNS_AUTOSIZE, {}, (DWORD_PTR)L" stop ", -1},
1337 | };
1338 |
1339 | if (HWND hwndTB = ZToolBar::Create(hwnd, (HINSTANCE)&__ImageBase, 0, 0, cc, cc, g_btns, _countof(g_btns), TRUE))
1340 | {
1341 | RECT rc, rc2;
1342 | SendMessage(hwndTB, TB_GETITEMRECT, _countof(g_btns) - 1, (LPARAM)&rc);
1343 |
1344 | if (HWND hwndCB = CreateWindowExW(0, WC_COMBOBOX, 0,
1345 | WS_VSCROLL|CBS_DROPDOWNLIST|WS_CHILD|WS_VISIBLE|WS_DISABLED,
1346 | rc.right += (3*cc>>3), 0, 4*cc, 0, hwndTB, (HMENU)ID_COMBO, 0, 0))
1347 | {
1348 | SendMessage(hwndCB, WM_SETFONT, (WPARAM)_hStatusFont, 0);
1349 |
1350 | ULONG H, y;
1351 | GetWindowRect(hwndCB, &rc2);
1352 | SetWindowPos(hwndCB, 0, rc.right, y = ((rc.bottom - rc.top) - (H = rc2.bottom - rc2.top)) >> 1, 0, 0,
1353 | SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
1354 |
1355 | _hwndCB = hwndCB;
1356 |
1357 | static PCWSTR mods[] = {
1358 | L"Boot",
1359 | L"System",
1360 | L"Automatic",
1361 | L"Manual",
1362 | L"Disabled",
1363 | };
1364 |
1365 | ULONG n = _countof(mods);
1366 | PCWSTR* pcsz = mods;
1367 | do
1368 | {
1369 | ComboBox_AddString(hwndCB, *pcsz++);
1370 | } while (--n);
1371 |
1372 | rc.right += 4*cc + (3*cc>>3);
1373 |
1374 | if (hwndCB = CreateWindowExW(0, WC_BUTTONW, L"Apply",
1375 | WS_CHILD|WS_VISIBLE|WS_DISABLED, rc.right, y, 3*H, H, hwndTB, (HMENU)ID_APPLY, 0, 0))
1376 | {
1377 | SendMessage(hwndCB, WM_SETFONT, (WPARAM)_hStatusFont, 0);
1378 |
1379 | _hwndApply = hwndCB;
1380 |
1381 | return TRUE;
1382 | }
1383 | }
1384 | }
1385 |
1386 | return FALSE;
1387 | }
1388 |
1389 | BOOL ZMainWnd::CreateClient(HWND hwnd, int x, int y, int nWidth, int nHeight)
1390 | {
1391 | _hFont = 0;
1392 |
1393 | if (!(hwnd = CreateWindowExW(0, WC_LISTVIEWW, 0,
1394 | WS_VISIBLE|WS_CHILD|LVS_EDITLABELS|LVS_REPORT|LVS_OWNERDATA|
1395 | LVS_SHOWSELALWAYS|LVS_SHAREIMAGELISTS|LVS_SINGLESEL|WS_HSCROLL|WS_VSCROLL,
1396 | x, y, nWidth, nHeight, hwnd, (HMENU)ID_LV, 0, 0))) return FALSE;
1397 |
1398 | _hwndLV = hwnd;
1399 |
1400 | NONCLIENTMETRICS ncm = { sizeof(NONCLIENTMETRICS) };
1401 | if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
1402 | {
1403 | ncm.lfCaptionFont.lfHeight = -ncm.iMenuHeight;
1404 | ncm.lfCaptionFont.lfWeight = FW_NORMAL;
1405 | ncm.lfCaptionFont.lfQuality = CLEARTYPE_QUALITY;
1406 | ncm.lfCaptionFont.lfPitchAndFamily = FIXED_PITCH|FF_MODERN;
1407 | wcscpy(ncm.lfCaptionFont.lfFaceName, L"Courier New");
1408 |
1409 | if (_hFont = CreateFontIndirect(&ncm.lfCaptionFont))
1410 | {
1411 | SendMessage(hwnd, WM_SETFONT, (WPARAM)_hFont, 0);
1412 | }
1413 | }
1414 |
1415 | SetWindowTheme(hwnd, L"Explorer", 0);
1416 |
1417 | if (CreateImageList())
1418 | {
1419 | ListView_SetImageList(hwnd, _himl, LVSIL_SMALL);
1420 | }
1421 |
1422 | LV_COLUMN lvclmn = {
1423 | LVCF_TEXT | LVCF_WIDTH | LVCF_FMT | LVCF_SUBITEM, LVCFMT_LEFT
1424 | };
1425 |
1426 | static const PCWSTR headers[] = {
1427 | L" Name ", L" Start ", L" State ", L"Type", L" Id ", L" Display Name "
1428 | };
1429 |
1430 | static const ULONG lens[] = { 20, 6, 7, 4, 4, 32 };
1431 |
1432 | C_ASSERT(_countof(headers) == _countof(lens));
1433 |
1434 | do
1435 | {
1436 | lvclmn.pszText = const_cast(headers[lvclmn.iSubItem]);
1437 | lvclmn.cx = lens[lvclmn.iSubItem] * ncm.iMenuHeight;
1438 | lvclmn.fmt = align[lvclmn.iSubItem];
1439 |
1440 | ListView_InsertColumn(hwnd, lvclmn.iSubItem, &lvclmn);
1441 | } while (++lvclmn.iSubItem < _countof(headers));
1442 |
1443 | ListView_SetExtendedListViewStyle(hwnd,
1444 | LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP|LVS_EX_DOUBLEBUFFER|LVS_EX_INFOTIP);
1445 |
1446 | ListView_SetItemCountEx(hwnd, _ItemCount, 0);
1447 | SortColum(hwnd, CID_NAME);
1448 |
1449 | return TRUE;
1450 | }
1451 |
1452 | void zmain()
1453 | {
1454 | ZGLOBALS globals;
1455 | ZApp app;
1456 | ZRegistry reg;
1457 | ZMainWnd wnd{};
1458 |
1459 | HRESULT status = wnd.Init();
1460 |
1461 | if (0 > status)
1462 | {
1463 | ShowErrorBox(0, status, 0);
1464 | }
1465 | else if (0 <= reg.Create(L"Software\\{0B62FC2A-9F2D-4c33-AE2F-65E0CF80C63B}"))
1466 | {
1467 | if (wnd.Create(L"Services", (HINSTANCE)&__ImageBase, MAKEINTRESOURCEW(ID_MAIN), TRUE))
1468 | {
1469 | app.Run();
1470 | }
1471 | }
1472 | }
1473 |
1474 | void CALLBACK ep(void*)
1475 | {
1476 | initterm();
1477 |
1478 | if (0 <= CoInitializeEx(0, COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE))
1479 | {
1480 | zmain();
1481 | CoUninitialize();
1482 | }
1483 | destroyterm();
1484 | ExitProcess(0);
1485 | }
1486 |
1487 | _NT_END
--------------------------------------------------------------------------------
/srv.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/srv.ico
--------------------------------------------------------------------------------
/stdafx.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
--------------------------------------------------------------------------------
/stdafx.h:
--------------------------------------------------------------------------------
1 | #define SECURITY_WIN32
2 | #include "../inc/stdafx.h"
3 | #include
4 | #include
5 | #include
6 | #include
7 |
--------------------------------------------------------------------------------
/stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/stop.png
--------------------------------------------------------------------------------
/token.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | _NT_BEGIN
4 |
5 | #include "impersonate.h"
6 |
7 | extern volatile const UCHAR guz;
8 |
9 | struct SID6 : public SID {
10 | DWORD SubAuthority[5];
11 | };
12 |
13 | struct SID2 : public SID {
14 | DWORD SubAuthority[1];
15 | };
16 |
17 | const SID6 TrustedInstallerSid = {
18 | {
19 | SID_REVISION, SECURITY_SERVICE_ID_RID_COUNT, SECURITY_NT_AUTHORITY, { SECURITY_SERVICE_ID_BASE_RID }
20 | },
21 | {
22 | SECURITY_TRUSTED_INSTALLER_RID1,
23 | SECURITY_TRUSTED_INSTALLER_RID2,
24 | SECURITY_TRUSTED_INSTALLER_RID3,
25 | SECURITY_TRUSTED_INSTALLER_RID4,
26 | SECURITY_TRUSTED_INSTALLER_RID5,
27 | }
28 | };
29 |
30 | const SID2 AdministratorsSid = {
31 | {
32 | SID_REVISION, 2, SECURITY_NT_AUTHORITY, { SECURITY_BUILTIN_DOMAIN_RID }
33 | },
34 | {
35 | DOMAIN_ALIAS_RID_ADMINS,
36 | }
37 | };
38 |
39 | EXTERN_C NTSYSCALLAPI NTSTATUS NTAPI NtCreateToken(
40 | _Out_ PHANDLE TokenHandle,
41 | _In_ ACCESS_MASK DesiredAccess,
42 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
43 | _In_ TOKEN_TYPE TokenType,
44 | _In_ PLUID AuthenticationId,
45 | _In_ PLARGE_INTEGER ExpirationTime,
46 | _In_ PTOKEN_USER User,
47 | _In_ PTOKEN_GROUPS Groups,
48 | _In_ PTOKEN_PRIVILEGES Privileges,
49 | _In_opt_ PTOKEN_OWNER Owner,
50 | _In_ PTOKEN_PRIMARY_GROUP PrimaryGroup,
51 | _In_opt_ PTOKEN_DEFAULT_DACL DefaultDacl,
52 | _In_ PTOKEN_SOURCE TokenSource
53 | );
54 |
55 | HRESULT GetLastHrEx(BOOL fOk)
56 | {
57 | if (fOk)
58 | {
59 | return S_OK;
60 | }
61 | ULONG dwError = GetLastError();
62 | NTSTATUS status = RtlGetLastNtStatus();
63 | return RtlNtStatusToDosErrorNoTeb(status) == dwError ? HRESULT_FROM_NT(status) : HRESULT_FROM_WIN32(dwError);
64 | }
65 |
66 | NTSTATUS SetTrustedToken(_In_ HANDLE hToken, _In_ PSID Sid)
67 | {
68 | NTSTATUS status;
69 | PVOID stack = alloca(guz);
70 | PVOID buf = 0;
71 |
72 | ULONG cb = 0, rcb;
73 |
74 | struct {
75 | PTOKEN_GROUPS ptg; // must be first
76 | PTOKEN_DEFAULT_DACL ptdd;
77 | } s;
78 |
79 | void** ppv = (void**)&s.ptdd;
80 |
81 | static const ULONG rcbV[] = {
82 | sizeof(TOKEN_GROUPS)+0x80, // must be first
83 | sizeof(TOKEN_DEFAULT_DACL)+0x40,
84 | };
85 |
86 | static TOKEN_INFORMATION_CLASS TokenInformationClassV[] = {
87 | TokenGroups,
88 | TokenDefaultDacl,
89 | };
90 |
91 | ULONG n = _countof(TokenInformationClassV);
92 |
93 | BEGIN_PRIVILEGES(tp, 7)
94 | LAA(SE_CREATE_TOKEN_PRIVILEGE),
95 | LAA(SE_BACKUP_PRIVILEGE),
96 | LAA(SE_RESTORE_PRIVILEGE),
97 | LAA(SE_SECURITY_PRIVILEGE),
98 | LAA(SE_TAKE_OWNERSHIP_PRIVILEGE),
99 | LAA(SE_CHANGE_NOTIFY_PRIVILEGE),
100 | LAA(SE_IMPERSONATE_PRIVILEGE),
101 | END_PRIVILEGES
102 |
103 | do
104 | {
105 | TOKEN_INFORMATION_CLASS TokenInformationClas = TokenInformationClassV[--n];
106 |
107 | rcb = rcbV[n], cb = 0;
108 |
109 | do
110 | {
111 | if (cb < rcb)
112 | {
113 | cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
114 | }
115 |
116 | status = NtQueryInformationToken(hToken, TokenInformationClas, buf, cb, &rcb);
117 |
118 | } while (status == STATUS_BUFFER_TOO_SMALL);
119 |
120 | if (0 > status)
121 | {
122 | return status;
123 | }
124 |
125 | *(ppv--) = buf, stack = buf;
126 |
127 | } while (n);
128 |
129 | //if (!RtlEqualSid(Sid, const_cast(static_cast(Sid))))
130 | {
131 | // reserve stack space for extend groups
132 | alloca(sizeof(SID_AND_ATTRIBUTES));
133 | PSID_AND_ATTRIBUTES Groups = s.ptg->Groups - 1;
134 | ULONG GroupCount = s.ptg->GroupCount + 1;
135 | s.ptg = CONTAINING_RECORD(Groups, TOKEN_GROUPS, Groups);
136 | s.ptg->GroupCount = GroupCount;
137 |
138 | Groups->Sid = const_cast(static_cast(Sid));
139 | Groups->Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_OWNER;
140 | }
141 |
142 | TOKEN_USER tu = {{ const_cast(static_cast(&TrustedInstallerSid)) }};
143 | const static TOKEN_OWNER to = { const_cast(static_cast(&TrustedInstallerSid)) };
144 | const static LUID AuthenticationId = SYSTEM_LUID;
145 | const static LARGE_INTEGER ExpirationTime = { MAXULONG, MAXLONG };
146 | const static TOKEN_SOURCE ts = {{ '*', 'S', 'Y', 'S', 'T', 'E', 'M', '*' }};
147 |
148 | if (0 <= (status = SetToken(hToken)))
149 | {
150 | if (0 <= (status = NtCreateToken(&hToken, TOKEN_ALL_ACCESS,
151 | const_cast(&oa_sqos), TokenImpersonation,
152 | const_cast(&AuthenticationId), const_cast(&ExpirationTime),
153 | &tu, s.ptg, const_cast(&tp),
154 | const_cast(&to), (PTOKEN_PRIMARY_GROUP)&to, s.ptdd, const_cast(&ts))))
155 | {
156 | status = SetToken(hToken);
157 | NtClose(hToken);
158 | }
159 |
160 | if (0 > status)
161 | {
162 | SetToken();
163 | }
164 | }
165 |
166 | return status;
167 | }
168 |
169 | HRESULT SetTokenForService(_In_ SC_HANDLE hService, _In_ HANDLE hSystemToken, _In_ ULONG Mask)
170 | {
171 | ULONG dwError;
172 |
173 | PVOID stack = alloca(guz);
174 |
175 | union {
176 | PVOID buf;
177 | PSECURITY_DESCRIPTOR lpSecurityDescriptor;
178 | };
179 |
180 | ULONG cb = 0, rcb = 0x100;
181 | do
182 | {
183 | if (cb < rcb)
184 | {
185 | cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
186 | }
187 |
188 | dwError = BOOL_TO_ERROR(QueryServiceObjectSecurity(hService,
189 | DACL_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION,
190 | lpSecurityDescriptor, cb, &rcb));
191 |
192 | } while (dwError == ERROR_INSUFFICIENT_BUFFER);
193 |
194 | if (dwError == NOERROR)
195 | {
196 | dwError = ERROR_NOT_FOUND;
197 |
198 | BOOLEAN bpresent, bDefaulted;
199 | union {
200 | PACL Dacl;
201 | PSID Owner;
202 | };
203 | NTSTATUS status;
204 |
205 | if (0 <= RtlGetDaclSecurityDescriptor(lpSecurityDescriptor, &bpresent, &Dacl, &bDefaulted) && bpresent && Dacl)
206 | {
207 | if (USHORT AceCount = Dacl->AceCount)
208 | {
209 | union {
210 | PACCESS_ALLOWED_ACE pAce;
211 | PACE_HEADER pHead;
212 | PVOID pv;
213 | PBYTE pb;
214 | };
215 |
216 | pv = ++Dacl;
217 |
218 | do
219 | {
220 | if (pHead->AceType == ACCESS_ALLOWED_ACE_TYPE)
221 | {
222 | if ((pAce->Mask & Mask) == Mask)
223 | {
224 | if (0 > (status = SetTrustedToken(hSystemToken, &pAce->SidStart)))
225 | {
226 | dwError = HRESULT_FROM_NT(status);
227 | }
228 | else
229 | {
230 | dwError = NOERROR;
231 | }
232 | break;
233 | }
234 | }
235 |
236 | } while (pb += pHead->AceSize, --AceCount);
237 | }
238 | }
239 |
240 | if (ERROR_NOT_FOUND == dwError && (Mask & WRITE_DAC) &&
241 | (0 <= RtlGetOwnerSecurityDescriptor(lpSecurityDescriptor, &Owner, &bDefaulted)) && Owner)
242 | {
243 | if (0 > (status = SetTrustedToken(hSystemToken, Owner)))
244 | {
245 | dwError = HRESULT_FROM_NT(status);
246 | }
247 | else
248 | {
249 | dwError = NOERROR;
250 | }
251 | }
252 | }
253 |
254 | return HRESULT_FROM_WIN32(dwError);
255 | }
256 |
257 | HRESULT SetTokenForService(_In_ SC_HANDLE hSCManager, _In_ PCWSTR lpServiceName, _In_ HANDLE hSystemToken, _In_ ULONG Mask)
258 | {
259 | ULONG dwError;
260 |
261 | if (SC_HANDLE hService = OpenServiceW(hSCManager, lpServiceName, READ_CONTROL))
262 | {
263 | dwError = SetTokenForService(hService, hSystemToken, Mask);
264 |
265 | CloseServiceHandle(hService);
266 | }
267 | else
268 | {
269 | dwError = GetLastError();
270 | }
271 |
272 | return HRESULT_FROM_WIN32(dwError);
273 | }
274 |
275 | _NT_END
--------------------------------------------------------------------------------
/x64/srvs.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/x64/srvs.exe
--------------------------------------------------------------------------------
/x86/srvs.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/x86/srvs.exe
--------------------------------------------------------------------------------
/yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbmm/Services/511fcfe16e06223946598faab4b3b931ea54f57d/yellow.png
--------------------------------------------------------------------------------