天天看點

PassUAC的簡單實作(二)

四、通過管理者建立程序的流程

在第一篇中大緻了解了每一個程序都有一個權限之後,這裡簡單了解一下管理者程序的建立。

​​https://github.com/xyddnljydd/PassUAC​​

首先來感受一下程序的建立步驟:

1、右鍵管理者啟動一個程序

PassUAC的簡單實作(二)

2、會彈出一個對話框,詢問使用者是否要以管理者的身份打開程序

PassUAC的簡單實作(二)

3、當點選是之後會打開一個管理者身份建立的程序,點選否則什麼也沒有發生一樣,且程序樹也是挂載explore下面的

PassUAC的簡單實作(二)

4、實際真的是這麼簡單的嗎?explore建立一個彈窗,詢問使用者是否要建立程序,得到使用者的許可之後建立管理者身份的程序?這裡要既然要做驗證可以直接附加到explore程序上面去,對ntdll!NtCreateUserProcess下一個斷點就行了。

PassUAC的簡單實作(二)

5、可以發現這個彈窗出來了,但是沒有斷下,說明建立這個對話框的程序并不是explore,那是什麼程序?

PassUAC的簡單實作(二)

6、最簡單的當時寫一個程序回調的驅動,看一下是誰建立的,但是有的兄弟對驅動開發不是很了解,是以這裡利用ProcMon來監控一下,”犯人“是誰?從下圖中可以看到是svchost程序啟動了consent程序,從程序的描述大緻也能知道就是用來畫界面的。

PassUAC的簡單實作(二)

7、現在知道了是svchost建立的,但是這個是系統的服務我們該如何去分析這個東西,這裡在拓展一些知識,不知道小夥伴有沒有寫過服務程式,就是用scm系列的api注冊一個服務,然後啟動,可以選擇開機啟動還是手動啟動。其中有一些服務叫做共享服務,這類服務通常是dll,而加載這些服務的就是svchost程序。

PassUAC的簡單實作(二)

8、那麼從上述描述中我們知道了Svchost就是彈出對話框的那個程序,其中Svchost中的某個服務完成了上面的操作,那麼直接附加到該程序,下斷點就能知道到底是那個dll在處理這些流程,從下面的棧中得到了兩個有用的資訊。

1)處理UAC事件的服務是appinfo這個共享程序(這裡面有很多細節,沒有說,比如對話框它等待多久之後會消失,哪些白名單不彈框之類的,感興趣可以自己去看一下)

2)appinfo服務是通過RPC接收和發送事件的(其實是ALPC,但是ALPC是RPC的子類)

PassUAC的簡單實作(二)

9、那麼思路也逐漸清晰起來,當使用者右鍵管理者建立程序的時候,explore會發送一個RPC事件給appinfo這個服務程序,當appinfo收到這個事件之後會建立一個對話框詢問是否真的要建立一個程序,當使用者點選是之後,才将程序真正的建立起來,下圖是函數第二次斷下的時候,可以看到,在我點選是之後appinfo以管理身份建立了KmdManager程序

PassUAC的簡單實作(二)

10、既然能夠通過RPC的方式發送請求,那麼我們是否可以不通過explore,直接給appinfo發消息,建立程序,當然是可以的,這塊隻需要定義函數的原型,将它寫入到一個idl檔案和acf檔案,就能直接使用了,查找函數原型和idl的定義在之前寫的檔案替換漏洞有說明,這裡就不在贅述了,定義的idl檔案如下

[
  uuid(201ef99a-7fa0-444c-9399-19ba84f12a1a),
  version(1.0),
]
interface boo
{

  typedef struct _MONITOR_POINT {
    long MonitorLeft;
    long MonitorRight;
  } MONITOR_POINT;

  typedef struct _APP_STARTUP_INFO {
    wchar_t* lpszTitle;
    long dwX;
    long dwY;
    long dwXSize;
    long dwYSize;
    long dwXCountChars;
    long dwYCountChars;
    long dwFillAttribute;
    long dwFlags;
    short wShowWindow;
    struct _MONITOR_POINT MonitorPoint;
  } APP_STARTUP_INFO;

  typedef struct _APP_PROCESS_INFORMATION {
    unsigned __int3264 ProcessHandle;
    unsigned __int3264 ThreadHandle;
    long  ProcessId;
    long  ThreadId;
  } APP_PROCESS_INFORMATION;

  long RAiLaunchAdminProcess(
    handle_t hBinding,
    [in][unique][string] wchar_t* ExecutablePath,
    [in][unique][string] wchar_t* CommandLine,
    [in]long StartFlags,
    [in]long CreationFlags,
    [in][string] wchar_t* CurrentDirectory,
    [in][string] wchar_t* WindowStation,
    [in]struct _APP_STARTUP_INFO* StartupInfo,
    [in]unsigned __int3264 hWnd,
    [in]long Timeout,
    [out]struct _APP_PROCESS_INFORMATION* ProcessInformation,
    [out]long* ElevationType);

}      

11、接口的定義處理好之後來看一看我們感興趣的參數,其實就是第三個參數StartFlags,這個标志位代表是按照管理者方式啟動一個程序還是非管理者,0是非管理者。

PassUAC的簡單實作(二)

12、好了這裡我們直接把flag改為1,啟動程序試試看,會發現還是有UAC的彈窗出現,置為0雖然能建立程序,但是是一個非管理者權限的程序,也沒有什麼用(想要嘗試的話,隻想要把github上的代碼拉下來調用對應的AicLaunchAdminProcess函數就行)

PassUAC的簡單實作(二)