Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Start application without administrator rights [duplicate]

Once you've started an application with Administrator permission, programs executed using ShellExecute in that application will inherit the Administrator permission. But that isn't what I want: it just has to start regularly without the extra permissions. ShellExecute accepts the parameter OPEN (regular) and RUNAS (Administrator). But if you use OPEN after you've started the application as Administrator, it still acts like RUNAS.

The following example demonstrates this: If you start it with regular permissions it says 'Started regular'. Once you press 1 for 'admin' it will start as administrator. If you press 2 in the newly created prompt it will not starts a 'regular' prompt, but again a 'Administrator' prompt.

I've found something about some parameters in RUNAS (https://superuser.com/a/374866), but they cannot be passed in ShellExecute. Any ideas?

program WindowsPrivilegeTest;
{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  Winapi.Windows,
  Winapi.ShellAPI;

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

// Source: http://stackoverflow.com/a/28572886/1870208
function 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
    Win32Check(AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
      SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
      psidAdmin));

    if CheckTokenMembership(0, psidAdmin, B) then
      Result := B
    else
      Result := False;
  finally
    if psidAdmin <> nil then
      FreeSid(psidAdmin);
  end;
end;

var
  lLine : String;
  lOperation : PChar;
begin
  try
    if IsAdministrator then
    begin
      Writeln('Started as administrator');
    end
    else
    begin
      Writeln('Started regular');
    end;

    while True do
    begin
      Writeln('');
      Writeln('How to start? 1 = admin, 2 = regular user. Type number and press enter');
      ReadLn(lLine);
      lOperation := '';

      if lLine = '1' then
      begin
        lOperation := 'RUNAS';
      end
      else
      if lLine = '2' then
      begin
        lOperation := 'OPEN';
      end;

      if lOperation <> '' then
      begin
        ShellExecute(0, lOperation, PChar(ParamStr(0)), nil, nil, SW_SHOWNORMAL);
        Break;
      end;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
like image 485
renevondecafe Avatar asked Oct 18 '22 23:10

renevondecafe


1 Answers

I used to solve this puzzle when creating an installer, here's one of the possible solutions.

The idea is to create a background process that runs with user privileges, your main application communicates with it and lets it know what program to start - the started process will have user privileges.

It should work like this: Background process is launched as usual, with User privileges. When launched, it starts your main program as Admin. The background process thn stays hidden and awaits the command from the main process.

like image 84
djsoft Avatar answered Nov 15 '22 09:11

djsoft