How to determine why application is prompting for elevation - windows-7

When launching my executable, Windows is prompting for elevation, when it shouldn't be.
How can i figure out why Windows is prompting me to elevate my executable on launch?
Notes:
there is no manifest resource (asking for asAdministrator, or otherwise)
there is no manifest file
the compatibilty tab (for all users and just me) has the "Run as administrator" not checked
How can i determine why my application is prompting for elevation?

In the absence of a manifest, the usual reasons are name heuristics (eg your file is called setup.exe) and group policy (which you may have set accidentally after a "this program may not have run as expected" dialog.)
To prevent it, simply apply a manifest (embedded or external) with asInvoker. Then you will no longer care about these heuristic and you will not elevate.
I know I commented this above but I need to repeat it: What your code tries to do will NEVER cause elevation. NEVER. Stuff that won't work unless you're elevated fails when you're not elevated. It doesn't elevate you.

Related

Get administrator privilegs in Qt during runtime [duplicate]

Is it possible to get a C++ application running in Windows to request administrator privileges from the operating system at run time?
I know it can be done at compile time, but can't seem to find anywhere whether it can be done at run time.
Thanks for your help!
EDIT: What if I want the current instance to have elevated privileges? For example, I might have data stored in memory which I want to keep.
If you want the application to always elevate, you can give it a manifest, either by building one in (not compiling technically) or by putting an external manifest in the same folder as the exe. If you want to decide, as a person, to run it elevated, you right click the exe or short cut and choose Run As Administrator. If you are launching it from code, then as #vcsjones comments, you use the runas verb when you launch that process. For example:
ShellExecute( NULL,
"runas",
"c:\\windows\\notepad.exe",
" c:\\temp\\report.txt",
NULL, // default dir
SW_SHOWNORMAL
);
You can elevate a process only during its creation. When a process already runs, there's no way to change its security token: it either runs elevated or not.
If your application needs to perform an administrative task, and it usually runs non-elevated, you have to create another .exe which will request elevation with its manifest. To start a process elevated, you have to use ShellExecute or ShellExecuteEx function. From your main process you will need a way to pass the commands to that new process that will run elevated.
For more information about UAC, read Designing UAC Applications for Windows Vista series.
Not quite, but you can do the opposite—you can drop privileges if you already have them. So, you can have your program start out running as an Administrator, using one of the methods listed by Kate Gregory. Then, drop your unneeded privileges; see Dropping privileges in C++ on Windows for how to do that.
Add a manifest file into your EXE as described here.
http://msdn.microsoft.com/en-us/library/bb756929.aspx
Your process (and threads) have a token assinged to them. That token already have all your groups set up. Under UAC, the Administrator group is disabled. UAC will remove that disabled group so you end up with a full administrator token.
To acheive the same, you must have the TCB priviledge. In other words, to elevate a process at runtime, you will need help from a process running under the SYSTEM account, and Microsoft isn't providing one, nor an API to control the current UAC implementation. Otherwise, it would defeat the purpose.
For the sake of completness, there is a whitelist of process that can perform some elevated operations without prompting. In short, your executable needs :
To be signed by Microsoft
To perform predefined operations, like with IFileOperation
The best explanation I found is this hack. It has been fixed since then, but is sheds some light on the whole thing.

Failure to launch Windows program via URI after adding to HKCU/Software/Classes

I'm trying to set up a test application on Windows to launch via a "myapp://website.com"-style URI. Mostly, I'm basing myself off of tutorials like this:
http://msdn.microsoft.com/en-us/library/ie/aa767914(v=vs.85).aspx
While I got the initial setup working inside HKEY_CLASSES_ROOT, a new constraint is for the installation to happen without requiring administrator access. So, I deleted all changes in CLASSES_ROOT, and decided to retry the registry additions, instead using the HKEY_CURRENT_USER branch, at HKEY_CURRENT_USER/Software/Classes/myapp.
This appears to be detected by the browsers, and they display their confirmation dialog. However, they never actually run the app. Internet Explorer gives the most helpful error message, with a dialog saying "Unable to open this helper application for {uri}. The protocol specified in this address is not valid. Make sure the address is correct, and try again.
Is there some part of the registry I'm missing for a non-administrator setup? This is an export of my changes as a .reg. (Dashes censoring my username). EditFlags was added as a guess, but didn't work without it either.
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\myapp]
"URL Protocol"=""
#="URL:David Protocol"
"EditFlags"=dword:02000000
[HKEY_CURRENT_USER\Software\Classes\myapp\DefaultIcon]
#="C:\\Users\\------\\AppData\\Roaming\\-----s Stuffs\\URISchemeTest.exe,1"
[HKEY_CURRENT_USER\Software\Classes\myapp\shell]
[HKEY_CURRENT_USER\Software\Classes\myapp\shell\open]
[HKEY_CURRENT_USER\Software\Classes\myapp\shell\open\command]
#="\"C:\\Users\\-------\\AppData\\Roaming\\------s Stuffs\\URISchemeText.exe\" \"%1\""
Now that I have this working, I can't be perfectly certain of what it was that was causing problems, but I can at least give an account of what I tried to do differently in the hopes this helps future researchers.
%-sign directory accessors might not be supported by the path declaration. If they are, they may need to be encoded a certain way. Lower down In the article linked in the question, it mentions how Internet Explorer may decode certain URL parameters, but other browsers may not. Either way, if you've been specifying the command line as "%APPDATA%/MyProgram.exe", it may be more reliable starting from "C:/" until you can work through that issue.
EDIT: One other thing I just noticed, if the Paste from my question is correct: My working version of the registry changes set the default key of the root to "URI :David Protocol". Note "URI", not "URL". It's possible that mis-naming that (easy since another value is declared as "URL Protocol") could break the resulting effects.
While you might not have to specify a DefaultIcon, you may want to be careful that you're not referring to an invalid one. For safety, I set up mine to point specifically to a .ico file, rather than ".exe,1"
As some other commenters mentioned, I don't think EditFlags is really necessary, and might not be related.
A cautionary rebuttal to the highly-voted answer near this one, though: This. Works. No UAC access necessary. From the outset of my research, I personally would have believed an explanation that it's too risky to allow without a UAC admin prompt, etc. However, I took the time to test it, and could write a simple program with a button that sets itself up under HKCU/Software/Classes, and is accessible to the browser. I then tested it from the computer of a developer who had never taken part in any of my research (clean environment), and without any admin prompts, it worked fine. (Obviously, this program will only be accessible to the current user)
(For easy reading, a reminder: HKCU = HKEY_CURRENT_USER. HKCR = HKEY_CLASSES_ROOT. HKLM = HKEY_LOCAL_MACHINE)
Anything that could write to the user's HKCU registry already has non-admin binary access. Furthermore, all browsers will show a warning message about launching the program before opening it (perfectly understandable, given that it's local code). Several of them even give the full folder path of the executable you'll be launching.
I know the tutorial said to put the key in HKCR; and that this is known to come from HKLM/Software. However, it's worth reading up the whole story here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724475(v=vs.85).aspx
This key is partially derived from the HKCU hive - and in fact, the user's settings will override the local machine settings. There is nothing specifically indicating that HKLM will override HKCU when displaying this type of key inside of HKCR.
You cannot ignore what the MSDN article tells you, registering the protocol handler in a HKCR key is a hard requirement.
There's a good reason for that, also fairly explicitly stated in the article, protocol handlers are dangerous. They allow an arbitrary web page to start a program on your machine. They even work inside a Store app, another example of a heavily secured runtime environment that runs code inside a sandbox that stops dangerous operations.
Documenting HKCR doesn't help much unravel this, it was meant for appcompat with 16-bit code and today is an alias. Shows a merged view of both HKCU and HKLM keys. The HKLM keys are different from HKCU keys, writing key values require elevation. Only a program that can acquire a elevated security token can create new values or alter them, normally obtained by going through the UAC prompt. The problem with HKCU keys is that any program can write keys there without elevation. Which would open up a security hole if protocol handlers could be registered in a HKCU key. So this cannot work, urlmon simply doesn't look at the HKCU keys to find the protocol handler.

Windows 7 (UAC) doesn't allow my program to write down inside data file owned by another program. How to do?

I've to maintain a VB6 piece of software which, basically, exports data from a second program and import them into data files about a third program. So, this import/export tool worked very well since some years under Windows 95 to XP, but, now, I have to update it to support Vista and Seven... And it fails when time comes to write down into third program's files. At this time, I've just done my tests under Windows 7, but I suppose it will be the same under Vista.
Here is the problem in detail :
When my program try to reach the third program's data for writing, I get this error : "Run-time error '75': Path/File access error". So, it sounds like a UAC blocking because my program try to obtains access for writing about a data file he doesn't own. Then, if I run my program with admin rights OR with XP compatibility, it works : no error and third program's data file is well modified.
At this time I'm wondering how to work around this error (fatal for my program since it's blocked about its main job : to export/import data) programatically : during install (I'm using Inno Setup) or during runtime.
What's the right way ? Force a "XP compatibility" programmatically OR elevate my program to be launched with admin rights ? How to achieve this and when (during install or at runtime) ? Does a manifest could change something in this field (never used any manifest at this time) ?
Also, whatever be the way (XP compatibility or admin rights), the UAC warns user about system change at every launching : very annoying :(
So, what to do to have my program runs as smoothly under Windows 7 and Vista as it does under XP, knowing it has no other choice than write down in third-party data file (since it's its main purpose) ?
Awaiting your lighted replies...
PS : also (it could be important), my program doesn't know the data files's path by itself, but it's the user who select-it using common dialog.
OK, I'm back with some news. I've embedded a manifest which just does level="requireAdministrator" using the Manifest Creator for VB6 (the one indicated by Matt in his reply).
If I install (under Windows 7) my program being logged as administrator, it installs without any question, then program is launched without any question and does its job (read and write any files which are not owned by my program) very weel without any question. So, perfect in this case !
Nevertheless, if I'm logged as simple user, it installs well after asking permission with admin password, then program is launched without any question, BUT (and this is the remaining problem) I fall again in the "Path/File access error" (error '75') when time comes to read or write external file (not owned by my program).
So, and this is my additional question : how to solve this error being logged as simple user ? Does it means elevation didn't worked (while it seems to work in others case for any steps : install, launching, read/write) in this specific case only ? It's a little bit confuse in my mind here...
EDIT : Well, I think I've understood a thing, but need your confirmation (or not). I'll call my program B. B will read/imports data owned by program A, then write/export to data owned by program C.
My confusion was that I reinstalled B being logged as simple user, but not programs A and C which still was installed being logged as admin. So, when time comes for B to read data about A, in spite of the elevation, it fails because these A's data are owned by administrator (even if these A's data are not in user specific path, but, says "C:\email_data").
If I reinstall all the three programs being logged as simple user, it works (no warning nor error).
So, I reformulate my question : since elevation works (which should allow program to gain admin rights), why does program B (installed by user) cannot read data about program A (installed by admin) ? Should I add something during Inno Setup process to do my program be installed as admin only (knowing I've not any influence about way A and C programs are installed) ?
You can use either an external manifest file (myapp.exe.manifest) or use a tool to include a manfiest in your exe and a Resource.
There is a ton of content available, just google it. From here I grabbed a sample manifest:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
You need to change the level to "requireAdministrator", which will prompt the user for permission when they launch the application (depending on their UAC settings).
The %Program Files% directory is protected under Windows 7 when UAC is enabled (You need elevated privileges to write directly to it)
This is the problem you are encountering.
In order for 'legacy' programs to work more seamlessly (i.e. without visible error) Windows 7 uses folder redirection. This allows your legacy application to read and write a copy of what is in the program files directory.
If you use a manifest, this tells windows that your application is UAC aware and so no folder redirection takes place but you will need to have elevated (administrator) privileges in order to read/write to program files.
There are tons of examples of how to use a manifest. My personal preference is Manifest Creator.
If you set the requestedExecutionLevel to "requireAdministrator" then it will read and write the actual folder but you will be prompted for UAC elevation when your app runs.
The solution really is to not read and write to the program files location but to use another location. Have a look at this stack overflow question for solutions on this.

What are the differences between "Run as administrator" and a manifest with requireAdministrator?

I've written a program with a manifest that includes requireAdministrator. On Windows 7 systems with UAC enabled, Windows pops up a dialog asking for permissions, as it should. Works great.
If a user starts my program by right-clicking it and choosing "Run as administrator", then Windows 7 also pops up a dialog asking for permissions. However, there are some slight differences in how my program operates in some of the more esoteric parts of my program.
So what are the differences between "Run as administrator" and a manifest with requireAdministrator? Any links to documentation that describe differences would be appreciated.
Edit: This is with UAC enabled.
Edit: As promised below is the full explanation of the difference I'm seeing.
I'm using the EasyHook library to inject a DLL into another process. When my application is run with "Run as administrator", the injected process crashes and EasyHook returns the error "Unknown error in injected assembler code". None of the code in my DLL gets a chance to execute; the crash occurs before then. (Moreover, the crash occurs even if I strip the DLL down to nothing)
If I run my program normally (i.e., elevated via requireAdministrator), everything works fine.
My application is composed of a few different executables. The process that the user launches is not the same process that performs the injection.
With the information given there would be no differences in the permissions between the two processes.
If you request an execution level of "requireAdministrator" via the applications manifest your application will either be launched with the full access token of an administrator or not at all if the user denies consent (see Create and Embed an Application Manifest (UAC) for further information).
The same will happen when a user chooses Run as Administrator.
The only difference is the way that the process is started. When you start an executable from the shell, e.g. by double-clicking in Explorer or by selecting Run as Administrator from the context menu, the shell will call ShellExecute to actually start process execution. The whole process of elevation is hidden inside this function. Kenny Kerr describes this process in more details in Windows Vista for Developers – Part 4 – User Account Control:
ShellExecute first calls CreateProcess to attempt to create the new process. CreateProcess does all the work of checking application compatibility settings, application manifests, runtime loaders, etc. If it determines that the application requires elevation but the calling process is not elevated then CreateProcess fails with ERROR_ELEVATION_REQUIRED. ShellExecute then calls the Application Information service to handle the elevation prompt and creation of the elevated process since the calling process obviously doesn’t have the necessary permissions to perform such a task. The Application Information service ultimately calls CreateProcessAsUser with an unrestricted administrator token.
If on the other hand you want to create an elevated process regardless of what application information is available then you can specify the little-known “runas” verb with ShellExecute. This has the effect of requesting elevation regardless of what an application’s manifest and compatibility information might prescribe. The runas verb is not actually new to Windows Vista. It was available on Windows XP and Windows 2003 and was often used to create a restricted token directly from the shell. This behavior has however changed. Here is a simple example:
::ShellExecute(0, // owner window
L"runas",
L"C:\\Windows\\Notepad.exe",
0, // params
0, // directory
SW_SHOWNORMAL);
So essentially starting an executable using the Run as Administrator option means that ShellExecute bypasses the checks for compatibility settings, application manifests etc and directly requests elevation.
Kenny Kerr's article also has sample code to query the current process' token for its permission using the OpenProcessToken function. Possibly you can use the example to identify that there are no differences in the way your process is elevated.
I'm definitely curious to know which differences you are observing as I strongly doubt they are related to elevation.
As a last thing: Can you double check that you really request a level of requireAdministrator and not by mistake only a level of highestAvailable?
One possible difference might be the rarely used/understood/deliberately-chosen uiAccess attribute. Can you create two manifests, one with uiAccess=false and one with uiAccess=true, then tell us whether one of them gives the same behaviour as you see with right-click-run-as-admin?
The EasyHook documentation for the RemoteHooking class' IsAdministrator property mentions:
Due to UAC on Windows Vista, this property in general will be false even if the user is in the builtin-admin group. As you can't hook without administrator privileges you should just set the UAC level of your application to requireAdministrator.
It's hard to imagine why this is happening, but it is conceivable (especially as you are seeing it happen!) that assets, processes, assemblies, &c, with possibly different trust levels and so forth, will not inherit the elevation of your main app. Setting the requireAdministrator flag may handle/enforce this globally across the entire scope of resources and dependencies. Would love to know how this turns out.
I thought I was seeing a difference between these as well. However, it turned out that in my case the issue was this:
When I click "Run as Administrator" from my file browser (Q-Dir), the working directory is different than when I try simply double clicking an application with requireAdministrator set in the manifest. This changed the behavior of some buggy DLLs I had received. In fact, it turned out that 100% of the differences I saw were due to running from different working directories (specifically, it mattered whether I was on C: drive or a different drive letter) and that the method of getting the program to run as administrator had nothing to do with it.
It's an issue that is specific to my computer's exact configuration, but it is a possible clue into the type of thing that might be happening (or might have happened 7 years ago . . . )

Programatically registering .dll's on Windows Vista (using DllRegisterServer)

Instead of calling regsvr32.exe, one can register a .DLL using the following steps:
HINSTANCE hLib = ::LoadLibraryEx(dllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
HRESULT (STDAPICALLTYPE* lpDllEntryPoint)(void);
(FARPROC&)lpDllEntryPoint = ::GetProcAddress(hLib, "DllRegisterServer");
const HRESULT hRes = (*lpDllEntryPoint)();
This works fine on Windows XP. Regrettably, it fails on Vista, but only with some specific DLLs. hRes becomes E_ACCESSDENIED. I guess this is a security issue. Does anyone know how to register a .DLL from code on Windows Vista?
Note: I was logged in as administrator when running this code.
COM registration requires write access to the HKEY_LOCAL_MACHINE part of the registry.
Under UAC, write access to the HKEY_LOCAL_MACHINE requires an elevated administrator.
The easiest way to get an elevated process is to create it with a manifest that specifies 'requireAdministrator' access. - Look under the Project Properties -> Configuration Properties->Linker->Manifest File->UAC Execution Level to set the correct setting.
This means you will probably want to split your EXE into two parts. The 'normal' asInvoker part, and, when self registration is detected as a requirement, an elevated InstallMyself part. When the non elevated part detects a first-run type condition, it needs to use ShellExecute(Ex) to execute the FirstInstall.exe part - using CreateProcess or some other API will simply fail with a insufficient privilege error. ShellExecute will present the UAC prompt.
It is possible to use Application Isolation to load COM dll's without any registration step at all.
Is is unfortunate that the cause cannot be determined. However, if you are interested in doing further research, a tool that will help a lot would be Process Monitor from SysInternals. Process Monitor can log all the File, Registry and other access for a process, including all success and fail codes making it a lot easier to debug problems like this without having to resort to deeper means of reverse engineering.
Regrettably, I couldn't get this to work for all DLLs, even with Chris Becke's excellent tips. I didn't want to spend too much time solving the problem, so now I simply call regsvr32.exe. I expect this .exe to be present on all Windows machines, so I guess it is a good enough solution.

Resources