实验资源下载地址:点击打开链接

只是不知道能不能从服务向桌面进程传递消息,,就像两个桌面进程之间用Sendmessage似的。。希望有知道的大神可以指点一下。。不胜感激。。

因为微软在Vista之后,对系统服务进行了隔离,即服务层为会话0 层,,而登录用户为1,2.。。。层,,因此,,假设须要服务层与用户进行交互,,仅仅能绕过Session 0 层。。因此己不能进行复杂的UI操作。。

服务是整合在Microsoft Windows操作系统中的结构。服务与用户的应用程序不同,由于你能够对他们进行配置,不须要一个激活的用户登录,就能够使这些服务在系统启动的时候执行,直到系统关闭。Windows中的服务,负责全部种类的后台活动,但不包含从远程过程调用(RPC)服务到网络位置服务的用户。

一些服务可能会试图显示一些用户界面对话框,或者与用户的应用程序进行通信。那么这些服务将会遇到与Windows 7 的兼容性问题。可能你有一个服务,试图显示一个对话框,可是,可能不过在任务栏中出现一个闪烁的图标。无独有偶,你的服务可能会多多少少遇到以下的一些现象。这些服务:

•              正在执行,可是没有做他们本希望去做的事情

•              正在执行,可是其它的一些进程却不能和这个服务进行通信

•              试图通过窗口消息,与用户的应用程序进行通信,可是窗口消息并没有被目标所接收到

•              在任务栏中,显示一个闪烁的图标,说明此服务希望与桌面信息进行交互

这些是Windows 7的服务的Session 0隔离机制的一些症状。它们能够大致分为两大类:

•              服务显示用户界面失败,或者只显示了一个简化的用户界面

当一个服务试图去展示不论什么有关用户界面的元素(即使这个服务被同意与桌面信息进行交互),一个叫做Interactive services dialog detection的简单对话框也会弹出,用于提示用户。用户能够进入Session 0的安全桌面中查看服务的用户界面,可是,工作流中的干扰,使得这个变成了一个严重的应用程序兼容性问题。

•              非常难实现服务和应用程序共享对象,而且这个对象将不可见

当一个对象由服务创建出来,而且同意标准应用程序訪问(以标准用户权限执行),那么这个对象将不能在全局命名空间中找到(它将被Session 0 中私有)。此外,安全变更,也将保证即使对象是可见的,但它也是不能被訪问的。这些将有可能影响其它的与你的服务进行交互的进程(比方普通用户的应用程序)。

真正的问题是Windows 7 服务的Session 0 隔离机制

在Windows XP, Windows Server 2003或者更早期的Windows操作系统中,全部的服务和应用程序都是执行在与第一个登录到控制台的用户得Session中。这个Session叫做Session 0。在Session 0 中一起执行服务和用户应用程序,因为服务是以高权限执行的,所以会造成一些安全风险。这些因素使得一些恶意代理利用这点,来寻找提升他们自身权限的结构。

在Windows Vista中,服务在一个叫做Session 0 的特殊Session中承载。因为应用程序执行在用户登录到系统后所创建的Session 0 之后的Session中,所以应用程序和服务也就隔离开来:第一个登录的用户在Session 1中,第二个在Session 2中,以此类推。其实执行在不同的Session中,假设没有特别将其放入全局命名空间(而且设置了对应的訪问控制配置),是不能互相传递窗口消息,共享UI元素或者共享kernel对象。以下的图例中,将进行图解:

了解很多其它关于Session 0 隔离机制,阅读Windows Vista 中的驱动和服务的Session 0 隔离机制的影响:http://www.microsoft.com/whdc/system/vista/services.mspx

解决方式

•              假设一个服务,须要向用户传递一条消息,那么能够使用WTSSendMessage方法。这种方法和MessageBox基本同样。它将能够给不须要复杂的UI界面的服务,一个简单而有效的解决方式,同一时候,因为所显示的消息对话框不能用于控制底层的服务,所以,这个解决方式也是安全的。

•              假设须要使用一个复杂的UI界面,那么能够使用CreateProcessAsUser方法,在提出请求的用户桌面中创建一个进程。

•         假设这两种交互方式都须要,那么能够使用诸如Windows Communication Foundation (WCF),.NET远程处理,命名管道或者其它的进程间通信(IPC)结构(除窗口消息之外)来跨Session通信。

•              安全通信和其它共享对象(比方,命名管道,文件地图),能够使用随意訪问控制列表(DACL)来严格控制用户的权限设置。使用系统訪问控制列表(SACL),来确保中低权限的进程依旧能够訪问由系统或高权限服务所创建的结构。

•              确保跨Session訪问的kernel对象是以Global\字符串为首字母进行命名,这意味着他们是属于全局Session命名空间中的。

解决方式步骤

眼下,我们已经遇到了全部的Windows服务的Session 0 隔离机制的情况,解释了什么是服务隔离,它是怎样影响你的服务和应用程序的,而且提出了一些解决方式。以下的一些測试和一些操作,能够帮助你找到问题,而且解决它。

试验 #1

1.            打开进程浏览器。

a.            下载或了解很多其它关于进程浏览器,请在Microsoft TechNet站点參看Process Explorer Web site 。

2.            确保进程浏览器显示了全部的进程:

a.            点击 File.

b.            选择 Show processes from all users.

3.            定位到可疑的服务,而且查看它的属性:

a.            右键点击进程。

b.            选择 Properties 。

c.             导航到 Security 标签。

d.            请注意服务执行在哪个Session中(通常在Session 0),而且它的所有级别。

以下是两个进程的样例-当中一个以中级权限执行(在Session 1),另外一个则以系统权限执行(在Session 1):

 

假设你的服务是以高权限执行在Session 0中,那么它将不能直接显示UI。只是即使这样,当你与服务进行共享kernel对象或者文件的时候,你可能还会遇到一些问题。

试验 #2

1.            打开进程浏览器。

2.            确保进程浏览器显示了全部的进程:

a.            点击 File.

b.            选择 Show processes from all users.

3.            定位到可疑的服务。

4.            假设服务包括了你已知的与用户应用程序共享的对象,请在以下的Handles窗体中检查他们的句柄(使用CTRL+H查看,或者从View菜单中进入)。

a.            右键点击每个能够的句柄,选择Properties。

b.            切换到Security标签页,查看当前用户和组是否同意使用当前句柄来訪问对象。

以下的图中,展示了一个无论是否是在Session 0 中执行的系统服务中,全部人都能够訪问的共享对象(“同步”权限):

以下的图中,展示了一个仅仅同意管理员和系统组才干訪问的共享对象:

5.            假设服务须要创建一个用户应用程序能够訪问的文件,请按照下面步骤:

a.            打开命令行窗体:

i.              点击 Start

ii.             指向 Programs

iii.            点击 Accessories

iv.           点击  Command Prompt

b.            执行icacls工具查看文件或者文件夹的集合权限和DACL信息,而且改动它们。

(请在Microsoft TechNet站点查看关于icacls的文档,以获取很多其它信息。)

c.             执行icacls MyFile来显示叫MyFile的文件的訪问控制列表。

d.            执行icacls MyFile /setintegritylevel Medium来将MyFile的集合权限级别改动为中级(这将使它能够訪问大部分用户应用程序。)

工具

•              进程浏览器 –Windows进程的监视工具,能够显示进程的集合级别和对象的安全信息。

o             很多其它信息: http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx

o             下载: http://download.sysinternals.com/Files/ProcessExplorer.zip

•              icacls –Windows有用工具中的一个,用于更改文件系统对象的ACL和整合级别。

o             很多其它信息: http://technet.microsoft.com/en-us/library/cc753525.aspx

代码演示样例

以下包括了一些演示样例代码,用来演示怎样:

•              使用WTSSendMessage从服务端向当前活动用户的桌面发送消息

•              当须要显示一个相对复杂的UI界面时,怎样在当前活动用户的桌面创建一个进程

•              创建一个属于全局命名空间的事件,而且包括安全配置,以便于它能够被当前活动用户所訪问。

使用WTSSendMessage 从服务端向当前活动用户的桌面发送消息:

void ShowMessage(LPWSTR lpszMessage, LPWSTR lpszTitle)

{

DWORD dwSession = WTSGetActiveConsoleSessionId();

DWORD dwResponse = 0;

WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, dwSession,

lpszTitle,

static_cast<DWORD>((wcslen(lpszTitle) + 1) * sizeof(wchar_t)),

lpszMessage,

static_cast<DWORD>((wcslen(lpszMessage) + 1) * sizeof(wchar_t)),

0, 0, &dwResponse, FALSE);

}

当须要显示一个相对复杂的UI 界面时,怎样在当前活动用户的桌面创建一个进程:

BOOL bSuccess = FALSE;

STARTUPINFO si = {0};

PROCESS_INFORMATION pi = {0};

si.cb = sizeof(si);

DWORD dwSessionID = WTSGetActiveConsoleSessionId();

HANDLE hToken = NULL;

if (WTSQueryUserToken(dwSessionID, &hToken) == FALSE)

{

goto Cleanup;

}

HANDLE hDuplicatedToken = NULL;

if (DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hDuplicatedToken) == FALSE)

{

goto Cleanup;

}

LPVOID lpEnvironment = NULL;

if (CreateEnvironmentBlock(&lpEnvironment, hDuplicatedToken, FALSE) == FALSE)

{

goto Cleanup;

}

WCHAR lpszClientPath[MAX_PATH];

if (GetModuleFileName(NULL, lpszClientPath, MAX_PATH) == 0)

{

goto Cleanup;

}

PathRemoveFileSpec(lpszClientPath);

wcscat_s(lpszClientPath, sizeof(lpszClientPath)/sizeof(WCHAR), L"\\TimeServiceClient.exe");

if (CreateProcessAsUser(hDuplicatedToken, lpszClientPath, NULL, NULL, NULL, FALSE,

NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,

lpEnvironment, NULL, &si, &pi) == FALSE)

{

goto Cleanup;

}

CloseHandle(pi.hProcess);

CloseHandle(pi.hThread);

bSuccess = TRUE;

Cleanup:

if (!bSuccess)

{

ShowMessage(L"An error occurred while creating fancy client UI", L"Error");

}

if (hToken != NULL)

CloseHandle(hToken);

if (hDuplicatedToken != NULL)

CloseHandle(hDuplicatedToken);

if (lpEnvironment != NULL)

DestroyEnvironmentBlock(lpEnvironment);

创建一个属于全局命名空间的事件,而且包括安全配置,以便于它能够被当前活动用户所訪问(从DACL 和SACL ):

DWORD dwSessionID = WTSGetActiveConsoleSessionId();

HANDLE hToken = NULL;

if (WTSQueryUserToken(dwSessionID, &hToken) == FALSE)

{

goto Cleanup;

}

DWORD dwLength;

TOKEN_USER* account = NULL;

if (GetTokenInformation(hToken, TokenUser, NULL, 0,& dwLength) == FALSE &&

GetLastError() != ERROR_INSUFFICIENT_BUFFER)

{

goto Cleanup;

}

account = (TOKEN_USER*)new BYTE[dwLength];

if (GetTokenInformation(hToken, TokenUser, (LPVOID)account, dwLength, &dwLength) == FALSE)

{

goto Cleanup;

}

LPWSTR lpszSid = NULL;

if (ConvertSidToStringSid(account->User.Sid,& lpszSid) == FALSE)

{

goto Cleanup;

}

WCHAR sddl[1000];

wsprintf(sddl, L"O:SYG:BAD:(A;;GA;;;SY)(A;;GA;;;%s)S:(ML;;NW;;;ME)", lpszSid);

PSECURITY_DESCRIPTOR sd = NULL;

if (ConvertStringSecurityDescriptorToSecurityDescriptor(sddl, SDDL_REVISION_1,& sd, NULL) == FALSE)

{

goto Cleanup;

}

SECURITY_ATTRIBUTES sa;

sa.bInheritHandle = FALSE;

sa.lpSecurityDescriptor = sd;

sa.nLength = sizeof(sa);

g_hAlertEvent = CreateEvent(&sa, FALSE, FALSE, L"Global\\AlertServiceEvent");

if (g_hAlertEvent == NULL)

{

goto Cleanup;

}

while (!g_Stop)

{

Sleep(5000);

SetEvent(g_hAlertEvent);

}

Cleanup:

if (hToken != NULL)

CloseHandle(hToken);

if (account != NULL)

delete[] account;

if (lpszSid != NULL)

LocalFree(lpszSid);

if (sd != NULL)

LocalFree(sd);

if (g_hAlertEvent == NULL)

CloseHandle(g_hAlertEvent);

而相同的,,假设须要用共享内存进行与桌面的进程通信的话,,在创建共享内存过程中,也须要进行权限的设置。。代码例如以下。。

此为服务内建立共享内存

		HANDLE hFileMap;
LPBYTE pcMap;
//PSECURITY_DESCRIPTOR securityDescriptorPointer1 = NULL;
//ServiceContext serviceContext1 = {0}; //serviceContext1.StatusHandle = RegisterServiceCtrlHandlerEx(argv[0], ControlHandlerEx, &serviceContext1);
//if (!serviceContext1.StatusHandle) {
// goto cleanup;
//} // if (!ConvertStringSecurityDescriptorToSecurityDescriptor(L"D:(A;;0x00000002;;;IU)(A;;GA;;;LS)", SDDL_REVISION_1, & securityDescriptorPointer1, NULL)) {
// goto cleanup;
// }
// SECURITY_ATTRIBUTES sa1 = {sizeof(SECURITY_ATTRIBUTES), securityDescriptorPointer1, FALSE};
// WriteToLog((char*)&sa1);
SECURITY_DESCRIPTOR secutityDese;
::InitializeSecurityDescriptor(&secutityDese, SECURITY_DESCRIPTOR_REVISION);
::SetSecurityDescriptorDacl(&secutityDese,TRUE,NULL,FALSE);
SECURITY_ATTRIBUTES securityAttr;
securityAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
securityAttr.bInheritHandle = FALSE;
securityAttr.lpSecurityDescriptor = &secutityDese;
// hMapping = CreateFileMappingW(INVALID_HANDLE_VALUE,&securityAttr,PAGE_READWRITE,0,0x100,L"Global\\z22"); hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,&securityAttr/*&sa1*/, PAGE_READWRITE, 0, 0x100, L"Global\\ShareData");
if(hFileMap == NULL)
{
WriteToLog("CreateFileMapping shibai");
return ;
}
// while(1)
// {
// WriteToLog("CreateFileMapping shibai");
//
// }
pcMap = (LPBYTE)MapViewOfFile(hFileMap, FILE_MAP_READ|FILE_MAP_WRITE,0, 0, 0);
if(pcMap == NULL)
{
WriteToLog("MapViewOfFile shibai");
return ;
}
int i = 0;
for(i = 0; i < len; i++)
{
pcMap[i] = IpaPath[i];
}
pcMap[i] = 0;
WriteToLog((char*)pcMap);
UnmapViewOfFile(pcMap); LPBYTE Get;
Get = (LPBYTE)MapViewOfFile(hFileMap,FILE_MAP_READ,0,0,0);
WriteToLog((char*)Get);
// CloseHandle(hFileMap); // delete []pChStr;


Windows系统服务的编写。的更多相关文章

  1. 将Tomcat加入windows系统服务

    将Tomcat加入windows系统服务 将Tomcat加入服务 1.修改bin目录中的service.bat: REM 添加下面的一行 set CATALINA_HOME=%cd% 如果从来没有安装 ...

  2. MongoDB安装,启动,注册为windows系统服务

    MongoDB安装与启动 周建旭 2014-08-10 解压完后配置环境变量 下载Windows 32-bit或64-bit版本并解压缩,程序文件都在bin目录中,其它两个目录分别是C++调用是的头文 ...

  3. VC Windows系统服务创建代码

    Windows系统服务创建步骤,常用类封装,废话不多说,直接上代码 // ServceDemo.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" ...

  4. windows后台服务程序编写

    Windows后台服务程序编写 1. 为什么要编写后台服务程序 工作中有一个程序需要写成后台服务的形式,摸索了一下,跟大家分享. 在windows操作系统中后台进程被称为 service. 服务是一种 ...

  5. 二、Windows 下 ShellCode 编写初步

    第二章.Windows 下 ShellCode 编写初步 (一)shellcode 定义:最先的 Shell 指的是人机交互界面,ShellCode 是一组能完成我们想要的功能的机器代码,通常以十六进 ...

  6. windows服务的编写,手动安装与卸载

    windows服务的编写 1.要添加的引用 using System.ServiceProcess; using System.ServiceModel ; using WcfServiceLibra ...

  7. C#开发奇技淫巧一:调试windows系统服务

    原文:C#开发奇技淫巧一:调试windows系统服务 windows系统服务不能直接运行,只能在安装完服务之后启动.暂停.继续.停止服务,导致服务的调试不能使用一般的断点调试. 要调试系统服务,可以采 ...

  8. 把Jar包加入windows系统服务

    之前在服务器上不一个Java服务时候,总是开着一堆黑框框,非常不雅,重点是极其容易误关,所以把可执行Jar文件加入Windows系统服务,看起来是个非常不错的选择!(实际上也确实是非常不错的选择) ! ...

  9. 将elasticsearch设置为windows系统服务

    目前我都是在windows的环境下操作是Elasticsearch,并且喜欢使用命令行 启动时通过cmd直接在elasticsearch的bin目录下执行elasticsearch 这样直接启动的话集 ...

随机推荐

  1. ZOJ 2412 Farm Irrigation(DFS 条件通讯块)

    意甲冠军  两个农田管内可直接连接到壳体  他们将能够共享一个水源   有11种农田  管道的位置高于一定  一个农田矩阵  问至少须要多少水源 DFS的连通块问题  两个相邻农田的管道能够直接连接的 ...

  2. Java写程序猿专访String2

    2.如何推理2一个字符串是否具有相同的字符 例如"aaaabbc"随着"abcbaaa" 2种思想 import java.lang.reflect.Array ...

  3. 3D数学--学习笔记(五岁以下儿童):总结一些概念(避免遗忘!)

    下面是一些概念只是一个简单的解释,这里是它的一个简单的了解! 当人们谈论,我能理解有关. 1.正交投影: 投影.这意味着降维操作. 全部的点都被拉平至垂直的轴(2D)或平面(3D)上.这样的类型的投影 ...

  4. NET版微信客户端.

    微信客户端.NET版 目录 说明 功能 原理步骤 一些参考 说明 前两天比较闲,研究了一下web版微信.因为之前看过一篇博客讲微信web协议的,后来尝试分析了一下,半途中发现其实没什么意义,但又不想半 ...

  5. Java达到MySQL数据库备份(两)

    博客<Java实现MySQL数据库备份(一)>使用I/O流的方式实现了MySQL数据库的备份,这样的方法比較繁杂.以下介绍还有一种备份MySQL数据库的方法: import java.io ...

  6. Android开发系列(十九个):至SimpleAdapter设置样式

    Adapter任务:在数据adapter处理后做.展会上的观点 对于一般ArrayAdapter供.传递给ArrayAdapter之后就能够在视图上用一个列表显示出这个字符串数组. 比例如以下边的代码 ...

  7. 注册表 ControlSet001、ControlSet002以及CurrentControlSet

    首先说说ControlSet几组控制之间的关系.      注册表HKLM\system注意 注册表项包含windows启动的三个控件组(额外还可能存在一个备份控件组).在初始状态下.它们各自是Con ...

  8. Chromium on Android: Android在系统Chromium为了实现主消息循环分析

    总结:刚开始接触一个Chromium on Android时间.很好奇Chromium主消息循环是如何整合Android应用. 为Android计划,一旦启动,主线程将具有Java消息层循环处理系统事 ...

  9. $.ajax()详解

    $.ajax()方法详解   jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Str ...

  10. 如何获得android手机通讯录的字母显示(两)

    随后的写如何使各第一字母显示相同的分类触点: 于adapter implement SectionIndexer 这项adapter必须在下面可以实现3接口: @Override public Obj ...