Saturday, April 30, 2011

WinDbg: CreateProcessAsUser 回傳 ACCESS_DENIED 之案例分析

最近手邊處理了一個案例。因為一些特殊需求,想要試試看在 Administrator 帳號下,呼叫 CreateProcessAsUser 建立在別的 Logon Session 的進程。這並不是一個典型的應用。你可以照著 MSDN 上的說明處理,幫 Administrator 加上需要的權限,看起來可以在 Console Session 上正常運作。

事情沒那麼簡單,在 Windows Server 2003 下面,CreateProcessAsUser 沒辦法在 Terminal Service 的 Logon Session 下面建立進程,永遠會得到一個 ACCESS_DENIED (5) 的錯誤碼。不過,MSDN 並沒有描述這個錯誤碼的原因。

看來,要有把手弄髒的心理準備。

首先,嘗試用 WinDbg 逐步執行看看是哪裡丟出了這個錯誤碼。結果發現,CreateProcessAsUser 裡面最終會用 CreateFile 去開一個 Terminal Server 的 Named Pipe,這個地方是讓 CreateProcessAsUser 呼叫失敗的點。

0:000> kvn
 # ChildEBP RetAddr  Args to Child              
00 002cce10 00525227 002cee90 c0000000 00000000 kernel32!CreateFileW (FPO: [Non-Fpo])
01 002ceef4 00515fd4 00000001 00000000 000003bc ADVAPI32!CreateRemoteSessionProcessW+0xbd (FPO: [Non-Fpo])
02 002cef44 0040433c 000003bc 00000000 002cf1a8 ADVAPI32!CreateProcessAsUserW+0xb0 (FPO: [Non-Fpo])

0:000> du 002cee90 
002cee90  "\\.\Pipe\TerminalServer\ozUBFyty"
002ceed0  "9LQoprqROq\1"

看來問題似乎是 Administrator 並沒有權限去讀寫這個 Named Pipe,於是乎,接下來的方向轉為確認這個 Name Piped 的 Security Context。

C:\>PsExec.exe -s c:\accesschk.exe \Pipe\TerminalServer\ozUBFyty9LQoprqROq\1

\\.\Pipe\TerminalServer\ozUBFyty9LQoprqROq\1
  RW NT AUTHORITY\SYSTEM
  RW NT AUTHORITY\LOCAL SERVICE
  RW NT AUTHORITY\NETWORK SERVICE
c:\accesschk.exe exited on 6BD2PFN1Z with error code 0.

結果發現 Administrator 果然不行開 Named Pipe。只有System、Local Service、和 Network Service 這幾個帳戶才有能力讀寫這個 Named Pipe。

在 Windows Server 2003 有 Terminal Service 的 System 帳戶下,呼叫 CreateProcessAsUser 在別的 Remote Logon Session 建立新進程,會發現新進程的 Parent Process 並不是我們自己的 Caller Process,而是 Winlogon.exe 這個系統進程。

這裡可以做個猜測,這個 Named Pipe 的作用就是讓 Caller Process 可以送出建立新進程的指令給 Winlogon.exe。打開 Process Explorer,確認一下果然發現 Named Pipe 是由 Winlogon.exe 所建立。


追到這邊,大概心裡有數了。在 Windows 2003 Server 上面,CreateProcessAsUser 是沒辦法跑在非系統內建的幾個重要帳戶裡面。Winlogon.exe 已經限制了 Named Pipe 的讀寫權限,若是沒有符合的帳戶,就是沒有辦法執行 CreateProcessAsUSer。

結論:好奇心除了可以殺死一隻貓,也可以殺掉你寶貴的時間。:P

[Updated]

  • CodeProject 裡有個小工具 RunAsEx,你可以用它來調整各種組合,實驗看看各種不同情境下的 CreateProcessAsUser,可以很方便的達到 PoC 的效果。

No comments: