views:

200

answers:

10

How can I protect my C# app from someone killing its process via taskman or programmatically?

Here is my scenario:

App A is an MFC app developed by another team. It has an unpublished text-based remote interface that is enabled via a backdoor.

I'm developing app B, a C# WinForms app which interacts with A. B enables A's backdoor when it needs remote access closes it when finished (or on failure).

I'm exploring ways users could abuse B in order to gain access to A's hidden functionality, such as killing B's process after it has enabled A's remote interface. I'd like have one last chance for B to close A's backdoor when that happens.

B uses localhost to interact with A, so I'm not worried about the power-down scenario.

I'm looking for a solution that doesn't involve changing A.

I'm not expecting to be able to stop Dark Tangent (though that would be a bonus), but right now a script kiddie could have his way with this design :)

These apps run on Windows XP, but will also soon support Vista & 7.

Thanks in advance, Jim

A: 

Why would you want to do that?

daedalus0x1a4
+4  A: 

You really, really, really don't want to do this. It makes users very angry!! However, if it is supposed to be a service, run it as a service account and don't give admin rights to users.

George
See my edited post.
Jim C
It's a WinForms app.
Jim C
+1  A: 

Short answer: you can't and you shouldn't.

Long answer: You can try to start a second 'helper' process, that checks every x seconds if your app is still running. If it isn't, it restarts it.

If you want a process to run for a long time just don't trust users to keep it running, consider windows services. They are designed for this.

Jouke van der Maas
A: 

As far as i know you can't, and even if you could you really shouldn't. imagine how annoying it would be if you couldn't force kill an application.

If its important that your application keep running you could always create a windows service that "pings" the application to ensure it is running (you could use named pipes, sockets, pid files... whatever). if the service detects that the process has died then it can just restart it. this is probably your best bet.

luke
+2  A: 

I'm willing shut the app down when they try but need to do some things first.

Having necessary steps at program shutdown leads to fragile programs that break easily. Even if you could prevent someone from killing your program via the task manager, you cannot stop them from turning off the computer, or even pulling the cable out of the wall. Whatever task that was so vitally important to complete will be lost. And what if there is a power cut? Again your task won't complete and your vital clean up code will not be run.

Instead you should make your program robust to failures at any point. Use transactions, and always save state to files atomically - make sure that you always have at least one valid copy of your data. Don't overwrite important files in a way that they become temporarily invalid.

Finally, you can add a dialog box to your program that when they try to close it, warns them that the program needs to shut down properly. If you make your shutdown fast users won't want to kill it and will let it terminate properly. If your shutdown takes ages then people will try to kill it. If you are nice to your users, they will be nice to you too.

If shutting down fast means that the user will lose some unfinished work then warn them about this and give them the opportunity to wait for the task to finish, but if they really want to quit your program then let them quit.

Mark Byers
You're making a broad assumption for someone who comes on so strongly...Specifically you're assuming WHY he wants to run anything on app kill. There are reasons to make sure you run shut down other than having dirty writes/still open transactions out there. Mostly closing down any child processes or other resources.
Jim Leonardo
I've had this problem once. I had a process that used semaphores to communicate with other instances of itself. If you terminated it wrong, it would leave an unknown number of counts left on the semaphore, messing up all the other instances.
Gabe
@Jim Leonardo: Another way to approach the problem you mention is to have the child processes programmed more robustly to correctly handle the condition that the parent program was aborted suddenly. Robustness in distributed application is increased if each component able to function sensibly independently of the others.
Mark Byers
+2  A: 

You can't - as long as the user has the right to call TerminateProcess on your program, you can't prevent End Process from killing you immediately in task manager. Raymond Chen posted on this some time ago: http://blogs.msdn.com/b/oldnewthing/archive/2004/02/16/73780.aspx

Michael
Then you've never seen the virus that stops the user from opening the task manager, control panel, or MSCONFIG? My friend caught this by clicking on the "You have a virus!" banner. Painful.
Phil
@Phil - even I wouldn't go that evil :) Anyway, one could write an app that would execute TerminateProcess programmatically, so protecting against GUI-based termination isn't sufficient.
Jim C
@Michael - In the end, the discussion in the link you provided convinced me of my folly. I'm going to push back on the A team.
Jim C
+2  A: 

I think everybody has missed the point. If I read it correctly (after your edit) you wish to know when you are being "killed" so you can shut down gracefully?

The point of "killing" is that you "can't" stop it. There are of course workarounds like using a second app to revive a killed app, but that has nothing to do with simply being able to shut down gracefully.

The best approach is to either run as a service (so you can't be killed, just asked to shut down), or to restructure the way your app works so that it doesn't need to "tidy up" before it quits. When an app is quit, most resources it holds are automatically cleaned up, so it's only really your own data that you have to close cleanly. Approaches you could try are:

  • Frequently commit your state to disk so that you don't lose much (or anything) if you are unexpectedly quit. (Remember to flush all I/O streams to be sure they are committed to disk)
  • Save information to disk that allows you to detect an unexpected shutdown the next time your program runs, so it is able to detect and rectify whatever problems might have been caused by being killed.
  • Tell your users not to be idiots, and quit your application nicely. Poke them in the eye if they ignore you. Usually after no more than two times they listen :-)
Jason Williams
Service can be killed.
Rohit
+1 for "do the recovery the next time the app starts", since unexpected shutdowns do happen (power event, disk failure, etc)
Ben Voigt
@rohit - Many users know how to kill tasks. Relatively few know how to Stop a service, let alone *Kill* one.
Jason Williams
@jason service appears like process a.exe so not that difficult. Yes stopping a service is unknown.
Rohit
@rohit: what OS are you running? Services don't appear as Applications or as Processes on XP, Vista or Win7 task managers. On XP you have to run "services.exe" to even see the services, while on V/W7 there is a new TM tab that lists the services but only admins can stop them. There is no option in any of the above to "kill" a service. Thus I contend that few users will know how to kill a service using built-in OS software. (Or you're talking about a Windows UI I've simply never noticed?)
Jason Williams
I am already doing your first 2 bullets, though this question really isn't about data loss. Did some research on killing services. Converting B to a service won't work for me, though.
Jim C
@Jason Williams: running services are visible in Task Manager, under Processes tab, just as any other running process. I have Administrator privileges, and have just run some custom service of my own (it was visible that it was running under SYSTEM user), and killed it afterwards using Task Manager, which changed service to Stopped state.
mr.b
@mr.b: The processes tab shows *processes*, which may include processes related to *some* services. My ancient XP box reports (as admin) 31 processes for all users, but services.exe lists 96 available services and 46 running ones. Maybe you have configured your PC specially, but normal users can't see or kill most services from the XP T.M. In Vista and Win7 the TM has an extra *Services* tab which does list the services (from which you can stop *but still not kill* services), but again only *processes* are shown in the Processes list.
Jason Williams
@Jason: Sorry, I have misunderstood your statement then. And yes, you are right that not all services are visible in TM processes tab even on my system.
mr.b
A: 

When the application initiates for the first time could you not execute a 3rd ap/process that is running in the background and attempts to callback to App B every so ofter, so when that App B is closed.. App C can see that and executes a procedure to close App A's backdoor.

So that when App B closes successfully via the intended Close button it will disable App C from checking App B is still working fine...

Im not really the best with C# at the moment but looking at your problem thats probably one of the ways i would try to do it..

Also if App B checks App C aswell then if App C has gone down App B will close the backdoor if it can.

As the others say this may not be a good idea tho.

RobertPitt
Interesting. Unfortunately, "App B" actually represents a class of applications, each of which manipulates the back door. Although only one B is running at at time, this would complicate how a 3rd app/service would be able to monitor B's existence.
Jim C
AS I said and I apologise for the lack of skills in this area but my comment was based in what I thought would be possible and how I would go about resolving a situation like so. Creating and Deploying this on my side is not going to a strong point, I was merely trying to give you a practical solution. your the man to work out how to.
RobertPitt
Ya, I realize that. Not looking for you to write my code, just giving you more info regarding the B concept.
Jim C
A: 

In order to prevent your application from being terminated, you run your application as another user (i.e. as a service, or as another user account), and limit users to be Standard User.

This way no malicious users can kill your process, since only administrators can kill it, and that is a privilege that you, apparently, don't trust anyone with.

It has the advantage of following the intended design of the operating system.

Ian Boyd
A: 

@Jim

If App A can receive modification requests

  1. Preferably, I would an architecture where all App B's are registered upon opening the backdoor and are required to ping App A with the registration at an interval so that App A can close it's own backdoor upon App B not informing it that it still needs access. This is still not perfectly secure but App A should not be structured with such an interface without some sort of self regulation for "secure" means of communication.

  2. Or, you could suggest App A be modified to check for valid processes and if none are found while it's backdoor is open then it gets closed (this is spoofable since it goes by processed name).

Otherwise, it sounds like App B should shut the backdoor as often as possible when it does not need immediate access.

Requiring an App B to provide security of access to App A is a poor model indeed.

Jamie Altizer
B does shut the backdoor when the task is complete. I agree, A is not optimally designed.
Jim C