CreateProcessAsUser-Erstellen-Fenster in der Aktiven Sitzung
Ich bin mit CreateProcessAsUser aus einem windows service (bitte können wir bleiben am Thema und an ich habe einen sehr guten Grund, dies zu tun). Im Gegensatz zu dem, was alle anderen Fragen hier, ich bin immer ein Fenster in meiner aktiven terminal session (Sitzung 1) anstelle der gleichen Sitzung wie der service (session-0) - und das ist unerwünscht.
Angeeignet ich Scott Allen - code; und kam mit der folgenden. Wesentliche änderungen sind der "revert to self", der "CREATE_NO_WINDOW" und Kommandozeilen-Argumente unterstützen.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Security.Principal;
using System.ComponentModel;
using System.IO;
namespace SourceCode.Runtime.ChildProcessService
{
[SuppressUnmanagedCodeSecurity]
class NativeMethods
{
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public Int32 dwProcessID;
public Int32 dwThreadID;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public Int32 Length;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
public enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
public enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
public const int GENERIC_ALL_ACCESS = 0x10000000;
public const int CREATE_NO_WINDOW = 0x08000000;
[
DllImport("kernel32.dll",
EntryPoint = "CloseHandle", SetLastError = true,
CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)
]
public static extern bool CloseHandle(IntPtr handle);
[
DllImport("advapi32.dll",
EntryPoint = "CreateProcessAsUser", SetLastError = true,
CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)
]
public static extern bool
CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandle, Int32 dwCreationFlags, IntPtr lpEnvrionment,
string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo,
ref PROCESS_INFORMATION lpProcessInformation);
[
DllImport("advapi32.dll",
EntryPoint = "DuplicateTokenEx")
]
public static extern bool
DuplicateTokenEx(IntPtr hExistingToken, Int32 dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
Int32 ImpersonationLevel, Int32 dwTokenType,
ref IntPtr phNewToken);
public static Process CreateProcessAsUser(string filename, string args)
{
var hToken = WindowsIdentity.GetCurrent().Token;
var hDupedToken = IntPtr.Zero;
var pi = new PROCESS_INFORMATION();
var sa = new SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
try
{
if (!DuplicateTokenEx(
hToken,
GENERIC_ALL_ACCESS,
ref sa,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)TOKEN_TYPE.TokenPrimary,
ref hDupedToken
))
throw new Win32Exception(Marshal.GetLastWin32Error());
var si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = "";
var path = Path.GetFullPath(filename);
var dir = Path.GetDirectoryName(path);
//Revert to self to create the entire process; not doing this might
//require that the currently impersonated user has "Replace a process
//level token" rights - we only want our service account to need
//that right.
using (var ctx = WindowsIdentity.Impersonate(IntPtr.Zero))
{
if (!CreateProcessAsUser(
hDupedToken,
path,
string.Format("\"{0}\" {1}", filename.Replace("\"", "\"\""), args),
ref sa, ref sa,
false, 0, IntPtr.Zero,
dir, ref si, ref pi
))
throw new Win32Exception(Marshal.GetLastWin32Error());
}
return Process.GetProcessById(pi.dwProcessID);
}
finally
{
if (pi.hProcess != IntPtr.Zero)
CloseHandle(pi.hProcess);
if (pi.hThread != IntPtr.Zero)
CloseHandle(pi.hThread);
if (hDupedToken != IntPtr.Zero)
CloseHandle(hDupedToken);
}
}
}
}
Nun davon ausgehen, dass der Dienst ausgeführt wird, unter "Domain\MyService', und ich bin derzeit angemeldet als 'Domäne\Administrator' - und ich bin dem Booten eine Konsole-Anwendung, wie ein Arbeitsprozess. Wenn ich eine client-Anwendung zum Zugriff auf den Dienst (der Dienst ist nicht gestartet, im Konsolen-Modus, d.h. es wird in session 0) und führen Sie dann die Methode aufruft, die die CreateProcessAsUser
den Arbeitsprozess erscheint auf meinem desktop.
Nun, ich könnte es eine windows Anwendung ohne Fenster zu Seite-Schritt die Erstellung von Konsolen-Fenster; jedoch, am Ende des Tages ist es immer noch in Sitzung 1.
Irgendwelche Ideen, warum die Konsole-Anwendung nicht erstellt wird, in der gleichen Sitzung wie der service?
Versucht, mit Hilfe von "Service-0×0-3e7$\Default" als die desktop -, die bewirkt, dass die Anwendung zum Absturz zu bringen.
Welche version von Windows? Haben Sie versucht, zu verlassen ipdesktop bei null?
Server 2008 R2. Ich habe in der Tat versucht, die Einstellung
lpDeskTop
zu null
(was zum Absturz führte, in den Arbeitsprozess) - ich habe auch versucht eine Einstellung von verschiedenen hart-kodierten Werten wie die built-in session 0 desktop-Namen.Wenn so viele Umstände, die Abstürze verursachen, vielleicht gibt es ein Marshalling Problem. Können Sie nach dem code für Ihre Strukturen und externs?
InformationsquelleAutor Jonathan Dickinson | 2012-02-01
Du musst angemeldet sein, um einen Kommentar abzugeben.
Als wahrscheinlich wissen Sie bereits, die isolation von Sitzung 0 ist für die Sicherheit Grund, und Sie können mehr darüber Lesen Sie hier
http://msdn.microsoft.com/en-us/windows/hardware/gg463353.aspx
Hinsichtlich, warum Ihre Konsole app erstellt, in der aktiven Sitzung (z.B. "Sitzung 1"), das eigentlich verlinkte direkt zurück zu Ihrem Benutzer-token. Wenn Sie Fragen, für aktuellen Benutzer-token das token automatisch mit der session-id-Informationen - in diesem Fall ist es das login-terminal services-Sitzung (Sitzung 1). Diese session-id wird die Referenz durch das Zeichen, die dann repliziert in der DuplicateTokenEx und dann in der CreateProcessAsUser-rufen. Um die Kraft der Schöpfung, die Ihre Konsole-Anwendung, die in Sitzung 0 ist, werden Sie brauchen, um einen expliziten Aufruf der SetTokenInformation API - (advapi32.dll), gingen in Ihren hDupedToken vor dem Aufruf CreateProcessAsUser wie unten
Hier ist mehr info auf SetTokenInformation http://msdn.microsoft.com/en-us/library/windows/desktop/aa379591(v=vs. 85).aspx
Vielen Dank für die Hilfe - ich bin gerade Probleme mit dem Erwerb der
SE_TCB_NAME
rechts (benötigt fürSetTokenInformation
). Ich habe zugegeben mein service Konto "einsetzen als Teil des Betriebssystem" Recht (wie auch der SERVICE für die shotgun-Versicherung). Ich habe versucht mitOpenThreadToken
mitTOKEN_ALL_ACCESS
- ohne Erfolg. Du hast das +250 - ich bin nur der Hoffnung, Sie haben ein wenig mehr Erfahrung in dieser Hinsicht, um mir zu helfen.Du bekommst das Kopfgeld. Zeit für ein neues Kopfgeld ;).
Vielen Dank für die bounty. Ich glaube nicht, dass es viel Weg, um es, wenn Ihr Dienst wird gestartet unter Verwendung von Benutzer-account, die von sich selbst begrenzt hat, OS Privileg. Kann Sie nicht starten Sie Ihren service mit LocalSystem-Konto? LocalSystem können starten Sie Ihren Prozess und automatisch haben, die Sicherheit und den Zugang zu anderen WTS-API, die Sie in der TS-Umgebung.
Ich hatte überlegt, aber es hat eine wirklich hohe installer Auswirkungen (unsere primäre Dienst muss unter einem Domänen-Konto) - noch werde ich es in der Tasche für später und sehen, ob management beißen angesichts der Gefahr. Vielen Dank für die Hilfe.
InformationsquelleAutor Fadrian Sudaman
War ich in der Lage zu implementieren, der erste post als eine funktionierende Lösung auf mein Ende, aber ich kann nicht scheinen, um einen Weg zu finden, um meine Konsole-Fenster ausgeblendet. Ich habe versucht, STARTF_USESHOWWINDOW und SW_HIDE aber mein command-Fenster immer noch erscheint. Irgendeine Idee warum?
InformationsquelleAutor Saif Khan
Versuchen Herumspielen mit den CharSet-benannte parameter von
MarshalAs
,StructLayout
, undDllImport
. Müssen Sie möglicherweiseMarshalAs
auf verschiedenen Saiten, um dies zu tun. Nicht die Mühe mit Unicode: Sie sind nicht mit dieser. Ich empfehle die Einstellung, Sie alle zuCharSet.Ansi
ersten. Führen Sie alle tests, die du schon versucht hast--das ist die Einstellung der desktop-und all das lustige Zeug. Wenn er abstürzt, schalten Sie Sie alle auf auto. Wenn es immer noch nicht funktioniert, entfernen Sie alle.Vorausgesetzt, keines dieser Werke, wechseln Sie zu
CreateUserProcessW
undCharSet.Unicode
damit Sie wissen, was Sie bekommen. Auf den zweiten Gedanken, überspringen Sie einfach diesen Schritt.Wenn Sie brauchen, um die
UnmanagedType
mitMarshalAs
für Streicher, Sie wollenUnmanagedType.LPStr
für AnsiUnmanagedType.LPTStr
für Auto undUnmanagedType.LPWStr
für Unicode. Eigentlich tun Sie dies für alle Ihre Saiten sowieso.vielen Dank - ich gebe es zu gehen heute Abend und Bericht zurück.
Viel Glück! Wenn Sie das Gefühl ehrgeizig, direkt in Unicode.
InformationsquelleAutor Zenexer