9

XP-64 と W2K3 では正常に動作するレガシー Windows サーバー サービスと (生成された) アプリケーションがありますが、W2K8 では失敗します。これは、新しい「セッション 0 分離」機能によるものだと思います。

そのため、Windows 2008 Server の Windows サービスから新しいプロセスを作成して、以前の動作を復元 (さらにはそれを上回る) できるようにするコード サンプル/セキュリティ設定モジョを探しています。次のようなソリューションが必要です。

  1. セッション 0 分離制限 (セッション 0 からグラフィックス ハードウェアへのアクセスなし) を回避するために、ゼロ以外のセッションで新しいプロセスを作成します。これに関する公式の MS 行は次のとおりです。

セッション 0 はユーザー セッションではないため、セッション 0 で実行されているサービスはビデオ ドライバーにアクセスできません。これは、サービスがグラフィックをレンダリングしようとしても失敗することを意味します。セッション 0 でディスプレイの解像度と色深度を照会すると、最大 1920x1200 で 32 ビット/ピクセルのシステムの正しい結果が報告されます。

  1. 新しいプロセスは、Windows DC の作成に使用できる Windows ステーション/デスクトップ (例: winsta0/default) を取得します。ここでこれに対する解決策(インタラクティブセッションで問題なく起動する)を見つけました:C++でのインタラクティブクライアントプロセスの開始

  2. Windows DC は、 OpenGL DescribePixelFormat 列挙型の基礎として使用される場合、ハードウェア アクセラレーション形式を見つけて使用できます (OpenGL ハードウェアが適切に装備されたシステム上)。ただし、ターミナル サービス セッションが実行されている場合を除きます (VNC は正常に動作します)。また、プロセスが動作するようにする (つまり、ターミナル サービス セッションが開いている場合でも OpenGL ハードウェア アクセラレーションを使用して実行する) ソリューションは、必須ではありませんが、非常に優れています。

私は現在、アイテム#1で立ち往生しています。これについて議論する同様の投稿がいくつかありますが(これ、およびこれなど)、ユーザーセッションがすでにログインして「取る」という保証がないため、適切な解決策ではありませんセッションIDから、また私はLocalSystemアカウントから実行していません(サービスのドメインアカウントから実行しているため、理由の範囲内で特権を調整できますが、優先度をエスカレートして含める必要はありませんSeTcbPrivileges.)

たとえば、これは機能すると思われるスタブですが、SetTokenInformation 呼び出しで常にエラー 1314 を返します (AdjustTokenPrivileges がエラーを返さなかったとしても)。プロセス トークン)、しかし、セッション ID を交換できないようです。

また、すべての場合 (たとえば、対話型のユーザーがログインしていない場合) で WTSActiveConsoleSessionId を使用することについても疑問がありますが、セッションがログインしていない状態で実行されているサービスの簡単なテストでは、適切なセッション値 (1) が返されたようです。

読みやすくするためにエラー処理を削除しました (まだ少し面倒です - 申し訳ありません)。

    //Also tried using LogonUser(..) here
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
                         | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID
                         | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY
                         | TOKEN_DUPLICATE, &hToken)

GetTokenInformation( hToken, TokenSessionId, &logonSessionId, sizeof(DWORD), &dwTokenLength )

DWORD consoleSessionId = WTSGetActiveConsoleSessionId();

/* Can't use this - requires very elevated privileges (LOCAL only, SeTcbPrivileges as well)   
   if( !WTSQueryUserToken(consoleSessionId, &hToken))
...
   */

DuplicateTokenEx(hToken, (TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE), NULL, SecurityIdentification, TokenPrimary, &hDupToken))


    // Look up the LUID for the TCB Name privilege.
LookupPrivilegeValue(NULL, SE_TCB_NAME, &tp.Privileges[0].Luid))

    // Enable the TCB Name privilege in the token.
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (!AdjustTokenPrivileges(hDupToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, 0))
    {
        DisplayError("AdjustTokenPrivileges");
           ...
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        DEBUG( "Token does not have the necessary privilege.\n");
    } else {
        DEBUG( "No error reported from AdjustTokenPrivileges!\n");
    }                                                                                                                                                                                        // Never errors here

   DEBUG(LM_INFO, "Attempting setting of sessionId to: %d\n", consoleSessionId );

   if (!SetTokenInformation(hDupToken, TokenSessionId, &consoleSessionId, sizeof(DWORD)))
           *** ALWAYS FAILS WITH 1314 HERE ***

SetTokenInformation 呼び出しまで、すべてのデバッグ出力は正常に見えます。セッション 0 が現在のプロセス セッションであることがわかります。私の場合は、セッション 1 (WTSGetActiveConsoleSessionId の結果) を設定しようとしています。(RDCではなくVNC経由でW2K8ボックスにログインしていることに注意してください)

だから - 質問:

  1. このアプローチは有効ですか、それともサービスによって開始されたすべてのプロセスが意図的にセッション 0 に制限されていますか?
  2. より良いアプローチはありますか (「ログオン時に起動」とサーバーの自動ログオンを除く)。
  3. このコードに何か問題がありますか、またはセッション ID を交換して新しいセッションでプロセスを生成したいことを示すことができるプロセス トークンを作成する別の方法はありますか? OpenProcessToken の代わりに LogonUser を使用してみましたが、それもうまくいきませんでした。(この時点で、生成されたすべてのプロセスがゼロ以外の同じセッションを共有しているかどうかは気にしません。)

どんな助けでも大歓迎です-ありがとう!

4

3 に答える 3

9

この問題の解決に関心のある方へ:

LogonSDK チームの MS サポートとこの問題について話し合いました。インタラクティブなユーザーをプログラムで完全に偽装して、物理コンソールと関連する GDI コンストラクトを取得することはできないようです。基本的に、これが機能していたのは「ただの幸運」でした。彼らは、セッション 0 の分離が回帰の根本原因であることを確認しました。

彼らの推奨事項は、対話型セッションへの自動ログオンを有効にし、対話型セッションで新しいクライアント コンポーネントと通信するようにサービスをリファクタリングすることです。このセキュリティ上の欠点に対処するために、ログオン時にサーバーを「キオスク」モードにするシェルの置き換えを実装することを推奨しています (たとえば、適切な資格情報がないと Explorer にアクセスできないなど)。

良い面としては、これにより、ハードウェア アクセラレーションが無効になるターミナル サービス セッションで発生していた問題が解決されるはずです。

私は、将来のリリースで「プロキシ ユーザー セッション」をサポートするために、この種の「レンダー ファーム」ユース ケースを検討するよう MS に要求を提出します。これにより、サーバーは、既存のクライアント ユーザー プロセスを必要とするというセキュリティ上の妥協なしに、ハードウェア アクセラレーション プロセスを生成できます。コンソールでログオンします。

于 2010-03-18T23:17:16.487 に答える
0

トレーニング コースを完了していませんが、Microsoft-MSDN サイトで「セッション 0 分離の回避策」のチュートリアルを見つけました。

http://msdn.microsoft.com/en-us/windows7trainingcourse_sessionisolation_unit.aspx

スケジュールされたタスク内で明らかになった同じセッション 0 分離の問題があります。

于 2013-05-01T14:30:17.897 に答える