How can I write an unkillable program, redux


A customer wanted to know how to write an unkillable process. Specifically, they want to write a program that runs continuously in the background, and they don't want the logged-in used (who is not an administrator) to be able to terminate it. They wanted to know if there was a way to hide the program from Task Manager, so the user cannot click "End Task".

The usual way to prevent a user from killing a program is to run the program as some other user. Users can kill their own programs (by virtue of being the owner), but they cannot kill programs that are owned by others, unless they have administrator privileges, or something administrator-equivalent like debug privilege, or unless the program permits others to terminate it.

"To clarify the scenario: This program needs to display a message to the user. Therefore, it cannot run as a service, because that would open the service to a shatter attack. The message is one to tell the user that the work day is over and they need to wrap things up and go home. We found that users are killing the program to make the message go away."

Okay, so what we really have here is a social problem, not a technical one. You want to remind the user to go home. Those that want to keep working are killing the program. You think the solution is to make the program unkillable, but that really doesn't change the situation. Even if you made the program unkillable, the user can simply ignore the message. There's nothing you can do to make a user pay attention to a message. If they want to ignore it, then they will ignore it.

"Yes, that was my advice to the customer, but the customer isn't looking for a solution. They just want an answer. They absolutely want to write the program that displays the 'Go home' message and make it unkillable."

What you can do is have a service inject the program into the session, and let it run as the logged-on user. (You have to make it run as the logged-on user in order to avoid a shatter attack.) The service can monitor the program, and if the user terminates it, the service can log an entry to the security event log, and you can roll up those events into a report so you can see which users are killing the reminder app, then apply appropriate social pressure.

If you want to be really annoying about it, you can even relaunch the app that displays the "Go home" message. Of course, that'll just trigger Le Chatelier's Principle for complex systems: The user will write a script that kills the app as soon as it is relaunched, or attack the app so it doesn't show the message in the first place.

If you want to make sure the user goes home, you can have the service lock the workstation and set a restricted logon policy so the user cannot log back in until 9am the next morning. The service can inject a program into the session to display a countdown timer. In this case, the user can terminate the countdown timer app all they want; that's not going to stop the workstation from being locked. They're just shooting the messenger.

Comments (52)
  1. Brian_EE says:

    At first I wondered why an employer would want to force employees to go home. But then maybe these employees are paid by the hour and the employer wants to control overtime pay costs.

    1. Boris says:

      Employees can unilaterally decide to have overtime and that’s it?

      1. Brian_EE says:

        I suppose you could fire employees who abuse the process. There is this plain-English analysis: http://www.employmentlawfirms.com/resources/employment/overtime-pay/are-employers-obligated-to-pay-unauthorized-overtime

      2. Max says:

        If an hourly employee does work, they legally have to be paid for all of the time they worked. If the employer wants to limit hours to a certain point, it’s their responsibility to make sure that employees stop working and go home when they hit those limits. If an employee ignores the schedule and decides to keep working for one extra hour, the employer is required to pay them for that hour (including overtime, if applicable), even if they clocked out before doing the work. The law takes a dim view of unpaid work, regardless of the reason.

        1. Rick C says:

          It’s not just work at the end of the day. According to Coyote Blog, he had employees who voluntarily worked through lunch in violation of California labor laws, which say you must be provided a 30-minute or whatever unpaid lunch break where you don’t work. Even when he had them sign a waiver saying they wanted to do it, people would still sue him after the fact. In the end, he had to make working lunches a fireable offense to get people to stop doing it.

        2. BZ says:

          When I was last an hourly employee (3 years ago, not that long), I filled out a timesheet, printed it, and faxed to the agency that employed me every week. If I worked extra hours and didn’t report them, nobody knew. After all, I was the interested party, so it was up to me to get them to pay me. They *could* have set things up in such a way that they did know, but it was in everyone’s best interest to rely on self-reporting. Of course there is room for abuse in such a system (they force you to work overtime without payment, or I report more work time than I really worked), but any technology-based system to enforce work hours could be gamed in one way or another save for something really draconian like locking you in if you don’t leave or having staff escort you out.

          1. CatCube says:

            BZ,

            And you could possibly sue for those hours you weren’t paid. The company could argue that they didn’t know you were doing it, but if they didn’t discipline people (to include firing) when they found out they were doing this, then you’d probably win.

    2. They may be ensuring the workers don’t go over their limit under the EU Working Time Directive, assuming they’re in the EU.

      I know one of my friends got ordered to go home by both her manager and her union rep when she hit her maximum number of hours when she was working in France at TI.

    3. smf says:

      @Brian_EE I guess when they have solved the problem of getting employees to work on time they need to find something else to do :-)

  2. The MAZZTer says:

    My workplace does this with forced reboots to apply system updates. You can delay them a limited number of times, but eventually it’ll come down to a countdown you can’t stop and then your system forces a reboot.

    1. Brian_EE says:

      Yup. And when you are unfortunate – it happens on the weekend while a multi-day unattended test with data-collection is occurring, and this test data is required to satisfy obligations for a government contract.

    2. smf says:

      That doesn’t make you stop work and go home, that makes you wait for the updates to be installed and then get back to work.

      The problem with forcing the user to logout and then not allow them to login until the next morning is that when the manager decides he wants the users to work outside of hours he cannot make them do so.

      You also don’t want a house that cannot be broken into, because if you lose your keys or the lock breaks then you would have to buy another house.

  3. Antonio Rodríguez says:

    It’s over and over again the same old: “the user doesn’t read this warning, so I will make it system modal an with a 24 pt bright red font”. You are only training the user to click a random button whenever something unexpected pops up. Training him, precisely, not to read your messages.

  4. IanBoyd says:

    I know the concepts of Objects, and ACLs on those objects, run deep in Windows NT. My understanding is that nearly everything is an object, and has a set of discretionary access control lists on those objects.

    Is there an ACL on the Process object? And is there an ACL entry where i can “deny” myself permission to terminate the process? It’s all a very nebulous area in Windows (and this is still after buying a copy of Keith Brown’s Programming Windows Security).

    I read that a process can have the PROCESS_TERMINATE access right (a process has the access right? Not the user), which is “required to terminate a process using TerminateProcess”. Can i remove the PROCESS_TERMINATE access right from my process (GetCurrentProcess) after i startup?

    1. Falcon says:

      Raymond has mentioned before that object owners have WRITE_DAC permission on their objects. Here’s one example: https://blogs.msdn.microsoft.com/oldnewthing/20150610-00/?p=45411/

      So, even if you can deny yourself permission to terminate the process, you can remove the restriction later.

      1. IanBoyd says:

        > even if you can deny yourself permission to terminate the process, you can remove the restriction later.

        Yes *i*, the program, could remove the restriction. But a user would not be able (easily) to remove the deny.

        They would have to inject a thread into my process, and restore the restriction. Not only would that be difficult for an end-user to accomplish, they don’t have required administrative permissions to do it.

        So, *is* there an ACL on a process that controls a user’s ability to terminate the process? MSDN seems to indicate that there is none – that instead there is a right set on the process (not an access control list)

        1. The user can change the ACLs on any object for which he is the owner. If the process is running as the user, then the user can change the ACL and grant himself TERMINATE rights.

          1. Joshua says:

            In this case the user is expected to be a non-programmer, or at least that’s how I read IanBoyd’s comment.

          2. dave says:

            > If the process is running as the user, then the user can change the ACL and grant himself TERMINATE rights.

            He can, but he needs a program to do that. Is there anything in the ‘commonly available Windows program repertoire’ that allows twiddling the DACL on a process? Are these particular users the sort of users that can write programs or find programs in obscure corners of the internets?

          3. alegr1 says:

            I think the process object owner (creator) can be different from the process user token. In which case the user will not be able to do anything with the process, even though the process runs under their account.

            Also, a process can create a desktop, switch to it, and the user will not be able to do anything about that (wonder if Ctrl-Alt-Del will switch it to the main desktop back, or invoke the Task Manager on the second desktop)

          4. Yeah, I think alegr1 is right. Who the program runs as and who owns it / has any rights to it are different things, at least potentially. I’m not sure whether it would be straightforward to create such a process, though, you might need to run through some hoops.

          5. poizan42 says:

            You can just change the owner of the process object. You can try this with Process Hacker. Here I have changed the owner to SYSTEM and removed the other ACLs: http://imgur.com/fvLtc6q. The associated token is still the one for my user: http://imgur.com/b0cBpEi

          6. > Is there anything in the ‘commonly available Windows program repertoire’ that allows twiddling the DACL on a process?

            The debugger is a great tool. You are allowed to debug your own processes, so debug the process and then click “Stop debugging” (which terminates the process). Even non-programmers can be taught to do this. (Actually, since all you want to do is stop the program from annoying you, just patch out the ShowWindow call.)

          7. smf says:

            >Even non-programmers can be taught to do this.

            And teaching non-programmers to do things like this can be very profitable (either in money or favours). The user isn’t your only adversary. Good enough is never good enough.

            You should assume that you’re trying to stop someone who is cleverer than you.

  5. Piotr Siódmak says:

    Next episode: “how do I kill an unkillable program?”

    1. Simon says:

      With the power button, of course.

      1. Falcon says:

        In this particular case, that’s pretty much what they want the users to do!

    2. smf says:

      @Piotr Siódmak

      >Next episode: “how do I kill an unkillable program?”

      The bonus is surely for “how do I kill my competitors unkillable program but prevent them from killing mine?”

  6. Joshua says:

    It turns out there is in fact a solution to this problem. I had to use it when tackling a more annoying variant.

    The solution is to steal the winlogon token for the winlogon process on the active session. You can then use that token to start a process as SYSTEM on that session that has the ability to render windows and receive input. Always handle WM_TIMER even if you don’t use timers and create no standard controls; EM_GETSELTEXT would give somebody else a very good day and you a very bad one.

    1. Don’t see why you’d need the token from winlogon in particular. Duplicating a standard SYSTEM token and changing the Remote Desktop session should have the same effect.

    2. Josh B says:

      Congratulations, you just created another vector for a Shatter attack. That was the whole point of making it a user process, not System, in the first place.

  7. DWalker says:

    You could have the keyboard shock the user, or have the monitor explode, or something, if the user kills the process. :-)

    Yes, these are sociological issues that people want to handle technologically.

  8. Ben says:

    How do shatter attacks work now that UIPI is a thing? Does simply having a window from a process running as SYSTEM in a user’s session effectively give that user SYSTEM privileges?

  9. ZLB says:

    Actually, the customer is asking a reasonable question.

    “I am responsible for these computers and what the users are doing on them. As the supreme lord Administrator of all I survey, how can I ensure a process is running in their session and they don’t keep killing it?”

    Ok. A user unkillable process that runs in the user’s session. That’s not going be misused is it? I’m going to get me a really nice bonus!

    But on the other hand think about things like parental control software. (Activity monitoring/reporting/blocking)

    The network administrator/company/institution may be legally responsible or under a duty of care for the individuals using the computers.

    This leaves us in a state where the choices are:

    1) Just run the application from a service in the user’s session as SYSTEM. Great! Now you have horrible security problems, and you have to impersonate the user for stuff.

    2) Build a privileged app and a user app that chat over IPC. Still not a great solution because the user can kill the user app just as fast as you can re-spawn it. And you’ve lost all the state. So you move more and more of the state, to the privileged app, followed by UI…see point 1 for further details.

    Really, we need some concept of a protected process that runs in the context of the user but the user is not able to fiddle with.

    Other than suggesting some sort of Authenticode signing requirements, I can’t think of a way that this won’t be abused by spyware or the shovelware that seems to be pre-loaded on every laptop these days.

    1. jgh says:

      Could be time-limited access on a public access computer. At my local library when you log on there’s a countdown timer on the task bar. If you kill it it comes back after a couple of seconds. When there’s only five minutes left of your session a window pops up warning you to save everyhting and prepare to log off. At 30 seconds a window pops up with a countdown timer. Even if you keep killing things all apps are killed at the end of your session and the computer soft reboots.

    2. poizan42 says:

      > Really, we need some concept of a protected process that runs in the context of the user but the user is not able to fiddle with.

      There is, you can just change the owner of the process object to SYSTEM and remove the ACLs for the user and session. You can try it yourself with Process Hacker, it seems to work fine as far as I can tell. I can’t do anything with the process afterwards without elevating.

      You may have to be careful with processing windows messages if you really want it to be protected – running it under high integrity is probably the easiest way to avoid this.

    3. Brad Westness says:

      If the employees do most of their work online, you could maybe just do something with the company’s network where all internet access is blocked after a certain time, and any URL request in a browser is intercepted and redirected to a “Go home” message.

  10. 12BitSlab says:

    This is a classic “using technology to solve a management problem” problem. I am sure many here have run into this before.

    Years ago, I was working on a medical system. One of things it had to do was to keep track of patients’ medical records that were in turn supplied to nursing homes. While we were gathering requirements, one of the end users asked if we could add spell checking to the med records stuff since much of it is free form text entered by a user. I replied that conceivably, we could, but we would put that down as a V2 requirement since the systems they were using at the time did not have spell checking.

    After hearing that, a different user asked, “You can do that?” I replied, “We can, but there isn’t time to do that in V1.” He went on to then ask, “If you can do that, can you add a dirty word filter?” To which I replied, “Dirty word filter? What do you mean by that?” He came back and explained that sometimes you have disgruntled employees and they write inappropriate things in the med records just to make the nursing homes mad.”

    I said, “In regards to ‘dirty words’, that is not a technology problem. That is a management problem. Rather than trying to use the system to do a manager’s job, the managers should simply do their job. If they aren’t capable of doing that, you have the wrong managers.”

    He reluctantly agreed that I was correct. I also later found out that he was in charge of the managers who supervise the medical records people.

    The bottom line is that sometimes as developers, we need to be honest with users even if it is not comfortable.

    1. alegr1 says:

      That’s clbuttic feature request.

  11. parkrrrr says:

    Why not create the interactive process as another unprivileged user, perhaps one created for the purpose of running this program? Granted, that potentially gives an attacker a vector by which to make their own process unkillable by the logged-on user as well, but at least it doesn’t give them administrative privileges.

    1. ZLB says:

      This won’t work at all.

      The other unprivileged user doesn’t have access to objects in the users session. Things like the desktop or files.

      The unprivileged user will also not have the impersonate right.

    2. Joshua says:

      Hmmm, this is not so bad; however the implementation is tricky. Logging on the unprivileged user won’t give you access to the desktop. You would have to read the window station’s access rights to find the nonce SID and construct the correct token out of thin air with NtXxxxxxXxxxx undocumented call (if you know the call you can identify it from the mask, and if you can’t find out you should not be using this technique).

      1. ZLB says:

        Ok. I’m on it.

        …hmm. Doesn’t seem to work for all versions of Windows. Is there a AppCompat shim I can manually enable?

    3. parkrrrr says:

      There’s at least a couple ways to get around the desktop issue, I’d think. One obvious way is to use a stub program that runs as SYSTEM on the logged-in user’s desktop, adds appropriate permissions to its own desktop handle, creates the “unkillable” program on that desktop, and terminates. Since the SYSTEM stub doesn’t have a message loop, it’s not vulnerable to shatter attacks. (I’ve just checked my own desktop on a Win7 machine, and it does have WRITE_DAC access for SYSTEM.)
      Access to files is irrelevant for a program like this, I’d think, but if it needs to use specific files it can probably use appropriately-hardened RPC to the system service for whatever access it needs.

  12. Dave Bacher says:

    At one place that I worked, you were authorized to use the computer (or be in the building) specific hours — they had a nag message like this. If you ignored it, you were talking to a security guard both to get out of the building that night and then again to get into the building the next day. That wasn’t about money — they wanted to know who was in the building, when and why.

  13. Dave says:

    Never heard of “shatter attack” till now, but wow that explains a couple things about Windows 7 that I didn’t know before: why the logged on user no longer on session 0 (can’t use tscon 0 /dest:console anymore, have to check which session number to use, though it’s probably 1), and why a service that posts a message box causes this really weird switch to a pocket dimension just to see it.

  14. mvadu says:

    Were they any way related to developers of “Microsoft Office Communicator”? You right click on the notification icon and select “Exit”, and you get a nice balloon saying “Communicator is still running”, they kind of did develop an unkillable program, or more like program which wanted to live on at any cost..

    1. I can never figure out how to exit that app.

      1. Joshua says:

        Assuming it’s the same one I briefly used to enable Outlook 2003 to talk to exchange online, I couldn’t really find a use case to exit it. It’s more like a service that happens to care what user is logged in than any normal desktop app.

      2. smf says:

        >I can never figure out how to exit that app.

        What is it worth to you?

  15. Dennis says:

    I think the customer is deleted and the program in question is deleted. [Remember the ground rules. -Raymond]

  16. Petro says:

    Just write a service which will use net send to deliver message to user.

Comments are closed.

Skip to main content