22

In my VB6 application I open other EXE files. My application runs without any UAC prompt, but I have an EXE which checks for updates to software. This prompts the UAC prompt. So how does Windows decide whether to show the UAC prompt? I saw this link . So does it depend on the code I wrote in my application? It is interesting that my application (that is the main EXE file) does not prompt UAC whereas a small EXE which checks and downloads updates prompts the UAC. I have all the EXE files digitally signed. I already had a glance at following links:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa511445.aspx

http://technet.microsoft.com/en-us/library/cc505883.aspx and some other.

But still I am not clear about it.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
IT researcher
  • 3,274
  • 17
  • 79
  • 143

4 Answers4

30

You are almost certainly hitting a Windows Installer Detection Technology compatibility heuristic. Windows will try to detect when an application is an installer, and probably needs to be elevated.

Installer Detection only applies to:

  1. 32 bit executables
  2. Applications without a requestedExecutionLevel
  3. Interactive processes running as a Standard User with LUA enabled

Before a 32 bit process is created, the following attributes are checked to determine whether it is an installer:

  • Filename includes keywords like "install," "setup," "update," etc.
  • Keywords in the following Versioning Resource fields: Vendor, Company Name, Product Name, File Description, Original Filename, Internal Name, and Export Name.
  • Keywords in the side-by-side manifest embedded in the executable.
  • Keywords in specific StringTable entries linked in the executable.
  • Key attributes in the RC data linked in the executable.
  • Targeted sequences of bytes within the executable.

So, as you said:

but i have a exe which checks for updates to software

My guess is that this CheckForUpdates.exe is triggering the compatibility heuristics.

The correct thing to do is to add an assembly manifest to your "checking" executable, informing Windows that it should not elevate the utility. This is done with a requestedExecutionLevel of asInvoker in the manifest:

AssemblyManifest.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
   <assemblyIdentity 
      version="1.0.0.0"
      processorArchitecture="X86"
      name="ITReasearchAssociates.Contoso.Updater"
      type="win32"
   /> 

   <description>Update checker</description> 

   <!-- Run as standard user. Disable file and registry virtualization -->
   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
      <security>
         <requestedPrivileges>
            <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
         </requestedPrivileges>
      </security>
   </trustInfo>
</assembly>

That way your "Check For Updates" application will never elevate, and never mistakenly gain administrative privileges.

If you want your updater to actually apply updates (updates which require administrative privileges), then you would launch your updater application as an administrator.

Sample Code

//Check if there are updates available
if (!CheckForUpdatesAvailable())
   return; //no updates. We're done

//If the user is an administrator, then get the update
if (IsUserAnAdmin())
{
    //Maybe throw in a "Hey, user, wanna get the update now?" dialog
    DownloadAndApplyUpdates();
    return;
}

//The user is not an admin. 
//Relaunch ourselves as administrator so we can download the update
//Maybe throw in a "Hey, user, wanna get the update now?" dialog. A button with a UAC shield on it
ExecuteAsAdmin(Application.ExecutablePath, "/downloadUpdate");

with the helper functions:

private Boolean IsUserAnAdmin()
{
    //Public domain: no attribution required
    //A user can be a member of the Administrator group, and yet not be an administrator.
    //Conversely, the user can be an administrator while not being a member of the administrators group.
    var identity = WindowsIdentity.GetCurrent();
    return (null != identity && new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator));
}

private void ExecuteAsAdmin(string Filename, string Arguments)
{
    //Public domain: no attribution required
    ProcessStartInfo startInfo = new ProcessStartInfo(Filename, Arguments);
    startInfo.Verb = "runas";
    System.Diagnostics.Process.Start(startInfo);
}

Then on startup you just need to look for the /downloadUpdate command-line parameter to know that you're job is to actually do work:

public Form1()
{
    InitializeComponent();

    //Ideally this would be in program.cs, before the call to Application.Run()
    //But that would require me to refactor code out of the Form file, which is overkill for a demo
    if (FindCmdLineSwitch("downloadUpdate", true))
    {
        DownloadAndApplyUpdates();
        Environment.Exit(0);
    }
}

Note: Any code is released into the public domain. No attribution required.

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • 1
    I will add that the filename rules listed above are almost certainly incomplete. Anecdotally an app I have which requires UAC when named like APP123.exe does NOT reqiure UAC if renamed to APP.exe. – StayOnTarget Feb 15 '17 at 15:20
  • 1
    Thanks @Ian Boyd! I saw this one: https://stackoverflow.com/questions/1423492 , installed Windows SDK and used `mt.exe` to add a manifest file like suggested to my `.exe`! Works like a charm! – ewerybody Jan 23 '19 at 15:06
  • "Targeted sequences of bytes within the executable." can you elaborate on that? – Sajuuk May 06 '20 at 09:03
  • @Sajuuk I cannot. Only Microsoft, or someone who has reviewed the Windows source code and signed an NDA, would know. – Ian Boyd May 06 '20 at 13:42
1

Someone can specify in the configuration of the exe that this file needs to be executed with higher Privileges.

How to request Admin Privileges

I don't know what this update is for, but I'd suggest that it needs to update a component like a service, or some files that are located in the ProgramFiles-Dir. Therefore it needs Admin Privileges.

user229044
  • 232,980
  • 40
  • 330
  • 338
sternze
  • 1,524
  • 2
  • 9
  • 15
  • My doubt is how windows decided that uac should prompt or not. Your method runs the program as admin and it does ask user to enter password of admin. – IT researcher Nov 20 '13 at 13:22
  • That's nevertheless how it works, although the Codeproject article is not very complete. You have a small choice of different options you can ask for in that manifest with subtle or non-existent differences (such as request highest possible privilegue or admin privilegue, or blah), but basically it's just that. Windows security is pretty dumb, though on the other hand I wish I could quote a system that is less dumb (Linux is even _more stupid_, as it makes you type in the root password...). – Damon Nov 20 '13 at 14:05
1

Your programs probably lack application manifests that mark them as non-legacy. As a result Windows will apply scripted installer detection heuristics to decide whether your program is an installer. This is pretty much the only way an "unexpected" UAC prompt gets raised.

These heuristics include keyword searches within the EXE file name and several of the extended properties of the EXE, and may even look for well-known binary signatures (i.e. byte strings) inside the file.

BTW, your crypto-signing doesn't enter into this at all. And it doesn't help a thing if it wasn't issued by a trusted CA.

For that matter anyone who trusts code just because Windows reports the commpany name on the UAC prompt is a fool. Malware authors steal these all the time, and for that matter they are trivial to obtain and almost never reported by users when crap programs cause problems. Save your money, code signing certs are a failed concept.

Bob77
  • 13,167
  • 1
  • 29
  • 37
  • Ok. So without running as administrator and having proper manifest file can avoid UAC prompts in my case? – IT researcher Nov 20 '13 at 14:30
  • Also how to create a manifest file which will make application to launch without UAC prompt? – IT researcher Nov 20 '13 at 14:56
  • 1
    @ITresearcher: If that is your real question (how to prevent the prompt), you should ask that - and provide more information than in this question. But the answer might very well be "The UAC prompt is there for good reason, you are changing the installed software, and that should be an intentional decision by the user". – MSalters Nov 20 '13 at 15:17
  • If you want a spawned program to run with the parent's rights it needs "asInvoker" specified in the element of the manifest. To create and add application manifests to VB6 applications you can use 3rd party tools or create and embed them manually. – Bob77 Nov 21 '13 at 15:55
0

The UAC prompt is used when a privilege elevation is needed. Your own VB6 app doesn't need it, and therefore the default behavior is OK. An updater would need the privilege, so its author marked the executable as requiring it. Windows spots that and puts up the UAC prompt.

Now depending on the exact Windows version and security updates, that privilege remains available for a while, even to other (child) processes. This may prevent duplicate UAC prompts.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • The updater is created by me. So some code in that triggers UAC to prompt? I didn't run the updater exe as admin(run as admin which causes UAC to prompt always)in my code. So is it some code triggering UAC? – IT researcher Nov 20 '13 at 14:05
  • 1
    I believe Windows does have some additional heuristics: did it need UAC in the past, for instance? Is it named "setup.exe" ? – MSalters Nov 20 '13 at 15:14
  • The file name is not setup.exe. But does UAC depend on the file name also? – IT researcher Nov 23 '13 at 06:19