├── .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 --------------------------------------------------------------------------------