0

ANCI C と Windows API の使用:

Windows 7 サービス アプリケーション (セッション 0 で実行中) から関数CreateProcessAsUser(,,,)を呼び出して、ユーザーがセッション 1 にログインしたときにアプリケーションを起動しています。

これはうまくいきます。この方法でサービスによって起動された後にアプリケーションによって示されるすべての動作は、ユーザーが通常アクセスできるネットワークの場所 (つまり、アプリケーションがセッション 1 から起動されたかのように) が使用できなくなることを除いて、正常です

だから私の質問は:

  1. セッション 1 にログインしたユーザーのトークンを正しく複製した場合、このトークンを使用してアプリケーションを起動すると、そのユーザーが通常アクセスできるネットワーク上の場所にあるデータにアクセスできないのはなぜですか?

  2. CreateProcessAsUser 関数の使用に加えて、ネットワークへのアクセスを復元するために欠けている追加の手順はありますか?

注: ソース コード内でユーザー資格情報を維持して渡す必要がないように、(CreateProcessWithLogonW などの他の選択肢ではなく) CreateProcessAsUser を特に選択しました。

助言がありますか?

セッション 1 ユーザーとして Windows サービスからアプリケーションを起動するために使用しているソース コードを次に示します。

BOOL LaunchAppIntoDifferentSession(char *AtsAppPathName) 
{
  PROCESS_INFORMATION pi;
  STARTUPINFO si;
  BOOL bResult = FALSE;
  DWORD dwSessionId;
  DWORD winlogonPid = 0;
  HANDLE hUserToken,hUserTokenDup,hPToken,hProcess;
  DWORD dwCreationFlags;

  // Log the client on to the local computer.
  dwSessionId = WTSGetActiveConsoleSessionId();

  // Find the winlogon process
  PROCESSENTRY32 procEntry;

  HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (hSnap == INVALID_HANDLE_VALUE)
  {
    return 1 ;
  }

  procEntry.dwSize = sizeof(PROCESSENTRY32);

  if (!Process32First(hSnap, &procEntry))
  {
    CloseHandle(hSnap);
    return 1 ;
  }

  do
  {
      if (stricmp(procEntry.szExeFile, "winlogon.exe") == 0)
      {
        // found a winlogon process...make sure it's running in the console session
        DWORD winlogonSessId = 0;
          if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId) && winlogonSessId == dwSessionId)
          {
            winlogonPid = procEntry.th32ProcessID;
            break;
          }
      }

  } while (Process32Next(hSnap, &procEntry));

  WTSQueryUserToken(dwSessionId,&hUserToken);
  dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE;
  ZeroMemory(&si, sizeof(STARTUPINFO));
  si.cb= sizeof(STARTUPINFO);
  si.lpDesktop = "winsta0\\default";
  ZeroMemory(&pi, sizeof(pi));
  TOKEN_PRIVILEGES tp;
  LUID luid;
  hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,winlogonPid);

  if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY
                                |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID
                                |TOKEN_READ|TOKEN_WRITE,&hPToken))
  {
    sprintf(gTempBuf, "Process token open Error: %u",GetLastError()); 
    if(LOG_ERR==1) WriteToLog("gTempBuf");

  }

  if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
  {
    sprintf(gTempBuf, "Lookup Privilege value Error: %u",GetLastError()); 
    if(LOG_ERR==1) WriteToLog("gTempBuf");
  }
  tp.PrivilegeCount =1;
  tp.Privileges[0].Luid =luid;
  tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;
  if(!DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityImpersonation,TokenPrimary,&hUserTokenDup))
  {
    sprintf(gTempBuf, "DuplicateTokenEx return Error: %u",GetLastError()); 
    if(LOG_ERR==1) WriteToLog("gTempBuf");
  }

  //Adjust Token privilege
  SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)dwSessionId,sizeof(DWORD));

  if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,NULL))
  {
    sprintf(gTempBuf, "Adjust Privilege value Error: %u",GetLastError()); 
    if(LOG_ERR==1) WriteToLog("gTempBuf");
  }

  if (GetLastError()== ERROR_NOT_ALL_ASSIGNED)
  {
    sprintf(gTempBuf, "Token does not have the privilege"); 
    if(LOG_ERR==1) WriteToLog("gTempBuf");
  }

  LPVOID pEnv =NULL;

  if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
  {
   dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
  }
  else
  pEnv=NULL;

  // Launch the process in the client's logon session.
  bResult = CreateProcessAsUser(
      hUserTokenDup,    // client's access token
      AtsAppPathName,   // file to execute
      NULL,             // command line
      NULL,             // pointer to process SECURITY_ATTRIBUTES
      NULL,             // pointer to thread SECURITY_ATTRIBUTES
      FALSE,            // handles are not inheritable
      dwCreationFlags,  // creation flags
      pEnv,             // pointer to new environment block 
      NULL,             // name of current directory 
      &si,              // pointer to STARTUPINFO structure
      &pi               // receives information about new process
   );
  // End impersonation of client.

  //Perform All the Close Handles task
  CloseHandle(hProcess);
  CloseHandle(hUserToken);
  CloseHandle(hUserTokenDup);
  CloseHandle(hPToken);
  CloseHandle(hSnap);

  //return iResultOfCreateProcessAsUser;
  return 0;
}  
4

2 に答える 2

0

マップされたドライブを使用してこれらのネットワークの場所にアクセスしていますか?

マップされたドライブは、ログイン セッションとともに保存されますユーザーのプロファイルが読み込まれていないため、 「マップされたドライブ」にアクセスできません。

代わりに完全な UNC パスを使用できます。

于 2014-01-01T19:04:21.880 に答える
0

問題は、管理 (昇格) トークンのコピーを取得していることです。デバッグ権限を有効にしているため、これはおそらく意図的なものです。残念ながら、ユーザーの昇格されたトークンはフィルター処理されたトークンと同じログオン セッションにないため、ユーザーのマップされたドライブはありません。

さまざまな回避策を含む詳細については、MSDN の記事「マップされたドライブからローカル ディレクトリへのファイルのコピーが失敗し、UAC が有効な場合、「場所が利用できません」というエラーが表示される」を参照してください。通常、最も簡単な解決策は、UNC パスを使用するか、必要に応じてドライブを再マップすることです。

于 2014-05-14T20:29:36.967 に答える