Elevating User Account Control with Delphi

If you have medium size of Delphi based application that required some privileges access to Windows OS particularly, then you might face problem with User Account Control (UAC). User Account Control (UAC) is a technology and security infrastructure introduced since Microsoft's Windows Vista. It aims to improve the security of Windows by limiting application software to standard user privileges until an administrator authorizes an increase or elevation. However without privileges access, application that need access to system folder or database might impact to failure.

This time lesson will share you 2 alternatives how the application "playing" with UAC. The first option order user to elevating the authorization manually by executing application using Run As Administrator from right click context menu of the EXE binary. While last option inject an embedding code to elevating user automatically. Both alternatives options came with the same scenario, a login form with Login button enabled if user has full privileges access, and so on in contrary. Let the learn begin, and here the detail explanation:

1. Detecting Elevation Level with ElevationType
We know that UAC only affect with OS greater than Windows XP, so you need also to detect what kind of OS version where the application currently running on. In order so, put below function on the code:

function osver: string;
begin
result := 'Unknown (Windows ' + IntToStr(Win32MajorVersion) + '.' + IntToStr(Win32MinorVersion) + ')';
case Win32MajorVersion of
        4:
                case Win32MinorVersion of
                        0: result := 'W95';
                        10: result := 'W98';
                        90: result := 'WME';
                end;
        5:
                case Win32MinorVersion of
                        0: result := 'W2K';
                        1: result := 'WXP';
                end;
        6:
                case Win32MinorVersion of
                        0: result := 'WVista';
                        1: result := 'W7';
                end;
end;
end;

Then, you can put elevation user account detector on form onShow event just like code below :

procedure TForm1.FormShow(Sender: TObject);
const
TokenElevationType = 18;
TokenElevation     = 20;
TokenElevationTypeDefault = 1;
TokenElevationTypeFull    = 2;
TokenElevationTypeLimited = 3;

var
token: Cardinal;
ElevationType: Integer;
Elevation: DWord;
dwSize: Cardinal;
RunAsAdministrator:boolean;
level: string;
begin
SB.Panels[0].Text:='OS type: ' + osver;

// Run As Administrator Validator
RunAsAdministrator:=false;
if OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, token) then
        try
        if GetTokenInformation(token, TTokenInformationClass(TokenElevationType), @ElevationType, SizeOf(ElevationType), dwSize) then
                case ElevationType of
                        TokenElevationTypeDefault:  RunAsAdministrator:=false;
                        TokenElevationTypeFull:     RunAsAdministrator:=true;
                        TokenElevationTypeLimited:  RunAsAdministrator:=false;
                else
                        RunAsAdministrator:=false;
                end
        else if (osver='W95') or (osver='W98') or (osver='WXP') then RunAsAdministrator:=true;

        if GetTokenInformation(token, TTokenInformationClass(TokenElevation), @Elevation, SizeOf(Elevation), dwSize) then
                begin
                if Elevation = 0 then RunAsAdministrator:=false
                else RunAsAdministrator:=true;
                end
        else if (osver='W95') or (osver='W98') or (osver='WXP') then RunAsAdministrator:=true;

        finally
        CloseHandle(token);
        end;

level:='(Administrator)';
btnLogin.Enabled:=true;
if not RunAsAdministrator then
        begin
        level:='(NOT Administrator)';
        btnLogin.Enabled:=false;
        end;
SB.Panels[0].Text:=SB.Panels[0].Text + ' ' + level;
end;

That's all. Try to execute the application in Windows 7, here's what I've got:



The Login button disabled since the application not executed with Run As Administrator context menu.



But, if the application running from Run As Administrator, the Login button now enabled!



Note that above code will not impact on Windows XP, since OS assumed that user running it as Administrator account even it executed from context menu or not.



2. Elevate Execution Level by Manifest file
Create a .manifest file :



Save it as .manifest. Continue to create a .rc file and named it as .rc.



Ah... don't forget to save the .manifest and .rc file in the same folder with the application source code. Then, continue to open command prompt, switch to directory where brcc32.exe (Borland Resource Compiler) exist and gives below syntax:



After the syntax succesfully compiled, it will automatically created a .res and .rec.



Back to the application source code and move to Project Manager window, right click to Project Files and point to View Source menu.



On .DPR menu, gives a line syntax after $R compiler directive just like picture below:



Finished! You may test the application and see what the different between options no #1 and #2.



Have a great fuckin' day!

Labels: ,


PS: If you've benefit from this blog,
you can support it by making a small contribution.

Enter your email address to receive feed update from this blog:

Post a Comment

 

Post a Comment

Leave comments here...