早上好,
这个问题似乎已被问过几次,但我无法确定它是否真的有可能。我已发布在 here
没有回复 - 让我们试着在这里问人。
我的目标是从当前用户上下文中的服务启动一个提升的进程(以管理员身份)(仅当它们位于本地管理员组中时)。
我可以毫无问题地获得当前用户令牌,但我无法获得该帐户的辅助/管理员令牌!
我已经阅读了很多论坛,但却无法让它发挥作用(开始认为它不可行)。
我目前的方法:
WTSGetActiveConsoleSessionId
- 获取有效会话ID WTSQueryUserToken
- 获取会话ID的用户令牌OpenProcess
- 已登录用户的explorer.exe的处理句柄OpenProcessToken
- 获取访问令牌的处理LookupPrivilegeValue
- SE_DEBUG确认我们可以调整令牌权限DuplicateTokenEx
- 用户令牌SetTokenInformation
AdjustTokenPrivileges
CreateEnvironmentBlock
- 在CreateProcessAsUser
- 希望在提升的用户环境中生成流程(不会发生 - 标准用户环境)请参阅下面的代码 - 道歉它的杂乱,需要整理,所有句柄都关闭。这只是目前的经验代码。
public static bool CreateProcessInConsoleSession(String CommandLine, bool bElevate)
{
PROCESS_INFORMATION pi;
bool isadmin = IsUserAnAdmin();
bool bResult = false;
uint dwSessionId, winlogonPid = 0;
IntPtr hUserToken = IntPtr.Zero, hUserTokenDup = IntPtr.Zero,
hPToken = IntPtr.Zero, hProcess = IntPtr.Zero;
Debug.Print("CreateProcessInConsoleSession");
// Log the client on to the local computer.
dwSessionId = WTSGetActiveConsoleSessionId();
// Find the winlogon process
var procEntry = new PROCESSENTRY32();
uint hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
{
return false;
}
procEntry.dwSize = (uint)Marshal.SizeOf(procEntry); //sizeof(PROCESSENTRY32);
if (Process32First(hSnap, ref procEntry) == 0)
{
return false;
}
String strCmp = "explorer.exe";
do
{
if (strCmp.IndexOf(procEntry.szExeFile) == 0)
{
// We found a winlogon process...make sure it's running in the console session
uint winlogonSessId = 0;
if (ProcessIdToSessionId(procEntry.th32ProcessID, ref winlogonSessId) &&
winlogonSessId == dwSessionId)
{
winlogonPid = procEntry.th32ProcessID;
break;
}
}
}
while (Process32Next(hSnap, ref procEntry) != 0);
//Get the user token used by DuplicateTokenEx
WTSQueryUserToken(dwSessionId, ref hUserToken);
//Check if the user token is admin
isadmin = CheckIfAdminToken(hUserToken);
var si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = "winsta0\\default";
var tp = new TOKEN_PRIVILEGES();
var luid = new LUID();
hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);
TOKEN_INFORMATION_CLASS tokenInfo = new TOKEN_INFORMATION_CLASS();
uint TokenInfLength = 0 ;
if (
!OpenProcessToken(hProcess,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY
| TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE, ref hPToken))
{
Debug.Print(String.Format("CreateProcessInConsoleSession OpenProcessToken error: {0}",
Marshal.GetLastWin32Error()));
}
if (!LookupPrivilegeValue(IntPtr.Zero, SE_DEBUG_NAME, ref luid))
{
Debug.Print(String.Format("CreateProcessInConsoleSession LookupPrivilegeValue error: {0}",
Marshal.GetLastWin32Error()));
}
bool Result;
#region TestToElevate
//http://www.microsoft-questions.com/microsoft/Platform-SDK-Security/35984508/how-to-run-a-process-with-elevated-privileges-run-as-administrat.aspx
// first call gets lenght of TokenInformation
Result = GetTokenInformation(hPToken, TOKEN_INFORMATION_CLASS.TokenUser, IntPtr.Zero , TokenInfLength , out TokenInfLength );
IntPtr TokenInformation = Marshal.AllocHGlobal((int)TokenInfLength);
Result = GetTokenInformation(hPToken, TOKEN_INFORMATION_CLASS.TokenElevation, TokenInformation, TokenInfLength, out TokenInfLength);
if (Result == false)
Result = GetTokenInformation(hPToken, TOKEN_INFORMATION_CLASS.TokenLinkedToken, TokenInformation, TokenInfLength, out TokenInfLength);
isadmin = CheckIfAdminToken(hPToken);
#endregion
var sa = new SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)TOKEN_TYPE.TokenPrimary,
ref hUserTokenDup))
{
Debug.Print(
String.Format(
"CreateProcessInConsoleSession DuplicateTokenEx error: {0} Token does not have the privilege.",
Marshal.GetLastWin32Error()));
CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hPToken);
return false;
}
if (bElevate)
{
tp.PrivilegeCount = 1;
tp.Privileges = new int[3];
tp.Privileges[2] = SE_PRIVILEGE_ENABLED;
tp.Privileges[1] = luid.HighPart;
tp.Privileges[0] = luid.LowPart;
//Adjust Token privilege
if (!SetTokenInformation(hUserTokenDup, TOKEN_INFORMATION_CLASS.TokenSessionId, ref dwSessionId, (uint)IntPtr.Size))
{
Debug.Print(
String.Format(
"CreateProcessInConsoleSession SetTokenInformation error: {0} Token does not have the privilege.",
Marshal.GetLastWin32Error()));
CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hPToken);
CloseHandle(hUserTokenDup);
return false;
}
if (!AdjustTokenPrivileges(hUserTokenDup, false, ref tp, Marshal.SizeOf(tp), /*(PTOKEN_PRIVILEGES)*/ IntPtr.Zero, IntPtr.Zero))
{
int nErr = Marshal.GetLastWin32Error();
if (nErr == ERROR_NOT_ALL_ASSIGNED)
{
Debug.Print(String.Format(
"CreateProcessInConsoleSession AdjustTokenPrivileges error: {0} Token does not have the privilege.", nErr));
}
else
{
Debug.Print(String.Format("CreateProcessInConsoleSession AdjustTokenPrivileges error: {0}", nErr));
}
}
}
isadmin = CheckIfAdminToken(hUserTokenDup);
//Create Environment
uint dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
IntPtr pEnv = IntPtr.Zero;
if (CreateEnvironmentBlock(ref pEnv, hUserTokenDup, true))
{
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
}
else
{
pEnv = IntPtr.Zero;
}
// Launch the process in the client's logon session.
bResult = CreateProcessAsUser(
hUserTokenDup, // client's access token
null, // file to execute
CommandLine, // command line
ref sa, // pointer to process SECURITY_ATTRIBUTES
ref sa, // pointer to thread SECURITY_ATTRIBUTES
false, // handles are not inheritable
(int)dwCreationFlags, // creation flags
pEnv, // pointer to new environment block
null, // name of current directory
ref si, // pointer to STARTUPINFO structure
out pi // receives information about new process
);
// End impersonation of client.
//GetLastError should be 0
int iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
//Close handles task
CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
CloseHandle(hPToken);
return (iResultOfCreateProcessAsUser == 0) ? true : false;
}
答案 0 :(得分:0)
你不能。服务被隔离并在不同的会话(会话0)上运行,该会话与用户的会话(会话1,2,3等)隔离。