powered by simpleCommunicator - 2.0.37     © 2025 Programmizd 02
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Повышение привилегий программно
9 сообщений из 9, страница 1 из 1
Повышение привилегий программно
    #40101793
hlopotun
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем доброго дня,

проблема повышения привилегий рещается без проблем с использованием манифеста:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
...........
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
         <requestedExecutionLevel level="requireAdministrator"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
............


проблема в том что повышенные привилегии нужны не всегда а по определённому условию и программа должна пускаться в 99% случает с обычными привилегиями. И только если условие выполняется должна свои привилегии повысить. Соотв. манифест тут не поможет. Как правильно запросить повышение привилегий программно?

Спасибо.
...
Рейтинг: 0 / 0
Повышение привилегий программно
    #40101796
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
unit RunElevatedSupport;

{$WARN SYMBOL_PLATFORM OFF}
{$R+}

interface

uses
  Windows;

type
  TElevatedProc       = reference to function(AParameters: String): Cardinal;
  TProcessMessagesMeth = procedure of object;

  TEleavateSupport = record
  private
    FProc : TElevatedProc;
    procedure CheckForElevatedTask;
  public
    constructor Create(Proc: TElevatedProc); overload;

    function  IsAdministrator: Boolean;
    function  IsAdministratorAccount: Boolean;
    function  IsUACEnabled: Boolean;
    function  IsElevated: Boolean;

    // Add 'Shield' icon to regular button
    procedure SetButtonElevated(const AButtonHandle: THandle);

    // Runs Proc under full administrator rights
    // Warning: this function will be executed in external process.
    // Do not use any global variables inside this routine!
    // Use only supplied AParameters.
    function RunElevated(const AParameters: String;
                         const AWnd: HWND = 0;
                         const AProcessMessages: TProcessMessagesMeth = nil): cardinal;
  end;


//  ---------------------- Usage -------------------------
//
//  On App start:
//
//  EleavateSupport:=TEleavateSupport.Create(function (Params: string): cardinal
//                                           begin
//                                             Result := ERROR_GENERIC_NOT_MAPPED;
//                                             if Params=MyMode then begin
//                                               try
//                                                 [DoWork]
//                                                 Result := ERROR_SUCCESS;
//                                               except
//                                                 Result := ERROR_GEN_FAILURE;
//                                               end;
//                                             end;
//                                           end);
//
//  if [NeedElevation] then begin
//    EleavateSupport.RunElevated(MyMode);
//  end;


var
  EleavateSupport: TEleavateSupport;

implementation

uses
  SysUtils, Registry, ShellAPI, ComObj;

const
  RunElevatedTaskSwitch = '0CC5C50CB7D643B68CB900BF000FFFD5'; // some unique value

function CheckTokenMembership(TokenHandle: THANDLE; SidToCheck: Pointer; var IsMember: BOOL): BOOL; stdcall; external advapi32 name 'CheckTokenMembership';

function TEleavateSupport.RunElevated(const AParameters: String;
                                      const AWnd: HWND = 0;
                                      const AProcessMessages: TProcessMessagesMeth = nil): cardinal;
var
  SEI: TShellExecuteInfo;
  Host: String;
  Args: String;
begin
  CheckForElevatedTask;

  if IsElevated then
  begin
    if Assigned(FProc) then begin
      Result := FProc(AParameters)
    end else begin
      Result := ERROR_PROC_NOT_FOUND;
    end;
    Exit;
  end;

  Host := ParamStr(0);
  Args := Format('/%s %s', [RunElevatedTaskSwitch, AParameters]);

  FillChar(SEI, SizeOf(SEI), 0);
  SEI.cbSize := SizeOf(SEI);
  SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
  {$IFDEF UNICODE}
  SEI.fMask := SEI.fMask or SEE_MASK_UNICODE;
  {$ENDIF}
  SEI.Wnd := AWnd;
  SEI.lpVerb := 'runas';
  SEI.lpFile := PChar(Host);
  SEI.lpParameters := PChar(Args);
  SEI.nShow := SW_NORMAL;

  if not ShellExecuteEx(@SEI) then
    Exit(GetLastError);

  try
    Result := ERROR_GEN_FAILURE;
    if Assigned(AProcessMessages) then begin
      repeat
        if not GetExitCodeProcess(SEI.hProcess, Result) then Result := ERROR_GEN_FAILURE;
        AProcessMessages;
      until Result <> STILL_ACTIVE;
    end else begin
      if WaitForSingleObject(SEI.hProcess, INFINITE)<>WAIT_OBJECT_0 then begin
        Result := ERROR_GEN_FAILURE;
      end else begin
        if not GetExitCodeProcess(SEI.hProcess, Result) then
          Result := ERROR_GEN_FAILURE;
      end;
    end;

  finally
    CloseHandle(SEI.hProcess);
  end;
end;

constructor TEleavateSupport.Create(Proc: TElevatedProc);
begin
  FProc:=Proc;
  CheckForElevatedTask;
end;

function TEleavateSupport.IsAdministrator: Boolean;
var
  psidAdmin: Pointer;
  B: BOOL;
const
  SECURITY_NT_AUTHORITY: TSidIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID  = $00000020;
  DOMAIN_ALIAS_RID_ADMINS      = $00000220;
  SE_GROUP_USE_FOR_DENY_ONLY  = $00000010;
begin
  psidAdmin := nil;
  try
    // Создаём SID группы админов для проверки
    Win32Check(AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
      SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
      psidAdmin));

    // Проверяем, входим ли мы в группу админов (с учётов всех проверок на disabled SID)
    if CheckTokenMembership(0, psidAdmin, B) then
      Result := B
    else
      Result := False;
  finally
    if psidAdmin <> nil then
      FreeSid(psidAdmin);
  end;
end;

{$R-}

function TEleavateSupport.IsAdministratorAccount: Boolean;
var
  psidAdmin: Pointer;
  Token: THandle;
  Count: DWORD;
  TokenInfo: PTokenGroups;
  HaveToken: Boolean;
  I: Integer;
const
  SECURITY_NT_AUTHORITY: TSidIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID  = $00000020;
  DOMAIN_ALIAS_RID_ADMINS      = $00000220;
  SE_GROUP_USE_FOR_DENY_ONLY  = $00000010;
begin
  Result := Win32Platform <> VER_PLATFORM_WIN32_NT;
  if Result then
    Exit;

  psidAdmin := nil;
  TokenInfo := nil;
  HaveToken := False;
  try
    Token := 0;
    HaveToken := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, Token);
    if (not HaveToken) and (GetLastError = ERROR_NO_TOKEN) then
      HaveToken := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token);
    if HaveToken then
    begin
      Win32Check(AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
        psidAdmin));
      if GetTokenInformation(Token, TokenGroups, nil, 0, Count) or
         (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then
        RaiseLastOSError;
      TokenInfo := PTokenGroups(AllocMem(Count));
      Win32Check(GetTokenInformation(Token, TokenGroups, TokenInfo, Count, Count));
      for I := 0 to TokenInfo^.GroupCount - 1 do
      begin
        Result := EqualSid(psidAdmin, TokenInfo^.Groups[I].Sid);
        if Result then
          Break;
      end;
    end;
  finally
    if TokenInfo <> nil then
      FreeMem(TokenInfo);
    if HaveToken then
      CloseHandle(Token);
    if psidAdmin <> nil then
      FreeSid(psidAdmin);
  end;
end;

{$R+}

function TEleavateSupport.IsUACEnabled: Boolean;
var
  Reg: TRegistry;
begin
  Result := CheckWin32Version(6, 0);
  if Result then
  begin
    Reg := TRegistry.Create(KEY_READ);
    try
      Reg.RootKey := HKEY_LOCAL_MACHINE;
      if Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\System', False) then
        if Reg.ValueExists('EnableLUA') then
          Result := (Reg.ReadInteger('EnableLUA') <> 0)
        else
          Result := False
      else
        Result := False;
    finally
      FreeAndNil(Reg);
    end;
  end;
end;

function TEleavateSupport.IsElevated: Boolean;
const
  TokenElevation = TTokenInformationClass(20);
type
  TOKEN_ELEVATION = record
    TokenIsElevated: DWORD;
  end;
var
  TokenHandle: THandle;
  ResultLength: Cardinal;
  ATokenElevation: TOKEN_ELEVATION;
  HaveToken: Boolean;
begin
  if CheckWin32Version(6, 0) then
  begin
    TokenHandle := 0;
    HaveToken := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, TokenHandle);
    if (not HaveToken) and (GetLastError = ERROR_NO_TOKEN) then
      HaveToken := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, TokenHandle);
    if HaveToken then
    begin
      try
        ResultLength := 0;
        if GetTokenInformation(TokenHandle, TokenElevation, @ATokenElevation, SizeOf(ATokenElevation), ResultLength) then
          Result := ATokenElevation.TokenIsElevated <> 0
        else
          Result := False;
      finally
        CloseHandle(TokenHandle);
      end;
    end
    else
      Result := False;
  end
  else
    Result := IsAdministrator;
end;

procedure TEleavateSupport.SetButtonElevated(const AButtonHandle: THandle);
const
  BCM_SETSHIELD = $160C;
var
  Required: BOOL;
begin
  if not CheckWin32Version(6, 0) then
    Exit;
  if IsElevated then
    Exit;

  Required := True;
  SendMessage(AButtonHandle, BCM_SETSHIELD, 0, LPARAM(Required));
end;

procedure TEleavateSupport.CheckForElevatedTask;

  function GetArgsForElevatedTask: String;

    function PrepareParam(const ParamNo: Integer): String;
    begin
      Result := ParamStr(ParamNo);
      if Pos(' ', Result) > 0 then
        Result := AnsiQuotedStr(Result, '"');
    end;

  var
    X: Integer;
  begin
    Result := '';
    for X := 1 to ParamCount do begin
      if (AnsiUpperCase(ParamStr(X)) = ('/' + RunElevatedTaskSwitch)) or
         (AnsiUpperCase(ParamStr(X)) = ('-' + RunElevatedTaskSwitch)) then
        Continue;

      Result := Result + PrepareParam(X) + ' ';
    end;

    Result := Trim(Result);
  end;

var
  ExitCode: Cardinal;
begin
  if not FindCmdLineSwitch(RunElevatedTaskSwitch) then
    Exit;

  ExitCode := ERROR_GEN_FAILURE;
  try
    if not IsElevated then
      ExitCode := ERROR_ACCESS_DENIED
    else

    if Assigned(FProc) then begin
      ExitCode := FProc(GetArgsForElevatedTask)
    end else begin
      ExitCode := ERROR_PROC_NOT_FOUND;
    end;
  except
    on E: Exception do
    begin
      if E is EAbort then
        ExitCode := ERROR_CANCELLED
      else
      if E is EOleSysError then
        ExitCode := Cardinal(EOleSysError(E).ErrorCode)
      else
      if E is EOSError then
      else
        ExitCode := ERROR_GEN_FAILURE;
    end;
  end;

  if ExitCode = STILL_ACTIVE then
    ExitCode := ERROR_GEN_FAILURE;

  TerminateProcess(GetCurrentProcess, ExitCode);
end;

{ TEleavateSupport }


end.

...
Рейтинг: 0 / 0
Повышение привилегий программно
    #40101797
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShellExecute + 'runas'.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Повышение привилегий программно
    #40101833
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hlopotun
Как правильно запросить повышение привилегий программно?
Написать COM-объект, который будет делать привилегированную работу, а потом правильно его создать

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
type
  BIND_OPTS3 = record
    cbStruct: DWORD;
    grfFlags: DWORD;
    grfMode: DWORD;
    dwTickCountDeadline: DWORD;
    dwTrackFlags: DWORD;
    dwClassContext: DWORD;
    locale: LCID;
    pServerInfo: PCoServerInfo;
    hwnd: HWND;
  end;

procedure CoCreateInstanceAsAdmin(AHWnd: HWND; const AClassID, AIID: TGUID; out AObj);
var
  LBO: BIND_OPTS3;
  LMonikerName: WideString;
begin
  { Request elevated out-of-process instance. }
  LMonikerName := 'Elevation:Administrator!new:' + GUIDToString(AClassID);
  FillChar(LBO, SizeOf(BIND_OPTS3), 0);
  LBO.cbStruct := SizeOf(BIND_OPTS3);
  LBO.dwClassContext := CLSCTX_LOCAL_SERVER;
  LBO.hwnd := AHWnd;
  OleCheck(CoGetObject(PWideChar(LMonikerName), @LBO, AIID, @AObj));
end;
...
Рейтинг: 0 / 0
Повышение привилегий программно
    #40101843
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Написать COM-объект, который будет делать привилегированную работу, а потом
правильно его создать

Ему повышение прав нужно чтобы СОМ-объекты регистрировать. Замкнутый круг.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Повышение привилегий программно
    #40101912
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
Ему повышение прав нужно чтобы СОМ-объекты регистрировать.
Можно этот COM регистрировать только для текущего пользователя
...
Рейтинг: 0 / 0
Повышение привилегий программно
    #40101940
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А сервер, крутящийся с повышенными правами, в который оно отмаршаллится, его там
найдёт?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Повышение привилегий программно
    #40102025
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
А сервер, крутящийся с повышенными правами, в который оно отмаршаллится, его там найдёт?..
Так пусть сам сервер и регистрирует его от своего имени
...
Рейтинг: 0 / 0
Повышение привилегий программно
    #40102060
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Per rectum ad astra.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Повышение привилегий программно
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]