用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

494 lines
15 KiB

5 months ago
/**
@file
@brief
Windows NT Service class library.
Copyright Abandoned 1998 Irena Pancirov - Irnet Snc
This file is public domain and comes with NO WARRANTY of any kind
Modifications copyright (c) 2000, 2017. Oracle and/or its affiliates.
All rights reserved.
*/
#include "nt_servc.h"
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "sql/restart_monitor_win.h"
static NTService *pService;
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
NTService::NTService() {
bOsNT = false;
// service variables
ServiceName = NULL;
hExitEvent = 0;
bPause = false;
bRunning = false;
hThreadHandle = 0;
fpServiceThread = NULL;
// time-out variables
nStartTimeOut = 15000;
nStopTimeOut = 86400000;
nPauseTimeOut = 5000;
nResumeTimeOut = 5000;
// install variables
dwDesiredAccess = SERVICE_ALL_ACCESS;
dwServiceType = SERVICE_WIN32_OWN_PROCESS;
dwStartType = SERVICE_AUTO_START;
dwErrorControl = SERVICE_ERROR_NORMAL;
szLoadOrderGroup = NULL;
lpdwTagID = NULL;
szDependencies = NULL;
my_argc = 0;
my_argv = NULL;
hShutdownEvent = 0;
nError = 0;
dwState = 0;
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
NTService::~NTService() {
if (ServiceName != NULL) delete[] ServiceName;
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
BOOL NTService::GetOS() {
bOsNT = false;
memset(&osVer, 0, sizeof(OSVERSIONINFO));
osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osVer)) {
if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT) bOsNT = true;
}
return bOsNT;
}
/**
Registers the main service thread with the service manager.
@param szInternName Name of service to run in this process.
@param ServiceThread pointer to the main programs entry function
when the service is started
*/
long NTService::Init(LPCSTR szInternName, void *ServiceThread) {
pService = this;
fpServiceThread = (THREAD_FC)ServiceThread;
ServiceName = new char[lstrlen(szInternName) + 1];
lstrcpy(ServiceName, szInternName);
SERVICE_TABLE_ENTRY stb[] = {
{(char *)szInternName, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL}};
return StartServiceCtrlDispatcher(stb); // register with the Service Manager
}
/**
Installs the service with Service manager.
nError values:
- 0 success
- 1 Can't open the Service manager
- 2 Failed to create service.
*/
BOOL NTService::Install(int startType, LPCSTR szInternName,
LPCSTR szDisplayName, LPCSTR szFullPath,
LPCSTR szAccountName, LPCSTR szPassword) {
BOOL ret_val = false;
SC_HANDLE newService, scm;
if (!SeekStatus(szInternName, 1)) return false;
char szFilePath[_MAX_PATH];
GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
// open a connection to the SCM
if (!(scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE)))
printf("Failed to install the service (Couldn't open the SCM)\n");
else // Install the new service
{
if (!(newService = CreateService(
scm, szInternName, szDisplayName,
dwDesiredAccess, // default: SERVICE_ALL_ACCESS
dwServiceType, // default: SERVICE_WIN32_OWN_PROCESS
// default: SERVICE_AUTOSTART
(startType == 1 ? SERVICE_AUTO_START : SERVICE_DEMAND_START),
dwErrorControl, // default: SERVICE_ERROR_NORMAL
szFullPath, // exec full path
szLoadOrderGroup, // default: NULL
lpdwTagID, // default: NULL
szDependencies, // default: NULL
szAccountName, // default: NULL
szPassword))) // default: NULL
printf("Failed to install the service (Couldn't create service)\n");
else {
printf("Service successfully installed.\n");
CloseServiceHandle(newService);
ret_val = true; // Everything went ok
}
CloseServiceHandle(scm);
}
return ret_val;
}
/**
Removes the service.
nError values:
- 0 success
- 1 Can't open the Service manager
- 2 Failed to locate service
- 3 Failed to delete service.
*/
BOOL NTService::Remove(LPCSTR szInternName) {
BOOL ret_value = false;
SC_HANDLE service, scm;
if (!SeekStatus(szInternName, 0)) return false;
nError = 0;
// open a connection to the SCM
if (!(scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE))) {
printf("Failed to remove the service (Couldn't open the SCM)\n");
} else {
if ((service = OpenService(scm, szInternName, DELETE))) {
if (!DeleteService(service))
printf("Failed to remove the service\n");
else {
printf("Service successfully removed.\n");
ret_value = true; // everything went ok
}
CloseServiceHandle(service);
} else
printf("Failed to remove the service (Couldn't open the service)\n");
CloseServiceHandle(scm);
}
return ret_value;
}
/**
this function should be called before the app. exits to stop
the service
*/
void NTService::Stop(void) {
SetStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 160000);
StopService();
SetStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 1000);
}
void NTService::SetExitEvent() { SetEvent(hExitEvent); }
/**
This is the function that is called from the
service manager to start the service.
*/
void NTService::ServiceMain(DWORD argc, LPTSTR *argv) {
// registration function
if (!(pService->hServiceStatusHandle = RegisterServiceCtrlHandler(
pService->ServiceName,
(LPHANDLER_FUNCTION)NTService::ServiceCtrlHandler)))
goto error;
// notify SCM of progress
if (!pService->SetStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 8000))
goto error;
// create the exit event
if (!(pService->hExitEvent = CreateEvent(0, true, false, 0))) goto error;
if (!pService->SetStatus(SERVICE_START_PENDING, NO_ERROR, 0, 3,
pService->nStartTimeOut))
goto error;
// save start arguments
pService->my_argc = argc;
pService->my_argv = argv;
// start the service
if (!pService->StartService()) goto error;
// wait for exit event
WaitForSingleObject(pService->hExitEvent, INFINITE);
// wait for thread to exit
if (WaitForSingleObject(pService->hThreadHandle, INFINITE) == WAIT_TIMEOUT)
CloseHandle(pService->hThreadHandle);
pService->Exit(0);
return;
error:
pService->Exit(GetLastError());
return;
}
void NTService::SetRunning() {
if (pService) pService->SetStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
}
void NTService::SetSlowStarting(unsigned long timeout) {
if (pService)
pService->SetStatus(SERVICE_START_PENDING, NO_ERROR, 0, 0, timeout);
}
/* ------------------------------------------------------------------------
StartService() - starts the application thread
-------------------------------------------------------------------------- */
BOOL NTService::StartService() {
// Start the real service's thread (application)
if (!(hThreadHandle =
(HANDLE)_beginthread((THREAD_FC)fpServiceThread, 0, (void *)this)))
return false;
bRunning = true;
return true;
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
void NTService::StopService() {
bRunning = false;
signal_event(Signal_type::SIGNAL_SHUTDOWN);
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
void NTService::PauseService() {
bPause = true;
SuspendThread(hThreadHandle);
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
void NTService::ResumeService() {
bPause = false;
ResumeThread(hThreadHandle);
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
BOOL NTService::SetStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
DWORD dwWaitHint) {
BOOL bRet;
SERVICE_STATUS serviceStatus;
dwState = dwCurrentState;
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwCurrentState = dwCurrentState;
if (dwCurrentState == SERVICE_START_PENDING)
serviceStatus.dwControlsAccepted = 0; // don't accept control events
else
serviceStatus.dwControlsAccepted =
(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE |
SERVICE_ACCEPT_SHUTDOWN);
// if a specific exit code is defined,set up the win32 exit code properly
if (dwServiceSpecificExitCode == 0)
serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
else
serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
serviceStatus.dwCheckPoint = dwCheckPoint;
serviceStatus.dwWaitHint = dwWaitHint;
// Pass the status to the Service Manager
if (!(bRet = SetServiceStatus(hServiceStatusHandle, &serviceStatus)))
StopService();
return bRet;
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
void NTService::ServiceCtrlHandler(DWORD ctrlCode) {
DWORD dwState;
if (!pService) return;
dwState = pService->dwState; // get current state
switch (ctrlCode) {
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
dwState = SERVICE_STOP_PENDING;
pService->SetStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1,
pService->nStopTimeOut);
pService->StopService();
break;
default:
pService->SetStatus(dwState, NO_ERROR, 0, 0, 0);
break;
}
// pService->SetStatus(dwState, NO_ERROR,0, 0, 0);
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
void NTService::Exit(DWORD error) {
if (hExitEvent) CloseHandle(hExitEvent);
// Send a message to the scm to tell that we stop
if (hServiceStatusHandle) SetStatus(SERVICE_STOPPED, error, 0, 0, 0);
// If the thread has started kill it ???
// if (hThreadHandle) CloseHandle(hThreadHandle);
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType) {
BOOL ret_value = false;
SC_HANDLE service, scm;
// open a connection to the SCM
if (!(scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE))) {
DWORD ret_error = GetLastError();
if (ret_error == ERROR_ACCESS_DENIED) {
printf("Install/Remove of the Service Denied!\n");
if (!is_super_user())
printf(
"That operation should be made by an user with Administrator "
"privileges!\n");
} else
printf("There is a problem for to open the Service Control Manager!\n");
} else {
if (OperationType == 1) {
/* an install operation */
if ((service = OpenService(scm, szInternName, SERVICE_ALL_ACCESS))) {
LPQUERY_SERVICE_CONFIG ConfigBuf;
DWORD dwSize;
ConfigBuf = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LPTR, 4096);
printf("The service already exists!\n");
if (QueryServiceConfig(service, ConfigBuf, 4096, &dwSize))
printf("The current server installed: %s\n",
ConfigBuf->lpBinaryPathName);
LocalFree(ConfigBuf);
CloseServiceHandle(service);
} else
ret_value = true;
} else {
/* a remove operation */
if (!(service = OpenService(scm, szInternName, SERVICE_ALL_ACCESS)))
printf("The service doesn't exist!\n");
else {
SERVICE_STATUS ss;
memset(&ss, 0, sizeof(ss));
if (QueryServiceStatus(service, &ss)) {
DWORD dwState = ss.dwCurrentState;
if (dwState == SERVICE_RUNNING)
printf(
"Failed to remove the service because the service is "
"running\nStop the service and try again\n");
else if (dwState == SERVICE_STOP_PENDING)
printf(
"\
Failed to remove the service because the service is in stop pending state!\n\
Wait 30 seconds and try again.\n\
If this condition persist, reboot the machine and try again\n");
else
ret_value = true;
}
CloseServiceHandle(service);
}
}
CloseServiceHandle(scm);
}
return ret_value;
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
BOOL NTService::IsService(LPCSTR ServiceName) {
BOOL ret_value = false;
SC_HANDLE service, scm;
if ((scm = OpenSCManager(0, 0, SC_MANAGER_ENUMERATE_SERVICE))) {
if ((service = OpenService(scm, ServiceName, SERVICE_QUERY_STATUS))) {
ret_value = true;
CloseServiceHandle(service);
}
CloseServiceHandle(scm);
}
return ret_value;
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
BOOL NTService::got_service_option(char **argv, const char *service_option) {
char *option;
for (option = argv[1]; *option; option++)
if (!strcmp(option, service_option)) return true;
return false;
}
/* ------------------------------------------------------------------------
-------------------------------------------------------------------------- */
BOOL NTService::is_super_user() {
HANDLE hAccessToken;
UCHAR InfoBuffer[1024];
PTOKEN_GROUPS ptgGroups = (PTOKEN_GROUPS)InfoBuffer;
DWORD dwInfoBufferSize;
PSID psidAdministrators;
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
UINT x;
BOOL ret_value = false;
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, true, &hAccessToken)) {
if (GetLastError() != ERROR_NO_TOKEN) return false;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken))
return false;
}
ret_value = GetTokenInformation(hAccessToken, TokenGroups, InfoBuffer, 1024,
&dwInfoBufferSize);
CloseHandle(hAccessToken);
if (!ret_value) return false;
if (!AllocateAndInitializeSid(&siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
&psidAdministrators))
return false;
ret_value = false;
for (x = 0; x < ptgGroups->GroupCount; x++) {
if (EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid)) {
ret_value = true;
break;
}
}
FreeSid(psidAdministrators);
return ret_value;
}