windows下一个用户下的所有进程一定都是在一个session里面吗

windows下一个用户登录进去,会产生一个会话,术语为session,可以用工具Process Explorer,查看进程的session id,如下所示,我们查看chrome进程的session id。

在这里插入图片描述
可以看出Session id是4.任务管理器中查看chrome的用户名是当前登录的用户名。

由于用户登录产生会话,故一直以为用户下所有进程必然是同一个session id,直到解决一个服务程序需要创建具有管理员权限的界面程序时,发现一个神奇的现象,任务管理器中的winlogon.exe进程的用户是SYSTEM,SYSTEM是服务程序用户,其下的程序的session一般是0,但是这个winlogon.exe是个例外,我们看下,如下图所示:
在这里插入图片描述
4是界面程序的session id,并且其权限信息显示其有管理员权限,所以利用这个winlogon.exe进程的token可以创建具有管理员权限的界面程序。
现在问题来了,SYSTEM用户(对应session为0)下是如何创建session为4的winlogon,经查,SetTokenInformation可以改变token所属的session,从而改变进程所属的session,下面是自己写的一个例子:

// TsService.cpp : Defines the entry point for the console application.
//

#include <stdio.h>

#include <Windows.h>

#include <UserEnv.h>


#pragma comment(lib, "userenv.lib")


#define SLEEP_TIME 50000 //间隔时间

bool brun = false;

SERVICE_STATUS servicestatus;

SERVICE_STATUS_HANDLE hstatus;

void WINAPI ServiceMain(int argc, char** argv);

void WINAPI CtrlHandler(DWORD request);

int InitService();

void CreateNewProcess()
{
	DWORD dwErr = 0;
	HANDLE hTokenThis = NULL;
	HANDLE hTokenDup = NULL;
	HANDLE hThisProcess = GetCurrentProcess();
	OpenProcessToken(hThisProcess, TOKEN_ALL_ACCESS, &hTokenThis);
	DuplicateTokenEx(hTokenThis, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup);
	DWORD dwSessionId = WTSGetActiveConsoleSessionId();
	BOOL bRet = SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD));
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	ZeroMemory(&si, sizeof(STARTUPINFO));
	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
	si.cb = sizeof(STARTUPINFO);
	si.lpDesktop = "WinSta0\\Default";
	LPVOID pEnv = NULL;
	DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
	CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE);
	bRet = CreateProcessAsUserA(
		hTokenDup,
		NULL,
		"E:\\learn\\c++\\mfc\\DllKiller\\Release\\DllKiller.exe",
		NULL,
		NULL,
		FALSE,
		dwCreationFlag,
		pEnv,
		NULL,
		&si,
		&pi);

	dwErr = ::GetLastError();
}

void WINAPI ServiceMain(int argc, char** argv)
{

	servicestatus.dwServiceType = SERVICE_WIN32;

	servicestatus.dwCurrentState = SERVICE_START_PENDING;

	servicestatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;//在本例中只接受系统关机和停止服务两种控制命令

	servicestatus.dwWin32ExitCode = 0;

	servicestatus.dwServiceSpecificExitCode = 0;

	servicestatus.dwCheckPoint = 0;

	servicestatus.dwWaitHint = 0;

	hstatus = ::RegisterServiceCtrlHandler("testservice", CtrlHandler);

	if (hstatus == 0)
	{

		return;

	}

	//向SCM 报告运行状态

	servicestatus.dwCurrentState = SERVICE_RUNNING;

	SetServiceStatus(hstatus, &servicestatus);

	//在此处添加你自己希望服务做的工作,在这里我做的工作是获得当前可用的物理和虚拟内存信息

	brun = true;

	MEMORYSTATUS memstatus;

	char str[100];

	memset(str, '\0', 100);

	while (brun)
	{
		CreateNewProcess();

		Sleep(SLEEP_TIME);

	}

}

void WINAPI CtrlHandler(DWORD request)
{

	switch (request)
	{
	case SERVICE_CONTROL_STOP:

		brun = false;

		servicestatus.dwCurrentState = SERVICE_STOPPED;

		break;

	case SERVICE_CONTROL_SHUTDOWN:

		brun = false;

		servicestatus.dwCurrentState = SERVICE_STOPPED;

		break;

	default:

		break;

	}

	SetServiceStatus(hstatus, &servicestatus);
}

void main()
{

	SERVICE_TABLE_ENTRY entrytable[2];

	entrytable[0].lpServiceName = "testservice";

	entrytable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

	entrytable[1].lpServiceName = NULL;

	entrytable[1].lpServiceProc = NULL;

	StartServiceCtrlDispatcher(entrytable);

}


工程名叫TsService.exe,用下面命令注册成服务:
sc create TsService binpath= E:\learn\c++\win32\Service\TsService\Release\TsService.exe
服务运行起来后,会创建进程DllKiller.exe,这个exe是自己写的一个程序,用户可以换成其他的exe文件。
结果是创建出的进程所属的用户名是SYSTEM,但是其session id却是4.

猜你喜欢

转载自blog.csdn.net/tusong86/article/details/106416221