5

i am writing a program which includes a windows service and a GUI-program, because the windows service cannot directly communicate with windows.

It is a program which interacts which a server-daemon stopping pupils from logging in with one account at multiple workstations. (to prevent password sharing)

The GUI-process is launched using Windows autostart and runs with the users permissions. Because of that, the users can easily just kill the GUI-process. This is not good because the GUI-process is causing the logoff (and user message).

How can i stop users from killing the process?

Zulakis
  • 7,859
  • 10
  • 42
  • 67
  • Does it need a GUI/WinForms program? Can it not be a command line program? – Arran Jun 19 '12 at 11:09
  • If you can manage with reviving the process each time it is killed and continuing it's work, I have give you something I wrote called "Watch Dogs" - two programs that revive each other when one is killed, and revive a 3rd given process as well. The only way to stop it is to kill both watch dogs very fast (using code) and then killin the 3rd process manually - which is good enough for most cases. – SimpleVar Jun 19 '12 at 11:11
  • @YoryeNathan: It's actually quite easy to kill off that sort of system and doesn't require any code at all. – Skizz Jun 19 '12 at 11:13
  • @Skizz Elaborate please? How could you do that without code? – SimpleVar Jun 19 '12 at 11:14
  • 2
    @YoryeNathan: Get hold of the SysInternals Process Explorer (from here: http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx). Locate the processes and change their state to suspended. Once suspended, kill them. – Skizz Jun 19 '12 at 11:18
  • A reliable way to make a user process temporarily unkillable (even by an administrator) is to initiate an overlapped non-buffered read. The process is not killable by any means other than pulling the plug. Of course that's not the cleanest or most resource-conserving thing in the world... but it may give you a starting point to search. Linux calls this "D state", no idea what Windows calls it. There are probably other more or less dirty ways of putting a process into this state. Or, like Yorye said, just restart the process, this is 99% good if done with a little thought. – Damon Jun 19 '12 at 11:20
  • @Skizz Very nice! Though I wouldn't think that most users knew about Process Explorer? I suppose my solution is good enough for some cases, and isn't for others. – SimpleVar Jun 19 '12 at 11:22
  • why not just set up the server to allow 1 connection per user? – msam Jun 19 '12 at 11:34
  • Running a samba server, this is not possible. – Zulakis Jun 19 '12 at 12:15
  • You haven't explained why logging in multiple times is a problem? What behaviour are you trying to suppress? Students wouldn't submit work using someone else's credentials and they wouldn't give out their credentials to potentially malevolent students. If you keep good server logs, you could easily check for multiple logins when you suspect unacceptable behaviour. – Skizz Jun 19 '12 at 12:49

8 Answers8

9

Since you don't have the option of using OS security to prevent this, the technical answer is that it cannot be done. That leaves only workarounds or alternative approaches.

One workaround that is not officially supported, relies on undocumented features and which you didn't hear from me is this:

public static class Unkillable
{
    [DllImport("ntdll.dll", SetLastError = true)]
    private static extern void RtlSetProcessIsCritical(UInt32 v1, UInt32 v2, UInt32 v3);

    public static void MakeProcessUnkillable()
    {
        Process.EnterDebugMode();
        RtlSetProcessIsCritical(1, 0, 0);
    }

    public static void MakeProcessKillable()
    {
        RtlSetProcessIsCritical(0, 0, 0);
    }
}

After you call Unkillable.MakeProcessUnkillable, killing the process will result in an immediate BSOD. This is a really ugly solution, but it's hard to argue against "can be implemented in 2 minutes".

Another workaround would be to create a group of processes that cooperate by relaunching each other whenever one dies.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • 2
    "Didn't hear for me" - Lol! Cute solution, except the BSOD part. I wouldn't want to cause BSOD when killed, personally. I would prefer just... not dying. – SimpleVar Jun 19 '12 at 11:14
  • Where did he say that he can't use OS security? I think we should really be suggesting _that_ instead :) – Roman Starkov Jun 19 '12 at 11:14
  • @romkyns: "runs with the user's permissions" -- therefore the user can kill it. – Jon Jun 19 '12 at 11:16
  • Since the users don't have admin rights, I assume `EnterDebugMode` would fail? In other words, an app that doesn't have admin rights can't do this to itself. – Roman Starkov Jun 19 '12 at 12:01
  • This doesn't seem to work with normal user permissions. The proccess starts and immediately closes. My code: static class Program { [DllImport("ntdll.dll", SetLastError = true)] private static extern void RtlSetProcessIsCritical(UInt32 v1, UInt32 v2, UInt32 v3); static void Main() { MakeProcessUnkillable(); } public static void MakeProcessUnkillable() { Process.EnterDebugMode(); RtlSetProcessIsCritical(1, 0, 0); } } – Zulakis Jun 19 '12 at 12:13
  • @romkyns: Could be, I have not tested this under different permission scenarios. Can you verify? – Jon Jun 19 '12 at 12:16
  • @Zulakis: Possibly because of what romkyns is talking about. I have not tried this myself from a non-privileged account. – Jon Jun 19 '12 at 12:16
  • 1
    OK, confirmed. `EnterDebugMode` gives the process `SeDebugPrivilege`, which is the highest privilege available. No secure system can possibly offer a way for a standard user process to obtain this. – Roman Starkov Jun 19 '12 at 12:25
  • Yes, romkyns is right. Because of this, it doesn't seem like a working solution for me. – Zulakis Jun 19 '12 at 12:26
  • @Zulakis: Well, it might be for the better. This is not a clean solution anyway :) – Jon Jun 19 '12 at 13:01
3

The GUI-process is launched using Windows autostart and runs with the users permissions. Because of that, the users can easily just kill the GUI-process.

How about this: you run the GUI process to show them the message, but you use the service to actually log off. Then they can kill the GUI process all they want, without affecting the primary function of your software.

Community
  • 1
  • 1
Roman Starkov
  • 59,298
  • 38
  • 251
  • 324
  • The students don't have admin rights. How can i start the process with different rights on user login? – Zulakis Jun 19 '12 at 11:52
  • @Zulakis I believe you can use the Task Scheduler to do that. Set Trigger to Log On, and use the "Run As" option. However, I've updated my answer with an alternative approach which I think will work out better. – Roman Starkov Jun 19 '12 at 11:57
  • @Zulakis [this question](http://stackoverflow.com/questions/267838/how-can-a-windows-service-execute-a-gui-application) suggests how a service could start a process as a different user, but it also explains that this is probably a bad idea. – Roman Starkov Jun 19 '12 at 12:00
  • I also thought about your first suggestion, but it looks pretty complicated. What i use is: ""[DllImport("user32.dll")] public static extern int ExitWindowsEx(int uFlags, int dwReserved); ExitWindowsEx(0x10, 0);"" I would rather use a simple solution. Isn't there a easy way to have a program autostart with other user rights? – Zulakis Jun 19 '12 at 12:23
  • @Zulakis I personally think Task Scheduler approach is pretty easy. You need to store the other user's credentials securely, so there's a limit to how easy this can be made. – Roman Starkov Jun 19 '12 at 12:26
  • While trying to use Task Scheduler i ran into another problem which i posted here: http://stackoverflow.com/questions/11102732/windows-task-scheduler – Zulakis Jun 19 '12 at 14:07
  • @Zulakis I'm afraid I can't help there, I was actually assuming Win7. You might get better help with that kind of problem at [serverfault.com](http://serverfault.com/about) – Roman Starkov Jun 19 '12 at 16:33
1

Perhaps you should configure your network better. If your domain is set up properly, you can set up a logon script that checks with the domain controller to see if the user is already logged on, logging them off if they are logged in somewhere else.

I assume each PC is set up with the appropriate account settings (i.e. not as administrators).

The logon scripts can also do other stuff like set up network shares.

Skizz
  • 69,698
  • 10
  • 71
  • 108
  • We have logon scripts of course. But these don't help if the students just plug the network cord. – Zulakis Jun 19 '12 at 11:51
1

i know this is old but it may help another one which are reading this.

You can do that in 5 ways:

  1. Have a signed kernel driver and run your process as protected through it. (the most recommended)

  2. Use RtlSetProcessIsCritical() in ntdll.dll to flag your process as a critical system process.

  3. Make 2 processes. If one terminates the other one starts it.

  4. Use System Exploits to gain Kernel Privilges or load an unsigned kernel driver.

  5. This technique is being used by usermode rootkits. It hooks functions in task manager (some rootkits even hook all processes that they can hook not task manager alone) and the function it hooks is TerminateProcess to return ERROR_ACCESS_DENIED if it tried to terminate your process. If it wasn't your process then it will continue with termination normally. I don't recommend this technique because a lot of AV's will flag it as a rootkit.

0

You could look into the rootkit style method of hiding the process from the task manager. It's not a particularly elegant solution.

arpz
  • 641
  • 5
  • 9
0

You can make a process difficult to kill using this code (plain C, sorry, but it shouldn't be too difficult to port to C#).

Technically this doesn't prevent the user from killing the process, since they can change the permissions, but they would need to write code or use a specially designed tool to do so. Neither task manager nor pskill will work, unless the user has admin privilege.

It might be possible to prevent the non-admin user from changing the permissions back by having the service use backup/restore privilege to take ownership of the process.

Community
  • 1
  • 1
Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
0

I finally ended up using a alternative RunAs program, CPAU, to start the process as Administrator on logon. Doing this, students can atleast not kill it that easily using Taskmanager or similar.

I might also implement the method suggested by Jon later. This way, even if students somehow manage to kill the process they will not succeed.

Community
  • 1
  • 1
Zulakis
  • 7,859
  • 10
  • 42
  • 67
-2

You should not disallow user to kill your application. If the service fail after GUI shoutdown then you should fix the Service not GUI.

But if you really would like to stop application close look here

Community
  • 1
  • 1