您的位置:首页 > 其它

[Win32] 服务程序开发(4)自定义控制码与服务通信

2015-08-17 09:35 363 查看
本博文由CSDN博主zuishikonghuan所作,版权归zuishikonghuan所有,转载请注明出处:/article/9672535.html
在上几篇博文中,我演示了如何编写一个系统服务,介绍了如何穿透Session 0在当前用户的桌面上创建一个用户进程,也可以获取服务自己的权限令牌在用户的桌面上创建一个拥有SYSTEM权限的进程。这一篇,我就说说如何使用自定义控制码与服务程序通信。

其实这一篇呢应该放到我以后的服务管理API系列去讲,但是毕竟服务开发吗,没有应用程序与服务的通信实在是说不过去,于是还是简单说一说。

只是与服务通信的时候也会受Session 0隔离的影响,比如:无法共享Windows消息啊,无法远程注入,无法远程读写内存等等。但是其他的进程间通信机制并不受影响,比如:命名管道,我们可以将自定义控制码和命名管道结合起来,实现进程通信。

首先来看看如何向服务发送自定义控制码

关于控制码,用户自定义控制码的范围,已经在[Win32] 服务程序开发(1)基本概念和服务程序的框架中讲过了,不再重复。

第一步:在服务程序的HandlerEx里注册用户控制码:(这里我用的200)

DWORD WINAPI HandlerEx(_In_ DWORD  dwControl, _In_ DWORD  dwEventType, _In_ LPVOID lpEventData, _In_ LPVOID lpContext)
{
switch (dwControl)
{
case SERVICE_CONTROL_STOP://控制代码:要求停止停止
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hStatus, &ServiceStatus);//报告服务运行状态
return 0;
case SERVICE_CONTROL_SHUTDOWN://控制代码:关机
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hStatus, &ServiceStatus);//报告服务运行状态
return 0;
case 200:
//这里是接收此控制码时的逻辑,可以在此处读命名管道。这里简单弹一个对话框
ShowMessage(L"收到自定义控制码", L"服务");
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hStatus, &ServiceStatus);//报告服务运行状态
return 0;
default:
break;
}
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hStatus, &ServiceStatus);//报告服务运行状态
return 0;
}


第二步:在用户进程中发送控制码
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (hSCManager != NULL){
SC_HANDLE hService = OpenService(hSCManager, TEXT("zz"), SERVICE_USER_DEFINED_CONTROL);
if (hService != NULL){
SERVICE_STATUS status;
if (!ControlService(hService, 200, &status)){
//发生控制码失败
}
CloseServiceHandle(hService);
}
else{
//OpenService失败
}
CloseServiceHandle(hSCManager);
}
else{
//OpenSCManager失败
}
这个代码可以在管理员权限的程序中执行也可以在非管理员权限的进程中执行。原因是权限设定:SC_MANAGER_CONNECT和SERVICE_USER_DEFINED_CONTROL限制了服务句柄只能用于发送用户自定义控制码。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: