I am looking for a method to use as an alternative to disabling UAC to keep application persistence throughout the lifetime of the system.
My application runs every time the system starts up, and it requires elevated privileges, so when UAC is enabled it asks the user whether or not to run my application, every time the system is rebooted. This is very tedious and can become annoying if it happens every time. If UAC is disabled this warning no longer appears but of course that is very harmful to the user as it could lead to threats on their computer.
My question is; In C++ how can I programmatically allow file/application persistence throughout any event on the users' PC just for my application without getting the UAC warnings each time!
I am looking for ANY possible method, an exploit, a bypass method, anything, I'm really desperate at the moment as I've been stuck with this program for several days now and I'm just 99.9% done my project. I really need to get this through. THANK YOU SO MUCH FOR ANY ADVICE you may offer me!
The first step is to determine whether your program really needs admin privilege at all. Sometimes a program only runs with admin privilege, but for trivial reasons: a log file is being generated in the wrong place, for example, or a file that should be being opened for read-only access is being opened for full access. If that's the case you can fix the problem and avoid any further structural changes.
Secondly, ask whether your program needs admin privilege all the time, or only when the user performs certain actions. In the latter case, you should probably only elevate when it becomes necessary to do so; as well as meaning that the user does not need to approve the program launch on every reboot, it also helps protect the user from making an administrative change without intending to. This is particularly relevant if UAC is configured to require a password each time.
Thirdly, ask whether your program really needs a user interface. If not, then it should be a system service.
If your program really does need admin privilege all the time, and really does need a user interface, then you need to separate it into two parts, one containing the user interface and one containing the functionality that requires elevated privilege.
The user interface part should be a program that runs whenever a user logs in, just as your program does now. The elevated privilege part should be a system service.
The primary logic might belong in either part, or might also need to be split into two; it depends entirely on the context. (The system service does need to contain enough logic to ensure that the the privileged operations it is performing are safe and appropriate. It can't simply do anything the user interface part tells it to.)
These two parts can interact using whatever form of inter-process communication and/or synchronization is most convenient. You do need to be aware that they will be in different Remote Desktop sessions; for example, if you create an event object for synchronization the name must start with the Global\ prefix.
You will need to consider that more than one user may be logged in at the same time, either via Switch User or because the machine is a Remote Desktop server. This may mean that the service component needs to support multiple simultaneous clients, which affects your choice and implementation of IPC. Alternatively, the user interface component needs to detect that another instance is already running, and wait until that instance goes away before attempting to connect.
You will also need to consider how the program should react when the logged-in user does not have administrative privilege. At the moment such a user can't run your program at all, probably making the prompts even more annoying than they are to an admin user! If it is OK for the program to work as normal for a non-admin user then you don't need to do anything special. If the program should not work for a non-admin user, or if some of the functionality should be restricted, then (a) the GUI component needs to behave accordingly, by, e.g., exiting silently; and (b) the service component needs to check the context in which the GUI component is running. It is not enough for the GUI component to do the check, because the user can trick it if he or she wishes to; the service component must check too.
The easiest way to do that is probably to use GetTokenInformation with the TokenElevationType option; if the token type is TokenElevationTypeLimited or TokenElevationTypeFull, the user has administrator privilege. If the token type is TokenElevationTypeDefault, there is no split token; either the user is not an administrator, is the local Administrator account, or UAC is turned off; in this case, use CheckTokenMembership to check whether the user is in the Administrators group or not.
In some cases, it might also be sensible for certain tasks to require UAC approval, even if other tasks do not. Such tasks need not involve the service component; the GUI component can elevate itself, with the user's consent, to perform them.
Related
I want to expand user specific environment variables. I have API for that "ExpandEnvironmentStringsForUser". My code is running in context of service. I want to fetch currently logged in user. Whenever I use GetUserName API it returns "SYSTEM".
My problem is I want to expand %temp% in user specific mode and not in system mode.
Is there any way to get currently logged in user when my code is running in service context?
If your program is running as a service, then there isn't "a logged-in user". The whole notion of multi-user systems makes such a concept meaningless. There could be any number of users logged in, and it is impossible for your program to guess which one you wanted it to pretend to be running under.
Your question is like asking "of all my family members, in whose bedroom is my car currently parked?" when in fact the car is safely and sanely sat outside in the driveway.
You can use the qwinsta command (part of Terminal Services) to obtain a list of currently logged-in users, and do something with that; it'll have absolutely nothing to do with your service, but on some Windows systems that allow only one interactive session at a time (for licencing reasons), it'll be the only one marked Active:
C:\Users\tomalak>qwinsta
SESSIONNAME USERNAME ID STATE TYPE DEVICE
services 0 Disc
>console tomalak 1 Active
That's a little hacky, though; typically you would have a little user-space application that can talk to the back-end service, and do all the user-specific shenanigans in the application.
I have an Avast antivirus and it has a process "AvastSvc.exe". If I try to end/kill that process in Windows Task Manager, then a windows with the following messages appears: "Unable to Terminate Process", "The operation could not be completed.", "Access is denied". Trying to end some system Windows processes (like winlogon.exe) may feature the same behaviour (although once I managed to kill winlogon.exe and got my machine hanged!).
I want my application (possibly, converted to a service) behave in the same way. How can I do this?
Disable Windows Task Manager so he cant kill my process is a similar question which has many interesting answers, but they don't seem to feature the technique which is used by the above antivirus and results in "Unable to Terminate Process" message.
http://forums.codeguru.com/showthread.php?t=503337 has a solution on how to prevent stopping a service (eg, via services.msc console), but I need preventing ending/killing its process in Task Manager.
I am writing the app in C++/winapi, no CLR/.Net, under Windows 7.
UPDATE on permissions:
Antivirus process AvastSvc.exe is owned by "system" account. However, I have other processes owned by "system" account, and they are killable and antivirus is not. Also, I compared executable permissions and owners of antivirus process and ones of killable processes, and I don't see any difference.
UPDATE on user control and purpose of the software:
The software functionality is somewhere between that of system and business software. The nature of the software requires it to run on a permanent basis. The application itself will have a "turn off" action, and we want to encourage users to use it and discourage them from killing the process (it's similar to what antiviruses do). I understand that it's not possible to completely prevent users from killing it, but I want to make it harder. This question is specifically about the way described above ("Unable to Terminate Process") which some services (like Avast) use to prevent killing their processes. It is sufficient for me to achieve just the same behavior. Also, users will be able to just uninstall the software if they don't like it/don't need it anymore.
This is not achieved through code (well, it might be for critical Windows system processes, but you are [probably] not writing components of the operating system), but rather through access permissions.
You can demonstrate this by elevating to Administrator and then attempting to kill Avast's process. It should succeed this time. Alternatively, you can take ownership of the executable (and possibly the folder in which it resides), then try to kill the process. Again, it should be successful.
Windows does not allow applications to exert more power over the computer than the user. If you own the machine and have the appropriate permissions, you can do anything you want, including terminating a running process. Thankfully, there is no way for you, as a developer, to block this.
The user is always in ultimate control. Attempting to create an alternative situation is a battle that virus and other malware developers fight—and lose—regularly. Since I'm not interested in helping anyone write malware, that's all I'm going to say about that.
And other than writing malware, I can't imagine what the motivation for this "feature" in an application would be in the first place. If you're simply trying to prevent regular users from killing a process that is critical to a business system, then you should just demote the privileges of the standard user accounts so that they will not be able to tamper with such things. As such, this is probably a job for Group Policy, rather than code.
I found that the function ProtectProcess() supplied in Prevent user process from being killed with "End Process" from Process Explorer results exactly in the effect I was looking for.
Hide your process by removing it from the eprocess structure
Issue persistent I/O requests that cannot be cancelled or completed by other processes
Create threads to debug your own process
Create separate process/es from memory that monitors the main process and re-starts it from memory once terminated by another process
This question is a follow up and continuation of this question about a Privilege problem I'm dealing with currently.
Problem Summary:
I'm running a program under a Domain Administrator account that does not have Debug programs (SeDebugPrivilege) privilege, but I need it on the local machine.
Klugey Solution:
The program can install itself as a service on the local machine, and start the service. Said service now runs under the SYSTEM account, which enables us to use our SeTCBPrivilege privilege to create a new access token which does have SeDebugPrivilege. We can then use the newly created token to re-launch the initial program with the elevated rights.
I personally do not like this solution. I feel it should be possible to acquire the necessary privileges as an Administrator without having to make system modifications such as installing a service (even if it is only temporary).
I am hoping that there is a solution that minimizes system modifications and can preferably be done on the fly (ie: Not require restarting itself). I have unsuccessfully tried to LogonUser as SYSTEM and tried to OpenProcessToken on a known SYSTEM process (such as csrss.exe) (which fails, because you cannot OpenProcess with PROCESS_QUERY_INFORMATION to get a handle to the process without the privileges I'm trying to acquire).
I'm just at my wit's end trying to come up with an alternative solution to this problem. I was hoping there was an easy way to grab a privileged token on the host machine and impersonate it for this program, but I haven't found a way.
If anyone knows of a way around this, or even has suggestions on things that might work, please let me know. I really appreciate the help, thanks!
By design, no process is allowed to achieve NT AUTHORITY\SYSTEM rights, unless it is started by another process with NT AUTHORITY\SYSTEM rights. The service is a workaround because the Service Control Manager itself is started by the Kernel at system start.
Unfortunately, the operating system is designed to prevent exactly what you're trying to do. If you want to be able to remove your service afterwards, simply grant the user in question SeDebugPrivilege for the local machine and then have the service uninstall itself.
Better yet, have the program whose memory is to be modified change DACLs to allow your administrator access to it's memory without SeDebugPrivilege. Then you don't need to take privilege at all.
EDIT2: And even better yet, just use shared memory in the first place. That's what it's for.
Is there a way to know whether user is completely logged in or not into system? I mean, i wanted to know whether initial login process, other initialization processes are done or not. Once those are done, i want to launch my application. So, in my service(installed before sys shutdown) i want to keep on checking whether everything is done or not, based on the result i want launch my app.
I'm not sure what you mean about "completeley logged into the system". The user can be logged in, or not; I don't get how he could be uncompletely logged.
If you want to launch an application when the session is opened, there are several ways of doing this:
Adding a shortcut in the "Startup" folder, in the "Start" menu
Adding a "Run" key in the registry (either in HKLM or HKCU depending on what your application does)
Your application can then detect if the session is about to close, listening to some specific Windows events, if it needs to.
If your application is a service, it can depend on other services and will wait for them to be started before starting itself.
If you just want to detect when the opened session is "ready to use", I'm afraid there is no good way to do this. The user could have some custom softwares launched on startup and there is no generic way to detect when these softwares were started.
I have a single thread that I'd like to run as an administrator in my application. The rest of the application I can happily run as the default user level (asInvoker). Is this possible? I notice there is an "ImpersonateLoggedOnUser" function. Can I somehow use this to log the administrator on and then get the thread to impersonate that person?
It seems as though this ought to be something pretty trivial to do ... but there doesn't appear to be any obvious way to do it. Can anyone help me out?
Edit: So if I have to fire off a seperate process is there any way I can CreateProcess a new process and have it launch from a specific entry point. I can, of course use command line processing to do it, but i'd really rather I could stop the user from entering the command line and starting an unclosable process!
No, elevation is per process, not thread.
If the rest of the application has to run non-elevated, you could run yourself elevated with some parameter (myapp.exe /uac "ipcparamhere") and use some sort of Inter-process communication to communicate back to the "main instance" of your app. (If the elevated process only performs a simple operation, you could probably check for success by using the exit code of the process)
This is not possible. You'll need to gain admin privileges by including a manifest in the app. Google "requireAdministrator" to find the manifest you'll need. Your user will probably quickly tire of doing this over and over again, your best bet is to spin-off the task that requires these privileges into a separate process. A service for example.
You can launch a separate exe and have a manifest on it saying it requires administrator. Then be sure to launch it with shell execute, which uses manifests, and you're all set. As a thoughtful touch, put a UAC shield on the button that kicks off that thread. (Send it a BCM_SETSHIELD message if you're doing this all by hand.)
You can decided whether you want a visible window or not on the separate process. Meanwhile the user can still drag and drop into the main app.