天天看點

MFC管理者權限(UAC下的程式權限提升)

原創文章,轉載請注明: 轉載自C/C++程式員之家

本文連結位址: MFC管理者權限(UAC下的程式權限提升)

UAC是微軟為了提高Windows的安全性,自Windows Vista開始引入的新安全機制。

傳統的NT核心系統依靠access token來做權限處理,access token由目前使用者所在的使用者組的權限決定。而由于長期以來的不當使用習慣問題,幾乎所有Windows上使用者所在的組都是管理者。

在啟用UAC之後,系統會額外引入一個filtered token,并且這個token預設隻能按照Standard User的權限去執行。是以這個token也通常被叫做limited filtered token。

PS:關于上面的簡單介紹,請參考這裡

因為執行權限有限,某些操作必然會要求更高的管理者權限。此時,通常就需要一個privilegs elevation的操作。程式可以向系統請求提權,系統會将此請求通過提一個提示框,請使用者确認。

這裡多說一點,如果目前使用者的使用者組權限不是管理者,提權操作是要求輸入管理者密碼的,這點和在Linux中的相應操作類似。不過我想大部分人的使用者組都是管理者,是以這句話當我沒說好了…

另外需要注意的一點是,這個elevation是受到一個process-boundary的限制的,具體展現在兩方面:

  1. 程式隻能在運作前要求提權。如果已經在運作了,那麼将失去申請提權的能力
  2. 權限提升僅對此次程序有效

不過,一個具有full administrator token的程序利用CreateProcess建立的程序預設都繼承了full administrator token。

提升權限的操作大緻有兩個:

  1. 自動提權請求
  2. 手動提權請求

自動提權請求

如果你的程式始終要求以full administrator token的模式運作,那麼應該考慮在程式啟動時自動向系統請求提權。

需要做的事情很簡單,隻需要更改程式的manifest檔案。這個檔案本質上是一個XML檔案,預設情況下,它的内容因該是:

01

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

02

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

03

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">

04

<security>

05

<requestedPrivileges>

06

<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>

07

</requestedPrivileges>

08

</security>

09

</trustInfo>

10

</assembly>

隻要将requestExecutionLevel的level的值改成requiredAdministrator,再重新将這個檔案連結入EXE即可。

另外,如果使用Visual Studio作為開發環境,直接在項目的屬性裡可以更改UAC的權限要求設定

MFC管理者權限(UAC下的程式權限提升)

UAC下的程式權限提升

手動提權請求

如果程序在運作途中需要full administrator token怎麼辦?

答案是,沒辦法。具體原因前面說了。

不過,一個具有limited filtered token的程序是可以運作一個程式,并且讓這個程式去請求系統提權。而且,我們可以讓這個程序去再一次運作自己的EXE檔案,并且請求提權。

這裡需要的API是ShellExecuteEx而不是根正苗紅的CreateProcess。因為後者沒有和UAC相關的屬性設定

ShellExecuteEx需要一個SHELLEXECUTEINFO結構,這個結構如下:

01

typedef

struct

_SHELLEXECUTEINFO {

02

DWORD

cbSize;

03

ULONG

fMask;

04

HWND

hwnd;

05

LPCTSTR

lpVerb;

06

LPCTSTR

lpFile;

07

LPCTSTR

lpParameters;

08

LPCTSTR

lpDirectory;

09

int

nShow;

10

HINSTANCE

hInstApp;

11

LPVOID

lpIDList;

12

LPCTSTR

lpClass;

13

HKEY

hkeyClass;

14

DWORD

dwHotKey;

15

union

{

16

HANDLE

hIcon;

17

HANDLE

hMonitor;

18

} DUMMYUNIONNAME;

19

HANDLE

hProcess;

20

} SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;

這裡我們需要關心大概隻有三個成員:lpVerb,lpFile和nShow

lpVerb必須被設定為runas;而lpFile是要運作可執行檔案的完整路徑;nShow控制視窗的顯示。

需要關注nShow是因為大部分初始化操作都将這個屬性預設初始化為0,很不巧的是,0對應的屬性是SW_HIDE。除非你不需要窗體,否則還是需要手動調教下這個成員。

通常來說,如果某個程式運作途中可以通過觸發,轉而使用full administrator token運作,那麼八成是利用這個API重新運作EXE檔案,再将原有的程式退出或者隐藏。

至于剩下的那兩成,表示不明白,不過我想可以請教傳說中的花大嬸。

Demo

自己手寫了一個Demo,程式預設以limited filtered token運作。單擊提權按鈕,向系統請求提權。

預設時是這樣:

MFC管理者權限(UAC下的程式權限提升)

MFC管理者運作

提升權限後是這樣:

MFC管理者權限(UAC下的程式權限提升)

MFC管理者運作

核心代碼是兩塊:

  1. 判斷目前程序是否已經提權. 這個通過判斷目前進