window服务调试(一):winodw服务运行原理
window服务调试(一):winodw服务运行原理
windows服务运行主要由三部分构成:安装windows服务 启动windows服务 卸载windows服务
一、安装window服务
安装window服务的原理是获取到SCM(服务控制管理器)的句柄,然后将服务名和该服务的可执行路径写入SCM中以注册一个服务,用到的Windows API有 OpenSCManager、CreateService
示例代码:
VOID SvcInstall()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
TCHAR szPath[MAX_PATH];
if (!GetModuleFileName(NULL, szPath, MAX_PATH))
{
printf("Cannot install service (%d)\n", GetLastError());
return;
}
// Get a handle to the SCM database.
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}
// Create the service
schService = CreateService(
schSCManager, // SCM database
SVCNAME, // name of service
SVCNAME, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
szPath, // path to service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password
if (schService == NULL)
{
printf("CreateService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
else printf("Service installed successfully\n");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
启动window服务
winodw服务并不是服务程序启动的,而是由SCM启动的,如下图所示( 按win+R 输入services.msc即可打开服务)当你启动这个服务时,SCM就会按照之前安装服务给出的路径去启动服务程序
这个时候
1.你需要告诉SCM主要的服务函数在哪里,然后SCM就会调用这个函数(StartServiceCtrlDispatcher)
2.用一个回调函数处理当SCM停止服务、暂停服务、恢复服务要做哪些操作(RegisterServiceCtrlHandler)
3.最后在主要的服务函数中告诉SCM启动成功(setSvcStatus或ReportSvcStatus)
示例代码
void __cdecl _tmain(int argc, TCHAR *argv[])
{
// If command-line parameter is "install", install the service.
// Otherwise, the service is probably being started by the SCM.
if (lstrcmpi(argv[1], TEXT("install")) == 0)
{
SvcInstall();
return;
}
// TO_DO: Add any additional services for the process to this table.
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
{ NULL, NULL }
};
DWORD dw_RetCode = -1;
// This call returns when the service has stopped.
// The process should simply terminate when the call returns.
if (!StartServiceCtrlDispatcher(DispatchTable))
{
dw_RetCode = GetLastError();
MessageBoxEx(NULL, _T("start SvrName service fail!"), NULL, 0, 0);
SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
}
}
VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
// Register the handler function for the service
gSvcStatusHandle = RegisterServiceCtrlHandler(
SVCNAME,
SvcCtrlHandler);
if (!gSvcStatusHandle)
{
SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
return;
}
// These SERVICE_STATUS members remain as set here
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE;
WriteToLog("in SvrMain(), start Service success!");
// Report initial status to the SCM
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
// Perform service-specific initialization and work.
SvcInit(dwArgc, lpszArgv);
}
卸载window服务
卸载Window服务是最简单的,利用OpenSCManager和OpenService获取服务句柄,再用DeleteService删除服务即可
代码实例(由于是逆向还原的代码,可读性有些差,多包涵)
void uninsatllService() {
SERVICE_STATUS ServiceStatus = {0,};
SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (!scm) {
_tprintf(L"UninstallService() : OpenSCManager failed (%d)", GetLastError());
return;
}
SC_HANDLE sevice = OpenService(scm, ServiceName, DELETE | SERVICE_INTERROGATE);
if (sevice == 0) {
DWORD error = GetLastError();
if (error != 0x424) {
_tprintf(L"UninstallService() : OpenSCManager failed (%d)", error);
CloseServiceHandle(scm);
return;
}
goto _EXIT;
}
ControlService(sevice, SERVICE_CONTROL_INTERROGATE, &ServiceStatus);
if (ServiceStatus.dwCurrentState != 1) {
_tprintf(L" -> Service is running! Stop the servi");
}
else {
if (DeleteService(sevice) == 0) {
_tprintf(L"UninstallService() : DeleteService fail");
}else
_tprintf(L"Service uninstalled successfully\n");
}
CloseServiceHandle(sevice);
_EXIT:
CloseServiceHandle(scm);
return;
}
完整源码:
#include <Windows.h>
#include<stdio.h>
#include<tchar.h>
#define ServiceName TEXT("SvcTest")
void WINAPI SvcMain(
DWORD dwNumServicesArgs,
LPSTR *lpServiceArgVectors
);
VOID WINAPI sub_401380(DWORD dwFlag);
void installService(TCHAR * fileName);
void uninsatllService();
struct _SERVICE_STATUS ServiceStatus = {0x10,0,0xFF,0,0,0,0};
SERVICE_STATUS_HANDLE hServiceStatus = {0,};
int _tmain(int argc, TCHAR*argv[]) {
TCHAR fileName[0x105] = {0,};
BOOL flag = FALSE;
LPSERVICE_MAIN_FUNCTIONW LpserviceMainFunctionw = (LPSERVICE_MAIN_FUNCTIONW)SvcMain;
SERVICE_TABLE_ENTRY steTable[] = {
{ServiceName,LpserviceMainFunctionw},
{NULL,NULL}
};
if (argc == 1) {
flag = StartServiceCtrlDispatcher(steTable);
if (flag) {
_tprintf(L"StartServiceCtrlDispatcher() failed!!! [%d]", GetLastError());
}
}
else if (argc == 2) {
if (!GetModuleFileName(NULL, fileName, 0x105)) {
printf("GetModuleFileName() failed! [%d]\n", GetLastError());
return 0;
}
if (!_tcsicmp(argv[1], L"install")) {
installService(fileName);
return 0;
}
if (!_tcsicmp(argv[1], L"uninstall")) {
uninsatllService();
return 0;
}
_tprintf(L"Wrong parameters!!!\n");
}
_tprintf(L"\nUSAGE : %s <install | uninstall>\n",argv[0]);
return 0;
}
void WINAPI SvcMain(
DWORD dwNumServicesArgs,
LPSTR *lpServiceArgVectors
) {
LPHANDLER_FUNCTION handle_funtion = (LPHANDLER_FUNCTION)sub_401380;
hServiceStatus = RegisterServiceCtrlHandler(ServiceName, handle_funtion);
if (hServiceStatus == NULL) {
OutputDebugString(L"RegisterServiceCtrlHandler() failed!!!");
return;
}
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hServiceStatus, &ServiceStatus);
do {
OutputDebugString(L"[SvcTest] service is running...");
Sleep(0x0BB8);
} while (TRUE);
}
void uninsatllService() {
SERVICE_STATUS ServiceStatus = {0,};
SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (!scm) {
_tprintf(L"UninstallService() : OpenSCManager failed (%d)", GetLastError());
return;
}
SC_HANDLE sevice = OpenService(scm, ServiceName, DELETE | SERVICE_INTERROGATE);
if (sevice == 0) {
DWORD error = GetLastError();
if (error != 0x424) {
_tprintf(L"UninstallService() : OpenSCManager failed (%d)", error);
CloseServiceHandle(scm);
return;
}
goto _EXIT;
}
ControlService(sevice, SERVICE_CONTROL_INTERROGATE, &ServiceStatus);
if (ServiceStatus.dwCurrentState != 1) {
_tprintf(L" -> Service is running! Stop the servi");
}
else {
if (DeleteService(sevice) == 0) {
_tprintf(L"UninstallService() : DeleteService fail");
}else
_tprintf(L"Service uninstalled successfully\n");
}
CloseServiceHandle(sevice);
_EXIT:
CloseServiceHandle(scm);
return;
}void installService(TCHAR * fileName) {
SC_HANDLE scm = OpenSCManager(NULL, NULL, 0xF003F);
if (scm == 0) {
_tprintf(L"InstallService() : OpenSCManager failed (%d)", GetLastError());
return;
}
SC_HANDLE service = CreateServiceW(scm, ServiceName, ServiceName, 0x0F01FF, 0x10, 3, 1, fileName, NULL, NULL, NULL, NULL, NULL);
if (service == 0) {
DWORD error = GetLastError();
_tprintf(L"InstallService() : CreateService failed (%d)", GetLastError());
if (error == 0x431) {
_tprintf(L"-> The specified service already exists.");
CloseServiceHandle(scm);
return;
}
else
goto _END;
}
_tprintf(L"InstallService() : Service installed successfully");
CloseServiceHandle(service);
_END:
CloseServiceHandle(scm);
}
VOID WINAPI sub_401380(DWORD dwFlag) {
if (dwFlag - 1 == 0) {
ServiceStatus.dwCurrentState = 3;
SetServiceStatus(hServiceStatus, &ServiceStatus);
ServiceStatus.dwCurrentState = 1;
SetServiceStatus(hServiceStatus, &ServiceStatus);
OutputDebugString(L"[SvcTest] service is stopped...");
}
return;
}