降权启动进程
Contents
Win7下有些进程需要以管理员权限启动,比如安装程序。但又需要这个具有管理员权限的进程启动一个非管理员权限的进程。要实现这一点,方法很简单,首先得到受限的Token,然后由这个Token调用CreateProcessAsUser。
#include "stdafx.h"
#include <Windows.h>
#include <UserEnv.h>
#include <WinBase.h>
#include <WinSafer.h>
#pragma comment(lib, "Userenv.lib")
// 获取不含管理员权限的Token
HANDLE CreateNormalUserToken()
{
SAFER_LEVEL_HANDLE hLevel = NULL;
if (!SaferCreateLevel(SAFER_SCOPEID_USER, SAFER_LEVELID_NORMALUSER, SAFER_LEVEL_OPEN, &hLevel, NULL))
{
return NULL;
}
HANDLE hRestrictedToken = NULL;
if (!SaferComputeTokenFromLevel(hLevel, NULL, &hRestrictedToken, 0, NULL))
{
hRestrictedToken = NULL;
}
SaferCloseLevel(hLevel);
return hRestrictedToken;
};
// 从管理员进程,创建非管理员进程
BOOL DeElevateStartProcess(TCHAR* cmd)
{
const HANDLE hRestToken = CreateNormalUserToken();
if (NULL == hRestToken)
{
return FALSE;
}
DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
LPVOID pEnv = NULL;
if(CreateEnvironmentBlock(&pEnv, hRestToken, TRUE))
{
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
}
else
{
pEnv = NULL;
}
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = _T("winsta0\\default"); //default input desktop for the interactive window station
ZeroMemory(&pi, sizeof(pi));
const BOOL bResult = CreateProcessAsUser(hRestToken, // client's access token
NULL, // file to execute
cmd, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
dwCreationFlags, // creation flags
pEnv, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
if (bResult)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
if (pEnv)
{
DestroyEnvironmentBlock(pEnv);
}
CloseHandle(hRestToken);
return bResult;
}
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR cmd[] = _T("notepad.exe");
DeElevateStartProcess(cmd);
return 0;
}
需要创建出的进程支持拖拽的看这里:创建支持拖拽的进程
License 知识共享署名 3.0 中国大陆许可协议