17

CreateProcessAsUser()を使用してスクリプトと実行可能ファイルを実行することにより、いくつかの自動化タスクを処理するサードパーティのWindowsサービスを使用しています。UACと、APIを介したLUAの昇格の処理方法が原因で、WindowsServer2008で問題が発生しています。

このサービスはLocalSystemとして実行され、「デスクトップとの対話」が有効になっていません。プロセスはAdministratorsグループのユーザーとして実行されていますが、Administratorアカウント(多くのUAC制限から免除されています)では実行されていません。すべてのUACデフォルト設定が設定されています。

任意のコマンドまたはPowerShellコードをサービスに渡すことはできますが、サービスによって開始される、昇格されていない非対話型のプロセスから「抜け出す」ことができないようです。

問題の核心は、昇格されたプロセスを開始するための唯一の(パブリック)APIオプションが'runas'動詞を持つShellExecute()であるようですが、私が知る限り、非対話型から呼び出すことはできませんサービスを実行しないか、「この操作にはインタラクティブウィンドウステーションが必要です」などのエラーが発生します。

私が見つけた唯一の回避策はここに記載されています: http ://www.eggheadcafe.com/software/aspnet/29620442/how-to-proper-use-sendinp.aspx

Vistaでは、プロセスを昇格させるための公式に文書化された方法は、シェルAPI ShellExecute(Ex)のみを使用することです(CreateProcessまたはCreateProcessAsUserではありません)。したがって、アプリケーションはShellExecute(Ex)を呼び出して、SendInputを呼び出すために昇格されたヘルパーを起動する必要があります。さらに、セッション0の分離により、サービスはCreateProcessAsUserまたはCreateProcessWithLogonW(ShellExecute(Ex)は使用できません)のみを使用してインタラクティブデスクトップを指定できます。

..Windowsサービスから昇格されたプロセスを生成する直接的な方法はないと思います。最初にCreateProcessAsUserまたはCreateProcessWithLogonWを使用して、昇格されていないプロセスをユーザーセッション(インタラクティブデスクトップ)に生成することしかできません。次に、昇格されていないプロセスで、ShellExecute(Ex)を使用して、実際のタスクの昇格されたプロセスを生成する場合があります。

.net / powershellコードからこれを行うには、.Net System.Diagnostics.ProcessStartInfoに同等のlpDesktopがないため、CreateProcessAsUserまたはCreateProcessWithLogonWを呼び出すために複雑なP/Invokeを実行する必要があるようです。 「winsta0\default」に設定します。また、LocalSystemにCreateProcessAsUserまたはCreateProcessWithLogonWを呼び出す権限があるかどうかもわかりません。

また、 http://blogs.msdn.com/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx と Processを確認しました。

これらすべてに基づいて、これを行う簡単な方法はないという結論に達しました。私は何かが足りないのですか?これは本当に難しいことではないようです。UACは、非対話型のユースケースを処理するように設計されたことがないように感じます。

そして、Microsoftの人がこれを読んでしまった場合、ShellExecuteが内部で昇格を処理する方法は、Application Information Service(AIS)を呼び出すことであることに気付きました。Win32または.NETAPIを介してAISへの同じ呼び出しを利用できないのはなぜですか? http://msdn.microsoft.com/en-us/library/bb756945.aspx

少し時間がかかってすみません。アイデアをありがとう。

4

2 に答える 2

19

セッションゼロの分離を解除する「公式」の方法は、ターミナルサービスAPIの組み合わせを使用しCreateProcessAsUser()、ユーザーのセッション内でプロセスを起動することです。私の以前の仕事では、ダウンロードした更新プログラムをインストールする前にサービスからユーザーにダイアログを表示する必要があったので、それを実行しました。したがって、少なくともWinXP、Win2K3、Vista、およびWin7で機能することはわかっていますが、私はWin2K8の違いが大きすぎるとは思わないでください。基本的に、プロセスは次のようになります。

  1. アクティブなコンソールセッションIDを取得するために呼び出します(クライアントシステムであってもWTSGetActiveConsoleSessionId()、インタラクティブセッションは常にセッション1であるとは限らないため、非常に重要です)。このAPIは、インタラクティブセッションにログインしているアクティブなユーザーがいない場合(つまり、RDPを使用するのではなく、物理マシンにローカルでログインしている場合)にも-1を返します。
  2. 前のAPI呼び出しからのセッションIDをにWTSQueryUserToken()渡して、コンソールにログインしたユーザーを表すオープントークンを取得します。
  3. DuplicateTokenEx()偽装トークン(からWTSQueryUserToken)をプライマリトークンに変換するために呼び出します。
  4. プロセスの新しい環境を作成するために呼び出しCreateEnvironmentBlock()ます(オプションですが、そうでない場合、プロセスには環境がありません)。
  5. CreateProccessAsUser()手順3のプライマリトークンを、実行可能ファイルのコマンドラインとともにへの呼び出しに渡します。手順4で環境ブロックを作成した場合は、CREATE_UNICODE_ENVIRONMENTフラグも(常に)渡す必要があります。これはばかげているように見えるかもしれませんが、そうでない場合(with ERROR_INVALID_PARAMTER)、APIはひどく失敗します。
  6. 環境ブロックを作成した場合は、を呼び出す必要がありますDestroyEnvironmentBlock。そうしないと、メモリリークが発生します。プロセスは、起動時に環境ブロックの個別のコピーを与えられるため、ローカルデータのみを破棄します。

そして出来上がり!Windowsはいくつかの内部魔法を実行し、アプリケーションが起動するのがわかります。ただし、これによりサービスからインタラクティブなプロセスが起動しますが、UACをバイパスするかどうかはわかりません(ただし、それについては引用しないでください)。つまり、レジストリまたは内部マニフェストで指定されていない限り、昇格されたプロセスとして起動されない可能性があります。その場合でも、UACプロンプトが表示される可能性があります。手順3で取得したトークンが制限付きトークンである場合はAdjustTokenPrivileges()、昇格された(完全な)トークンを復元するために使用できる可能性がありますが、それについても引用しないでください。ただし、MSDNのドキュメントに記載されているように、まだ特権を持っていないトークンに特権を「追加」することはできないことに注意してください(たとえば、AdjustTokenPrivileges;を使用して制限付きユーザートークンを管理者に変えることはできません。

Win2K以降、これをすべて行うことは技術的に可能です。ただし、Win2Kには( Win2K Proと同様に)WTSGetActiveConsoleSessionId()APIWTSQueryUserToken()がないため、実際にはWinXPからのみ実行可能です。WTSEnumerateProcesses()セッションIDとして0をハードコーディングすることができ(Win2Kでは常にそうであるため)、実行中のプロセスを列挙し、それらのトークンの1つを複製することでユーザートークンを取得できる可能性があります(インタラクティブSIDが存在します)。いずれにせよ、CreateProcessAsUser()サービス設定から[デスクトップとの対話]を選択しなくても、対話型ユーザートークンが渡された場合は同じように動作します。LocalSystemまた、プロセスは敬虔なアクセストークンを継承しないため、サービスから直接起動するよりも安全です。

さて、あなたのサードパーティのアプリがスクリプト/プロセスを実行するときにこれを行うかどうかはわかりませんが、サービスからそれを行いたい場合は、それが方法です(そして、VistaまたはWin7では、それが唯一の方法ですセッション0の分離を克服します)。

于 2010-09-04T05:09:49.083 に答える
1

ユースケースに応じて、私がしていることを行うことができます。アクティブなセッションの winlogon プロセスを探し出し、そのトークンを盗みます。アクティブなセッションがない場合 (API が -1 を返した場合)、WINVER >= 6 の場合は 1 を使用し、それ以外の場合は 0 を使用します。これにより、アクティブなセッションで SYSTEM が発生します。

于 2013-07-03T19:05:44.770 に答える