This is the scenario:
I have a service (#1) running as LOCAL SYSTEM, and it will eventually run a process (#2) that updates an application (#3). This process (#2), the updater, must run as LOCAL SYSTEM also, no problem here, since it needs to rewrite some files (#3).
When the updater starts as LOCAL SYSTEM, it will kill any running instance of my application (#3). After the files being update, I need to start the updated application (#3) again as the current logged account.
How could I manage this? Is there anything conceptually wrong in my idea?
UPDATED
The updater kills the app just to replace the files.
I don't think there's a way for the service to get its hands on the WindowsIdentity.Token handle it would need to call the CreateProcessAsUser() API function. Unless the app itself provides it.
There's a better way, you don't have to terminate the app to replace its executable files. All you have to do is rename them. You can then put the updates in place and signal the app to restart itself. Another nice advantage of this approach is that the app voluntarily shuts down (including notifying the user) instead of getting rudely aborted. Clean up the renamed files when you see the process terminated.
If you have access to the user's credentials, you can use Process.Start with a ProcessStartInfo specifying the username and password of the user.
If you don't know the credentials, then I am not sure it can be done.
A work around could be to have the service communicate with your program, asking it to shutdown itself, but before doing so, it should start a seperate tiny program. This should be running in the background, but it will be running with the current user's credentials. When you are finished, ask the background program to start your main program again, then exit.
One problem is knowing the "logged in user". XP and up support fast user switching, where more than 1 user may be logged on at the same time (vista and up support this feature even if the machine is a domain member).
Here is a link to a Raymond Chen blog article discussing the issue: http://blogs.msdn.com/oldnewthing/archive/2006/08/22/712677.aspx
Related
I would like to enumerate child windows of a given process to check for dialog windows. For reasons I won't go into here, if it finds any, I'd like to subsequently kill that application.
Running a standalone application to do this works without any issues. The application has access (via some P/Invoke calls) to a process's windows and I can subsequently kill that application.
Running the same code as a service, however, does not work as expected. It seems that the user running the service is not able to interact with the desktop (which is a setting I can only see for the LOCAL system account).
Does anyone know of any workarounds to this? Is it possible for me to enumerate a process's windows from a windows service?
FYI -- the code (at least an adaptation of) I'm using is available here: https://stackoverflow.com/a/1405088/2115261
You're probably running Windows 7 (or 8 or Vista), because the ability for Windows Servcies to interact with the desktop was last supported in Windows XP.
There is a white paper on MSDN that describes the changes made for Vista and upwards. Basically, it is now not possible to interact with the desktop in any way.
However, there is an example on CodeProject that demonstrates how to interact with the Task Scheduler from a Windows Service, and the process executed by the Task Scheduler can interact with the desktop. Perhaps this would be a suitable workaround for you.
You can only enumerate windows on the same terminal services session (aka Remote Desktop session) as your process. However, given appropriate privilege, you can launch a subprocess in another terminal services session to do the work on your behalf, although you need to be aware of the potential security issues depending on how you do this.
Assuming that you've already got a handle to the target process, the simplest approach would be to use OpenProcessToken to get a token in the target session, DuplicateTokenEx to duplicate it, and CreateProcessAsUser to launch the subprocess. Since all you need is a yes/no answer, you can use the process exit code rather than needing an IPC mechanism.
Security implications: since your subprocess is running in the user's context, a knowledgeable user could prevent it from running properly. Also, if you do use an IPC mechanism, you'd have to treat the input from the subprocess as untrusted (check for buffer overruns, etc.).
An alternative approach would be to launch a subprocess in your own context but in the target session. IIRC, you can do this by duplicating your own token and using SetTokenInformation on the duplicate to change TokenSessionId before launching the subprocess with CreateProcessAsUser.
Security implications: the subprocess, and through it the service process and the service account, could be subject to shatter attacks (malicious window messages) and other risks, although the integrity level mechanism may mitigate this to some extent. It is my understanding that creating a separate window station and desktop (with appropriate ACLs) eliminates these risks, but I'm not sure offhand of the impact on the code you want to run. Another mitigation would be to use CreateRestrictedToken to remove all groups and privileges from the token before launching the subprocess.
Unless it is absolutely essential that the user not be able to subvert your ability to detect the existence of the dialog window, I strongly recommend the first approach.
If you give the service a local system account to log on with, you will be able to tick the "Allow service to interact with desktop" checkbox in the service's properties (from Service Control Manager).
See the "Log On" tab of the Service's Property Pages.
That might work for you. But unfortunately, it probably won't. Still worth a quick try?
We are developing a .net application to run on startup for all users. Now we want to hide this application from task manager -> process list so that logged in user cannot delete it. We are using windows-xp
Please let me know if this is feasible
It's definitely possible to hide a process; you're talking about designing a rootkit. If that's actually what you want to do, see this question.
It's usually not the right way to approach this problem however: if you're the admin of a machine and you don't wish other users to kill a process, you simply don't give them permissions to do it.
Have your users log on with a limited user account and have your application run under a different account.
To get logon time reliably, you can use some either the windows security logs or if you're on a domain, active directory services:
Getting Local Windows User login session timestamp in C#
Getting idle time is more complicated because it depends on what you consider "idle" to be, but if you consider GetLastInputInfo() sufficient, this question describes a good way to do it, with a user process reporting back to a system process:
Getting user Idle time in C#?
Since the user cannot kill the system process, you could have that watch the user process and recreate it if necessary.
That's what Windows security is for. Define user account's permission in a way that he/she cannot manage services or kill processes.
If the case is as you described in comments under Colin's answer, then you can run a service-level process that respawns user process every time it is killed (by user). This way it is even simplier. You can use CreateProcessAsUser from WinApi to execute process on behalf of the user: http://msdn.microsoft.com/en-us/library/ms682429%28v=vs.85%29.aspx
Hide it in plain sight : make it run as a service with name that looks like it should be part of windows.
Then have another service that watches for the this one shutting down and restart it.
I have a very critical process that will run on the background in my winform application.
How can I prevent the user to end my winform application process?
I want to prevent the user to:
end the process from the Task Manager
shutdown the computer before the process of my application end
any other software-related method to kill a process (of course I cannot prevent the user from pressing the power button of his CPU)
My code is in C#, framework 4, build in VS2010 Pro.
Thanks in advance.
Stating your 'absolute' need to keep this process running, I really suggest to separate the critical part of your process from your winforms application and to move this part away from the user machine to a company server.
On this server write a service which keeps your vital work alive and running all the time you like.
These kind of 'absolute' requirements could be enforced only on server machines with redundancy disks, ups units and, (especially), informed sysadmins.
It's basically impossible to stop users from killing processes (you can even kill explorer.exe which is the shell for windows).
So it's recommended that you write your applications in such a way that they are resilient to user action or crashing. In your case it would be wise to have resumable operations in that process.
You can't absolutely ensure these things, but you can get some of what you want by:
1) Run only on Vista or later versions of Windows that assign security levels to processes
2) Run your process as administrator so it is the highest security level.
3) Make sure UAC (User Account Control) is turned on.
4) Turn off access to task manager for the logged in user account (via group policy)
5) Provide no way for the logged in user to elevate to admin, so that he can't run anything that has the privileges to stop your process.
6) Use a Shutdown script to check for your process running and prevent shutdown.
I have a service, written in C#, that monitors a set of files. It uses Growl to notify the end-user if the modified time of one of these files is over 4 hours old. I've seen situations where Growl.exe was not running under the current user's session, thus they did not receive updates. I'd like my service to check to make sure Growl is running (either Growl.exe or maybe I could look for the application ID somewhere?) and start it if it's not. How can I ensure that Growl is always running in the current user's session on any machine that this service runs on?
If the service needs to run as the current user, then why make it a service? The purpose of a service is to run at all times, even when a user is not logged in. As such, it's designed to run as a specific user at all times.
Why not convert this to a program that runs when a user logs in?
It's an interesting question, but it would appear that you can't do this as this post suggests. It seems like you can either specify that the service runs as a local system service, or as a particular user:
If your service is being started as "automatic" then you may only pre-configure a single set of credentials for the service. However, if you can identify the .exe file that the service is invoking at startup then you can create a batch file that will kick off that service at logon, at which point the active users credentials will be used by default.
Cheers,
CEC
At my company we have a product which pretty much interacts with everything you can imagine... registry, databases, devices, etc... it is composed of many parts but the entire application is launched by a single executable (start.exe) which is responsbile for launching everything else - this is all legacy code and run under a USER account.
Currently this is launched as a STARTUP item (or by double-clicking on the desktop icon) in Windows, meaning when the user logins into the USER account the application (start.exe) automatically kicks off, under this account it has all the permissions it needs to run and everything has been fine for years...
Now comes the change - I have written a service (Serv.exe) that is running as LocalSystem - this service is responsible for updating the various software components of our product and works as follows:
- when the product detects an update it signals the LocalSystem service (Serv.exe) and then terminates itself
- Serv.exe will then perform all the updating
Now, after everything is done, the product (via start.exe) needs to be launched again automatically ... and this is where I need some advice ... what is the best way to restart the product (start.exe)?
Right now I use the LocalSystem Service (Serv.exe) and impersonate the USER account as follows:
- CreateEnvironmentBlock for the USER
- CreateProcessAsUser(start.exe) as the USER with the corresponding EnvBlock
- DestroyEnvironmentBlock
But is this really 100% equivalent to double-clicking on the icon in the USER account context? I need to ensure that everything is identical when it is either launched on STARTUP of USER or by Impersonation from Serv.exe (LocalSystem) - is there a risk involved? Will I still have the same rights/abilities with all databases? registry? device interaction? etc..
By loading the EnvBlock I seem to get everything I need but ... is this not a good way to do it...?
Kind of hoping for some guidance and advice from the pro's out there ...
Any help or hints would be much appreciated.
Thanks,
Update: Here is a post named: Launching an interactive process from Windows Service in Windows Vista and later. Which is exactly what you are looking for. It starts with:
The first thing you should do about it is that; don't do it. There are many limitations and bad implications and restrictions involved.
So first test if your current solution works. That depend on what the process is doing. If it is not involving user interaction. Or manipulating the current user session. Then you don't need this complex solution. If you need it, than good luck!
Before update: Its not 100% equivalent. Except authorization there are, in windows, sessions and, in each session, there are desktops. The process that is lunched from the service will run on the service session and desktop ( if the service has it). Depending on what the start.exe does, it may be important or not.
Look at the SetTokenInformation function.
Instead of launching the application directly as a "startup item" you could start a "launcher.exe" that then would launch your application. The service could then signal "launcher.exe" that another instance of the application should start after an update. Using this method you can't use the service to update "launcher.exe", but this executable should be very simple and hopefully not require any updates. Using this method would avoid all the pitfalls of trying to start an interactive application from a service.