呼び出しCreateProcessAsUserからC#
-
21-08-2019 - |
質問
している新しいプロセス下でのコンテキストの特定のユーザーを使用 CreateProcessAsUser
機能のWindows APIがいきなどの手セキュリティ問題が...
前にも説明し、更に、こちらのコードを使ってい開始の新しいプロセス(コンソールプロセスユ具体的には、こんな物を).
private void StartProcess()
{
bool retValue;
// Create startup info for new console process.
var startupInfo = new STARTUPINFO();
startupInfo.cb = Marshal.SizeOf(startupInfo);
startupInfo.dwFlags = StartFlags.STARTF_USESHOWWINDOW;
startupInfo.wShowWindow = _consoleVisible ? WindowShowStyle.Show : WindowShowStyle.Hide;
startupInfo.lpTitle = this.ConsoleTitle ?? "Console";
var procAttrs = new SECURITY_ATTRIBUTES();
var threadAttrs = new SECURITY_ATTRIBUTES();
procAttrs.nLength = Marshal.SizeOf(procAttrs);
threadAttrs.nLength = Marshal.SizeOf(threadAttrs);
// Log on user temporarily in order to start console process in its security context.
var hUserToken = IntPtr.Zero;
var hUserTokenDuplicate = IntPtr.Zero;
var pEnvironmentBlock = IntPtr.Zero;
var pNewEnvironmentBlock = IntPtr.Zero;
if (!WinApi.LogonUser("UserName", null, "Password",
LogonType.Interactive, LogonProvider.Default, out hUserToken))
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error logging on user.");
var duplicateTokenAttrs = new SECURITY_ATTRIBUTES();
duplicateTokenAttrs.nLength = Marshal.SizeOf(duplicateTokenAttrs);
if (!WinApi.DuplicateTokenEx(hUserToken, 0, ref duplicateTokenAttrs,
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary,
out hUserTokenDuplicate))
throw new Win32Exception(Marshal.GetLastWin32Error(), "Error duplicating user token.");
try
{
// Get block of environment vars for logged on user.
if (!WinApi.CreateEnvironmentBlock(out pEnvironmentBlock, hUserToken, false))
throw new Win32Exception(Marshal.GetLastWin32Error(),
"Error getting block of environment variables for user.");
// Read block as array of strings, one per variable.
var envVars = ReadEnvironmentVariables(pEnvironmentBlock);
// Append custom environment variables to list.
foreach (var var in this.EnvironmentVariables)
envVars.Add(var.Key + "=" + var.Value);
// Recreate environment block from array of variables.
var newEnvironmentBlock = string.Join("\0", envVars.ToArray()) + "\0";
pNewEnvironmentBlock = Marshal.StringToHGlobalUni(newEnvironmentBlock);
// Start new console process.
retValue = WinApi.CreateProcessAsUser(hUserTokenDuplicate, null, this.CommandLine,
ref procAttrs, ref threadAttrs, false, CreationFlags.CREATE_NEW_CONSOLE |
CreationFlags.CREATE_SUSPENDED | CreationFlags.CREATE_UNICODE_ENVIRONMENT,
pNewEnvironmentBlock, null, ref startupInfo, out _processInfo);
if (!retValue) throw new Win32Exception(Marshal.GetLastWin32Error(),
"Unable to create new console process.");
}
catch
{
// Catch any exception thrown here so as to prevent any malicious program operating
// within the security context of the logged in user.
// Clean up.
if (hUserToken != IntPtr.Zero)
{
WinApi.CloseHandle(hUserToken);
hUserToken = IntPtr.Zero;
}
if (hUserTokenDuplicate != IntPtr.Zero)
{
WinApi.CloseHandle(hUserTokenDuplicate);
hUserTokenDuplicate = IntPtr.Zero;
}
if (pEnvironmentBlock != IntPtr.Zero)
{
WinApi.DestroyEnvironmentBlock(pEnvironmentBlock);
pEnvironmentBlock = IntPtr.Zero;
}
if (pNewEnvironmentBlock != IntPtr.Zero)
{
Marshal.FreeHGlobal(pNewEnvironmentBlock);
pNewEnvironmentBlock = IntPtr.Zero;
}
throw;
}
finally
{
// Clean up.
if (hUserToken != IntPtr.Zero)
WinApi.CloseHandle(hUserToken);
if (hUserTokenDuplicate != IntPtr.Zero)
WinApi.CloseHandle(hUserTokenDuplicate);
if (pEnvironmentBlock != IntPtr.Zero)
WinApi.DestroyEnvironmentBlock(pEnvironmentBlock);
if (pNewEnvironmentBlock != IntPtr.Zero)
Marshal.FreeHGlobal(pNewEnvironmentBlock);
}
_process = Process.GetProcessById(_processInfo.dwProcessId);
}
のための課題ここで、無視するコードを扱うに環境変数(私試れ独立してるようになったようです。)
現在、このエラーを取得します以下の(スローされるラインの呼び出 CreateProcessAsUSer
):
"必要な特典が開催され、クライアント"(エラーコード1314)
(エラーメッセージによって発見され除去のメッセージのパラメータからのWin32Exceptionコンストラクタです。確かに、私のエラーコードの取り扱いがありませんのでやや不ます。致しましてコメントでご希望の場合はしています。) ほんっと混乱しないように気をつけるの原因は漠然としたエラーのことです。MSDN文書および各種フォーラムのスレッドのみを与えてくれた存在だといってよいのでアドバイスは、特にその原因間のコミュニケーションが多様を持っていませんというアイデアのコードを修正する必要があ.このような単一のパラメータIの変更が必要なものをとることができると思いますか、誤り/なすのキャンペーンはすべて分かっています。何を混乱さんを大きくすることを以前のバージョンのコードを使用するの CreateProcess
機能と同等以外のユーザーのトークンパラメータ)を完璧に動作します。私の理解では、必要な限りにおいて、ログオンユーザの機能を受け、適切なトークンの取扱およびその複製でき渡し CreateProcessAsUser
.
あらゆる提案のための改造、コーポレートガバナンスと説明することを歓迎する。
注記
私は主に参考にMSDN docsなど PInvoke.net C#機能/柱/enum宣言).以下のページは特にそう多くの情報は、その一部が重要で逃した
編集
いただきました、走ったことがありましたMitchの提案が、残念ながらの古いエラーで取り替え:"システムにファイルを指定します。" (エラーコード2)
前の呼び出 CreateProcessAsUser
したの
retValue = WinApi.CreateProcessWithTokenW(hUserToken, LogonFlags.WithProfile, null,
this.CommandLine, CreationFlags.CREATE_NEW_CONSOLE |
CreationFlags.CREATE_SUSPENDED | CreationFlags.CREATE_UNICODE_ENVIRONMENT,
pNewEnvironmentBlock, null, ref startupInfo, out _processInfo);
このコードな使用にはトークンの複製ではなく、独自にMSDN docsが示唆する.
ここで、この日の試用 CreateProcessWithLogonW
.エラー時には"ログオンに失敗:不明ユーザ名やパスワード"(エラーコード1326)
retValue = WinApi.CreateProcessWithLogonW("Alex", null, "password",
LogonFlags.WithProfile, null, this.CommandLine,
CreationFlags.CREATE_NEW_CONSOLE | CreationFlags.CREATE_SUSPENDED |
CreationFlags.CREATE_UNICODE_ENVIRONMENT, pNewEnvironmentBlock,
null, ref startupInfo, out _processInfo);
この指定のユーザー名にUPN形式("アレックス@アレックス-パソコン")のドメインとして、別の二つ目の引数は、全てに無い(同一のエラー)。
解決
ああ...私はWinAPIの相互運用プログラミングの最大の落とし穴の一つによってキャッチされてきたlikerようです。また、私の関数宣言のコードを投稿すること、この場合には賢明されていると思います。
とにかく、私が行うために必要なことすべてはCharSet = CharSet.Unicode
を指定する機能のDLLIMPORT属性に引数を追加しました。これはCreateProcessWithLogonW
とCreateProcessWithTokenW
機能の両方のためのトリックを行いました。私はそれが最終的にだけで関数名のWサフィックスがUnicodeに言及することを私を襲ったと私は明示的にC#でこれを指定する必要があると思います!ここではの正しいの誰もが興味を持っている場合は、関数の宣言ます:
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CreateProcessWithLogonW(string principal, string authority,
string password, LogonFlags logonFlags, string appName, string cmdLine,
CreationFlags creationFlags, IntPtr environmentBlock, string currentDirectory,
ref STARTUPINFO startupInfo, out PROCESS_INFORMATION processInfo);
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CreateProcessWithTokenW(IntPtr hToken, LogonFlags dwLogonFlags,
string lpApplicationName, string lpCommandLine, CreationFlags dwCreationFlags,
IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
他のヒント
からここをます:
コール一般的に、プロセス CreateProcessAsUser関数を持っている必要があります SE_ASSIGNPRIMARYTOKEN_NAMEと SE_INCREASE_QUOTA_NAME特権。もし この関数は失敗すると ERROR_PRIVILEGE_NOT_HELD(1314)、使用 CreateProcessWithLogonW機能 代わりに。 CreateProcessWithLogonW 特別な権限を必要としませんが、 指定されたユーザーアカウントがなければなりません 対話的にログオンすることができました。 一般的に、それを使用するのが最適です 作成するCreateProcessWithLogonW 代替の資格情報とプロセスます。
このブログの記事<のhref = "http://blogs.msdn.com/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx" のrel =を参照してください。 "noreferrer"> .NET の
でCreateProcessWithLogonW&CreateProcessAsUserを呼び出す方法ジョナサン・ペッパーズ
私の問題を修正したコードのこの素晴らしい作品を提供<のhref = "http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/0c0ca087-5e7b-4046-93cb-c7b3e48d0dfb?ppud=4" のrel = "nofollowをnoreferrer" > http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/0c0ca087-5e7b-4046-93cb-c7b3e48d0dfb?ppud=4 の