2016-02-12 55 views
3

我有一個Delphi應用程序,可以重新啓動某些Windows服務。模擬管理員重新啓動Windows服務

如果執行此應用程序的用戶具有管理權限(Administrators組的成員),則服務重新啓動將會成功。

對於普通用戶,服務重啓將失敗。

如果此普通用戶使用「右鍵單擊」以管理員身份運行,它也會成功。 但是,普通用戶必須輸入管理員用戶名和密碼。

我想爲普通用戶解決這個問題。

我的想法是在代碼中「模擬用戶」,顯然是模擬本地管理員帳戶。

但是,它仍然不起作用。

這裏是我的代碼:

function GetCurrUserName: string; 
var 
    Size    : DWORD; 
begin 
    Size := MAX_COMPUTERNAME_LENGTH + 1; 
    SetLength(Result, Size); 
    if GetUserName(PChar(Result), Size) then 
    SetLength(Result, Size) 
    else 
    Result := ''; 
end; 

function ConnectAs(const lpszUsername, lpszPassword: string): Boolean; 
var 
    hToken  : THandle; 
begin 
    Result := LogonUser(PChar(lpszUsername), nil, PChar(lpszPassword), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken); 
    if Result then 
    Result := ImpersonateLoggedOnUser(hToken) 
    else 
    RaiseLastOSError; 
end; 

我這樣稱呼它:

try 
    ConnectAs('Administrator','password'); 
except 
    on E: Exception do 
    Writeln(E.ClassName, ': ', E.Message); 
end; 

// Restart the Windows service 

// Done, back to the user 
RevertToSelf; 

服務重新啓動將失敗。如果用戶以管理員身份運行它(右鍵單擊RunAs),它就可以工作。

模擬本身工作正常。我可以通過獲取當前用戶名來檢查它。但是,爲什麼它仍然不起作用。它看起來像用戶模仿沒有管理員特權。

有沒有其他種類的模仿?

+1

你打算從哪裏獲得本地管理員密碼? –

+0

由用戶告知,密碼不是祕密。它實際上不是管理員帳戶本身,而是另一個屬於管理員組成員的帳戶。 – ewlung

+3

您不檢查'ImpersonateLoggedOnUser'的返回值。我不確定如果不通過UAC就可能提升。我建議你有兩個服務。添加可以重新啓動第一個服務的第二個保護服務。 –

回答

5

這是可以預料的。在管理員組中的UAC用戶下,除非他們通過UAC提升過程,否則會收到經過篩選的令牌。您正在冒充其他用戶,但您沒有UAC提升權限,因此擁有經過篩選的特權令牌。

爲了使用提升的權限執行代碼,在UAC下,您必須通過UAC提升過程。如果你能避免這樣做,那麼UAC將毫無意義。

至於我可以告訴你有以下原則選擇:

  1. 啓動另一個進程做工作,使用runas外殼動詞強制擡高,或者實際上其他一些機制來安排升高。這將通過你想避免的UAC對話。
  2. 作爲替代方案,安裝兩項服務。第一項服務是您當前安裝的服務,即您希望重新啓動的服務。第二項服務是一項小而簡單的服務,其唯一任務就是執行重新啓動。因爲第二個服務在沒有UAC的會話0中運行,所以您可以輕鬆地安排它具有足夠的權限來重新啓動第一個服務。當你需要從你的桌面應用程序,重新啓動服務1,發送請求到服務2,使服務2能夠進行服務1.

的重啓順便說一句,我注意到,你不檢查您致電ImpersonateLoggedOnUser的錯誤。

+0

謝謝大衛。我想我現在對這個UAC很瞭解。你說得對,如果它可以被這樣繞過,那將是毫無意義的。我會嘗試實施第二項服務。 – ewlung

相關問題