Installing a Windows Service as a user - c#

I'm currently in the process of creating a Windows service application which will monitor changes to certain keys made in the HKEY_USERS registry. The way I do this is by collecting the SID of the current user. The issue I'm having is that its returning the administrators SID due to the service currently running as local system.
What I need the system to do is collect and return the SID of the currently logged in user (by this I dont mean the local service, local system or network service but the person whos logged into windows via the GINA), so what I need the service to do is run as that user. This will also allow the service to write back to the users network drive which is the intention of this program.
The issue I'm having is that when I try and install a user service using installutil.exe it asks for a username and password now I've tried my own credentials (I have an admin and non admin account) but it isn't having any of it plus I want the user to change depending on the person logging on and not to be fixed. Is there any way to do this?

The "The current user" assumption is a desktop Windows concept, and with Fast User Switching even that is not true anymore. The Windows services layer is rather common across desktop and server variants, and doesn't really deal well with this. It sits below the interactive sessions layer. One of the ways this manifests itself is in the ability to run services even if there are zero users logged in.

This all seems a bit confused. There can be any number of people logged on via remote desktops etc. If you as a service want to see their registry, you definitely wont get there via HKCU. If you want something like this, you should be using an autorun exe rather than a service. Anything like inspecting sessions and injecting stuff into them to access the loaded registry hive in the session is way overkill and not likely to be clean in any way.

You can find a process that runs with every user like explorer.exe then get the SID of the user that runs the process (you can use WMI like in the function here)

Related

Get a list of mapped drives as a Windows service.

I'm trying to get a list of mapped drives on my machine as a Windows service. I can get a proper list if I run my code as a normal program, but not as a Windows service. I've seen several posts regarding this topic but none give a clear solution.
I'm running the service on the same account that created the service, and the service has admin rights.
Does anyone know how to properly do this?
It is not possible
please see the following MSDN article
https://msdn.microsoft.com/en-us/library/windows/desktop/ms685143%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
If a service is configured to run under a user account, the system always creates a new logon session for the user and starts the service in that new logon session. Therefore, a service cannot manage the drive mappings established within the user's other sessions.
If you are in Windows 7 with UAC enabled, then the administrative session has different mapped drives then the regular user session. Open an administrative command prompt and run net show and check the mapped drive status.
Update: I have EnabledLinkedConnections set on my Windows 10 workstation so I don't see this issue there.

Stand alone WPF application using a service ID or like

I've been asked to write a C# application to run on a Windows 7 machine to display the time of day, weather, etc.. That I can do. What I'm looking for is guidance to run the application on a Windows7 machine without logging as a user. In essence the machine would simply be a CPU with a screen. No keyboard or mouse. I've seen deployments done on MS-PixelSense (use to be MS-Surface) using a service ID.
If I need to signin, user policies kick in, screen savers enable, etc.. I'm assuming if I use an automatic Service ID, I can let the application override most of the settings keeping the screen on and needed privileges assigned / locked down to the service ID.
Any information / suggestions are appreciated....
First, some background informations:
Accessing a network share
If a process running on your client wants to access a (CIFS) share, it has to be run under a user account (or "Service ID") which has access rights to this share. There is a way (if the client is a member of Active Directory) that the machine name appended with $ (which is in fact the machine account’s name in AD) has to be entered in the ACL (Share / NTFS), but this is not a very "usual" way.
See also https://serverfault.com/questions/41130/network-service-account-accessing-a-folder-share
Windows Service running under a user account (aka technical account or Service ID)
A service running under a user account cannot access the GUI. There are some tricks, and some years ago I wrote a tool which allows a service to start another GUI program, where the GUI is displayed above the Ctrl-Alt-Del dialog. But this does not work under Windows 7 anymore.
But even a service which runs under local system cannot display a GUI on the logon screen.
You would have to write a Credential Provider.
See
Windows service showing a GUI when no user is logged in
https://stackoverflow.com/a/3074040/4547223
Another very deep technically article. It says it is possible to display a GUI on the secure desktop / logon screen. I have not yet tested this myself:
http://calebdelnay.com/blog/2012/01/displaying-a-program-on-the-windows-secure-desktop
Autologon
The most well known way is still the "classic" autologin.
See https://security.stackexchange.com/questions/10170/how-secure-is-windows-auto-logon for some explanations and links.
The medium secure way is to store the password as LSA secret (can be done in C# with P/Invoke or with some tools).
If I need to signin, user policies kick in, screen savers enable, etc.
Yes, but this can be handled, you probably have to create an own AD OU with an own policy for that.
I'm assuming if I use an automatic Service ID, I can let the application override most of the settings keeping the screen on and needed privileges assigned / locked down to the service ID.
A service ID /technical account is basically the same as a normal personal user account.
In some Active Directory enterprise environments a technical account has restrictions that it cannot log on interactively and other restrictions. But it still IS a "user account"
Logonexpert (http://www.logonexpert.com/)
I tested this (trial version). It is a nice, small tool which does it’s job. It is more safe than "normal autologon", however in the end, it is not much different from normal classic autologon. One benefit: it stores the password more recurely, but in theory, some hacker may still decompile the program and find out a way to decrypt it. And more important for you: Beside the more safe password store, it does not gain you much. You still have a user login same as normal autologon.
A few suggestions
Probably you can use a local user account on the client system and use normal autologon mechanism. And then you should consider that the client system does not poll for new data on a network share, but instead another server program (implemented as a service, running under a technical domain account) pushes data on a network share on the client.
Doing it this way, the client code does not need to access network shares, with the benefit, that a malicious attacker also has no access to network shares.
If you really need to access a network share from the local user context, you can probably logon to the server, as explained in my answer here:
https://stackoverflow.com/a/28749093/4547223
You have to to change the registry code part with the access to the CIFS share.
But doing it this way, you again have a password, which you have to encrypt and store. I do not recommend this.
In the end...
Windows does not make it easy what you want to do. If you are not strictly bound to Windows, you can consider using a Raspberry Pi with Raspbian (a Debian derived Linux). You can install Chromium browser, which displays a web page on the server and updates automatically. We use this with great success for some time.

how to hide .net app from process list

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.

Is it possible to use WMI in a Windows service?

I'm writing a simple service to set the default printer based on where I'm connected, but I'm having trouble using WMI in my service. The more I think about it the less I think it's possible to do what I'm trying to do; as a service is not associated with a particular user, but I thought I would ask about it anyway in case my suspicions are wrong.
Here is what I'm doing.
Service subscribes to NetworkChange.NetworkAvailabilityChanged event.
When event is received query WMI SELECT * FROM Win32_Printer WHERE Network=true.
Loop through the ManagementObjectCollection and check the status of each printer.
If the printer is connected call ManagementObject.InvokeMethod("SetDefaultPrinter",null)
When I check the Security event log I noticed Failure Audit events "Unknown username or bad password", which I'm assuming is because I did not explicitly supply that information.
Is there a way to do this without specifying a username and password, or are credentials required for security purposes?
The service must run as some user, for example NETWORK SERVICE, LOCAL SERVICE or SYSTEM. You need to make sure the given account has permission to do what you want.
To change the permission of a deployed service on Windows go to Start > Administrative Tools > Services then you can change the service account for a given service.
I know this is an old question but i feel the existing answer doesn't quite provide a manageable solution.
As pointed out to effect a users default printer selection you need to be authenticated as that user and whilst it is possible to set a windows service to logon as a specific user a better solution would be to ...
Create a winforms program using a hidden form and launch it when the user logs on using Task Scheduler.
This way the PC can be used by many users and benefit from the application without having to change the service logon settings.
I suggested a winforms application as it has a low entry bar, you can use any other kind of invisible from a UI perspective project type.
you should use linqtowmi for this it works great!

Launching a program using LocalSystem Service CreateProcessAsUser equivalent to double-clicking on the icon when logged in? [C#]

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.

Categories