背景:
在win7以上的系统,当系统服务要弹出对话框的时候,会弹出“交互式服务对话框检测”提示对话框。
原因分析:
真正的问题是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对象。下面的图例中,将进行图解:
上述解说参照的博客:
http://blog.csdn.net/angelxf/article/details/7552707
解决方案:
1.如果你不想要弹出这个对话框,可以参照百度经验里边的下边文章。
http://jingyan.baidu.com/article/8275fc86d8f04d46a03cf685.html
2.如果你编写服务的时候,想要直接弹出对话框,同时不弹出“交互式服务对话框检测”提示对话框。可以模拟当前用户来弹出对话框。
这里边用C语言,简单描述一下做法。
Test.h
//DWORD WINAPI WTSGetActiveConsoleSessionId(); //kernel32.dll
typedef DWORD (WINAPI *pWTSGetActiveConsoleSessionId)(void);
pWTSGetActiveConsoleSessionId WTSGetActiveConsoleSessionId;
//BOOL WINAPI CreateEnvironmentBlock( __out LPVOID *lpEnvironment, __in_opt HANDLE hToken, __in BOOL bInherit); //UserEnv.dll
//BOOL WINAPI DestroyEnvironmentBlock( __in LPVOID lpEnvironment);//UserEnv.dll
typedef BOOL (WINAPI *pCreateEnvironmentBlock)( LPVOID *lpEnvironment, HANDLE hToken, BOOL bInherit);
typedef BOOL (WINAPI *pDestroyEnvironmentBlock)( LPVOID lpEnvironment);
pCreateEnvironmentBlock CreateEnvironmentBlock;
pDestroyEnvironmentBlock DestroyEnvironmentBlock;
//BOOL WINAPI WTSQueryUserToken( ULONG SessionId, PHANDLE phToken); //wtsapi32.dll
typedef BOOL (WINAPI *pWTSQueryUserToken)( ULONG SessionId, PHANDLE phToken);
pWTSQueryUserToken WTSQueryUserToken;
Test.c
HINSTANCE hKernel32Lib,hWtsapi32Lib,hUserenvLib;
HANDLE hTokenThis = NULL;
HANDLE hDuplicatedToken = NULL;
LPVOID lpEnvironment = NULL;
DWORD dwSessionID;
char CurDir[_MAX_PATH];
int pos;
OSVERSIONINFOEX os;
STARTUPINFO si= {0};
PROCESS_INFORMATION pi = {0};
si.cb = sizeof(si);
si.lpDesktop = TEXT("winsta0\\default");
si.wShowWindow = SW_SHOWNORMAL;
//对话框程序
GetModuleFileName(NULL,CurDir,_MAX_PATH);
pos = strlen(CurDir)-strlen(strrchr(CurDir,'\\'));
strncpy(CurDir,CurDir,pos);
CurDir[pos] ='\0';
strcat(CurDir,"\\MsgDlg.exe");
//加载需要的动态链接库,vc6.0的时候需要
hKernel32Lib = LoadLibrary("kernel32.dll");
hWtsapi32Lib = LoadLibrary("wtsapi32.dll");
hUserenvLib = LoadLibrary("userenv.dll");
if( (hKernel32Lib != NULL) && (hWtsapi32Lib!=NULL) && (hUserenvLib!=NULL))
{
//加载需要的函数
WTSGetActiveConsoleSessionId = (pWTSGetActiveConsoleSessionId)GetProcAddress(hKernel32Lib, "WTSGetActiveConsoleSessionId");
CreateEnvironmentBlock = (pCreateEnvironmentBlock)GetProcAddress(hUserenvLib, "CreateEnvironmentBlock");
DestroyEnvironmentBlock = (pDestroyEnvironmentBlock)GetProcAddress(hUserenvLib, "DestroyEnvironmentBlock");
WTSQueryUserToken = (pWTSQueryUserToken)GetProcAddress(hWtsapi32Lib, "WTSQueryUserToken");
if( (WTSGetActiveConsoleSessionId!=NULL) && (CreateEnvironmentBlock!=NULL) && (DestroyEnvironmentBlock!=NULL) && (WTSQueryUserToken!=NULL) )
{
//模拟当前登录用户启动对话框
dwSessionID = WTSGetActiveConsoleSessionId();
WTSQueryUserToken(dwSessionID, &hTokenThis);
DuplicateTokenEx(hTokenThis,MAXIMUM_ALLOWED, NULL,SecurityIdentification,TokenPrimary,&hDuplicatedToken);
CreateEnvironmentBlock(&lpEnvironment,hDuplicatedToken, FALSE);
if( CreateProcessAsUser(hDuplicatedToken,CurDir, NULL, NULL, NULL, FALSE,NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE |CREATE_UNICODE_ENVIRONMENT,lpEnvironment, NULL, &si, &pi)== FALSE)
{
LogOutInt(DEF_MODULENAME, 93, 1, "CreateProcessAsUser-FALSE in PVDownLoadProcPS",GetLastError());
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
if( hTokenThis !=NULL )
CloseHandle(hTokenThis);
if( hDuplicatedToken !=NULL )
CloseHandle(hDuplicatedToken);
if( lpEnvironment !=NULL )
DestroyEnvironmentBlock(lpEnvironment);
FreeLibrary(hKernel32Lib);
hKernel32Lib=NULL;
FreeLibrary(hUserenvLib);
hUserenvLib=NULL;
FreeLibrary(hWtsapi32Lib);
hWtsapi32Lib=NULL;