-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathservice_operations.cpp
More file actions
149 lines (133 loc) · 5.29 KB
/
service_operations.cpp
File metadata and controls
149 lines (133 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "service_operations.h"
#include "common.h"
#include "privilege_guard.h"
#include <windows.h>
#include <iostream>
namespace {
bool SetServiceAcl(SC_HANDLE serviceHandle) {
return SetRestrictiveAcl(serviceHandle, SE_SERVICE, SERVICE_ALL_ACCESS, GENERIC_READ);
}
bool QueryServiceState(SC_HANDLE serviceHandle) {
SERVICE_STATUS_PROCESS statusInfo = {};
DWORD bytesNeeded = 0;
if (!QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO,
reinterpret_cast<LPBYTE>(&statusInfo),
sizeof(statusInfo), &bytesNeeded)) {
PrintLastError(L"QueryServiceStatusEx");
return false;
}
std::wcout << L"Service state: ";
switch (statusInfo.dwCurrentState) {
case SERVICE_STOPPED:
std::wcout << L"Stopped\n";
break;
case SERVICE_START_PENDING:
std::wcout << L"Starting...\n";
break;
case SERVICE_STOP_PENDING:
std::wcout << L"Stopping...\n";
break;
case SERVICE_RUNNING:
std::wcout << L"Running\n";
break;
case SERVICE_CONTINUE_PENDING:
std::wcout << L"Continue pending...\n";
break;
case SERVICE_PAUSE_PENDING:
std::wcout << L"Pause pending...\n";
break;
case SERVICE_PAUSED:
std::wcout << L"Paused\n";
break;
default:
std::wcout << L"Unknown (0x" << std::hex << statusInfo.dwCurrentState << std::dec << L")\n";
break;
}
return true;
}
} // namespace
int ProcessServiceCommand(const std::wstring& serviceName, const std::wstring& command) {
bool requiresTakeOwnership = false;
bool requiresRestorePrivilege = false;
DWORD desiredAccess = 0;
if (command == L"start" || command == L"stop") {
desiredAccess = SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS;
} else if (command == L"harden") {
desiredAccess = WRITE_DAC | WRITE_OWNER;
requiresRestorePrivilege = true; // Needed to set the owner to SYSTEM
requiresTakeOwnership = true; // Needed for WRITE_DAC
} else if (command == L"takeown") {
desiredAccess = WRITE_OWNER;
requiresTakeOwnership = true;
} else if (command == L"query") {
desiredAccess = SERVICE_QUERY_STATUS;
} else if (command == L"weaken") {
desiredAccess = WRITE_DAC;
} else {
std::wcerr << L"Unknown service command: " << command << L"\n";
std::wcerr << L"Valid commands: start, stop, query, harden, takeown, weaken\n";
return 1;
}
// Enable SE_TAKE_OWNERSHIP_NAME privilege for WRITE_OWNER access
PrivilegeGuard takeownPrivilegeGuard(requiresTakeOwnership ? SE_TAKE_OWNERSHIP_NAME : nullptr);
if (takeownPrivilegeGuard.IsValid() && !takeownPrivilegeGuard.IsEnabled()) {
return 1; // Error message already printed by PrivilegeGuard
}
// Enable SE_RESTORE_NAME privilege if setting owner to another user
PrivilegeGuard restorePrivilegeGuard(requiresRestorePrivilege ? SE_RESTORE_NAME : nullptr);
if (restorePrivilegeGuard.IsValid() && !restorePrivilegeGuard.IsEnabled()) {
return 1; // Error message already printed by PrivilegeGuard
}
std::wcout << L"Opening service: " << serviceName << L" with permissions: 0x" << std::hex << desiredAccess << std::dec << L"\n";
SC_HANDLE scmHandle = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT);
if (!scmHandle) {
PrintLastError(L"OpenSCManager");
return 1;
}
SC_HANDLE serviceHandle = OpenServiceW(scmHandle, serviceName.c_str(), desiredAccess);
if (!serviceHandle) {
PrintLastError(L"OpenService");
CloseServiceHandle(scmHandle);
return 1;
}
bool success = false;
if (command == L"start") {
std::wcout << L"Starting service...\n";
success = StartServiceW(serviceHandle, 0, nullptr) != 0;
if (success) {
std::wcout << L"Service started successfully\n";
} else {
PrintLastError(L"StartService");
}
} else if (command == L"stop") {
SERVICE_STATUS status;
std::wcout << L"Stopping service...\n";
success = ControlService(serviceHandle, SERVICE_CONTROL_STOP, &status) != 0;
if (success) {
std::wcout << L"Service stopped successfully\n";
} else {
PrintLastError(L"ControlService");
}
} else if (command == L"harden") {
success = SetServiceAcl(serviceHandle);
if (success) {
std::wcout << L"Service ACL hardened successfully\n";
}
} else if (command == L"takeown") {
DWORD result = TakeOwnership(serviceHandle, SE_SERVICE);
success = (result == ERROR_SUCCESS);
if (success) {
std::wcout << L"Service ownership transferred to Administrators\n";
}
} else if (command == L"weaken") {
success = WeakenAcl(serviceHandle, SE_SERVICE, SERVICE_ALL_ACCESS);
if (success) {
std::wcout << L"Service ACL weakened successfully (Everyone has full access)\n";
}
} else if (command == L"query") {
success = QueryServiceState(serviceHandle);
}
CloseServiceHandle(serviceHandle);
CloseServiceHandle(scmHandle);
return success ? 0 : 1;
}