2009年4月22日 星期三

[文章] 深入探討 Vista User Account Control 的文章

Vista 引進了比較嚴謹的程式存取限制, 這導致在 Vista 下的使用者必須強迫使用 “管理者身份” 執行我的程式.

我不希望這樣, 所以就有了下面的文章.

 

本文內容包含

     1. Kenny Kerr 的文章: UAC 原理 (重點整理)

          * 系統提醒使用者是否需要系統管理者權限執行的流程

          * 如果不論程式的相容性與 manifest 如何,
              我就是要 elevation 我的程式, 該怎麼做?

          * 如何知道我現在的執行權限是不是 elevation?

     2. Understanding and Working in Protected Mode Internet Explorer
          重點整理

           * 如何知道目前我的程式是否處於 IE 的 Protected Mode?

           * 那檢測結果確實發現我的 ocx 在 IE 的 Protected Mode 下,
               那我該怎麼存取我的設定檔?

           * 可是我就是要把資料存到 User Profile 怎麼辦?

           *  Michael Dunn 提供的程式範例 [3]

 

開始!

snap003 Kenny Kerr 先生在 2006 年9 月發表了一篇有關 Vista User Account Control 的精彩文章.

 Windows Vista for Developers – Part 4 – User Account Control  

內容包含

  1. 介紹如何使用 CreateRestrictedToken 建立一個 Token
  2. 詳細解說 Vista 新功能 User Account Control 對程式的影響與運作機制
  3. 介紹如何建立一個 Token, 使得擁有該 token 的程式不能 restart, sleep, shutdown 你的電腦

             * 利用剛剛建立的 token 讓你的電腦完全不能關機

                (藉由修改 Explore.exe 的執行權限)

             如何讓公共的電腦限制執行權限 ? 我想答案應該在這裡吧.

    4. 你可以指定 child process 的 integrity levels (我翻譯成執行層級, 比較好理解)

      5. 他提供了一個例子, 讓 notepad.exe 只能開檔但是不能存檔.

VERIFY(::CreateProcessAsUser(duplicateToken,
                             L"C:\\Windows\\Notepad.exe",
                             0, // cmd line
                             0, // process attributes
                             0, // thread attributes
                             FALSE, // don't inherit handles
                             0, // flags
                             0, // inherit environment
                             0, // inherit current directory
                             &startupInfo,
                             &processInfo));

 

其他的重點摘要:

* 一般程式執行層級是 Medium, 而經過使用者允許過後的程式 token 執行層級是 High. 注意: IE 的 token 執行層級是 Low

* 你可以用 Mark 先生發表的軟体 Process Explorer 中, 看到每個 process 

    的執行權限層級 (開啟 integrity level 選項).

(Process Explorer 的執行狀況圖)

* 我們可以用 GetTokenInformation 得知目前 process 的 integrity level (順便驗證一下你的 ocx 在 IE 7 下的 integrity level是不是 Low)

 

 

系統提醒使用者是否需要系統管理者權限執行的流程

     Step 1:  當使用者點選需要系統管理需求的程式執行時

     Step 2: ShellExecute 呼叫 CreateProcess 建立新的 process, 隨後

                    CreateProcess 接手檢查這個 process 的相容性等工作

    Step 3: 若發現需要 elevation(系統管理者權限), 而呼叫的人沒有elevation

                   則 CreateProcess 回傳 ERROR_ELEVATION_REQUIRED

     Step 4: ShellExecute 發現這種狀況, 則交給 Application Information

                     Service 處理顯示提示視窗, 並且執行該需要 elevation 的程式.

 

 

如果不論程式的相容性與 manifest 如何, 我就要 elevation 我的程式的作法

<sol>  使用 runas 指令  (XP 就有這個指令了)

範例:

::ShellExecute(0, // owner window
               L"runas",
               L"C:\\Windows\\Notepad.exe",
               0, // params
               0, // directory
               SW_SHOWNORMAL);

 

 

 

如何知道我現在的執行權限是不是 elevation?

<sol>  呼叫 IsUserAnAdmin  即可

 

 

 

另外下面是 “Understanding and Working in Protected Mode Internet Explorer” [2]  的重點整理

1. 如何知道目前我的程式是否處於 IE 的 Protected Mode?

<sol> 呼叫  IEIsProtectedModeProcess

 

那檢測結果確實發現我的 ocx 在 IE 的 Protected Mode 下, 那我該怎麼存取我的設定檔? (LocalLow)

<sol> 當你程式被執行在 IE Protected Mode (low integrity level), 那麼你的 ocx 可以寫入 %userprofile%\AppData\LocalLow 目錄下面. 利用 SHGetKnownFolderPath 搭配 FOLDERID_LocalAppDataLow 可以取得這個目錄的位置.  (注意: 這段是 Vista 相關, 所以你的 ocx 必須要判斷作業系統而決定呼叫)

程式碼範例:

SHGetKnownFolderPath(FOLDERID_LocalAppDataLow, 0, 
NULL, szPath, ARRAYSIZE(szPath));

 


我們可以用上面的知識, 得知 low integrity level 的 process 可以自由存取放在  LocalLow 中的內容.


可是我就是要把資料存到 User Profile 怎麼辦?


<sol> 這個情況大多是你的 ocx 紀錄使用者設定檔資料.


        詳細的作法如下 (3 steps): 會跳出視窗提醒使用者


        Step 1: 先在 LocalLow 裡面建立你的設定檔
                      (用 IEGetWriteableFolderPath )


        Step 2: 呼叫 IEShowSaveFileDialog, 這個 function 是用 medium


                        integrity context 中執行, 會提醒使用者我們要存東西到其


                        他目錄.


        Step 3: 然後用 IESaveFile 把你的檔案放過去.


 


 Michal Dunn 文章 [3] 在他的文章也列出使用範例


// Step 1:  取出 Protected Mode 情況下可以存取的目錄
                     先把東西存過去

LPWSTR pwszCacheDir = NULL;// 暫存空間目錄
TCHAR szTempFile[MAX_PATH] = {0};//暫存空間中完整檔案路徑
hr = IEGetWriteableFolderPath (FOLDERID_InternetCache,
&pwszCacheDir );
if(S_OK !=hr) return FALSE;
// 在 cache 目錄中建立暫存檔, 放我們的設定檔
GetTempFileName ( CW2CT(pwszCacheDir), _T("bob"),
0, szTempFile );
CoTaskMemFree ( pwszCacheDir );
// 然後存檔到暫存空間 (szTempFile) …
 
// Step 2: 跳出視窗, 由使用者選擇目標目錄. 
HRESULT hr;
HANDLE hState;
LPWSTR pwszSelectedFilename = NULL;
const DWORD dwSaveFlags =
OFN_ENABLESIZING | OFN_HIDEREADONLY |
OFN_PATHMUSTEXIST |OFN_OVERWRITEPROMPT;


hr = IEShowSaveFileDialog (
m_hWnd, L"Saved log.txt", NULL,
L"Text files|*.txt|All files|*.*|",
L"txt", 1, dwSaveFlags, &pwszSelectedFilename,
&hState );

if ( S_OK != hr )
MessageBox(_T("IEShowSaveFileDialog 出問題”));

 


// Step 3:  最後用 IESave 存到目標目錄

hr = IESaveFile ( hState, T2CW(szTempFile) );
if(S_OK!=hr)
IECancelSaveFile ( hState );//出問題,取消存檔
else
DeleteFile ( szTempFile ); // 清除在 cache 中的暫存檔
 
如果我的 ocx 會呼叫其他執行檔工作, 該怎麼辦?
<sol> 告訴 IE 你要執行的 EXE 是可以信任的並且不要彈出視窗.
作法是: 在 
HKLM\Software\Microsoft\Internet Explorer\Low Rights\ElevationPolicy
下面, 建立一個新的 key. 並且包含 3 項資料.
AppName: 你的執行檔名稱. (例如: abc.exe)
AppPath: 執行檔位置
Policy: 這裡設定為 3
 
 
 

其他細節, 請參考延伸閱讀中他們的文章.


by Jing.


 


 


延伸閱讀


[1] M. Russinovich, “Inside Windows Vista User Account Control, “ http://technet.microsoft.com/en-us/magazine/2007.06.uac.aspx, 2007,7.


[2] M. Silbey and P. Brundrett, “Understanding and Working in Protected Mode Internet Explorer, “ http://msdn.microsoft.com/en-us/library/bb250462.aspx#wpm_fliwl,  2009, 2.


[3] M. Dunn, “A Developer's Survival Guide to IE Protected Mode, “ http://www.codeproject.com/KB/vista-security/PMSurvivalGuide.aspx, 2007, 5.

1 則留言:

  1. 版大您好~
    請教如何開啟 integrity level 選項呢?
    是select columns->process Image-> integrity level 這個選項嗎???

    但不知為何~ 這選項被disable(它是灰色的)不能勾選!!
    或是有其他方式開啟integrity level
    懇請不吝賜教! 謝謝

    回覆刪除