Is it possible to write a self-destructive program in C?
Asked Answered
H

5

11

Is it possible to write a program in C that upon execution deletes itself (the binary) and then terminates successfully. If so, what's the easiest way of doing this?

Hubing answered 1/4, 2012 at 14:32 Comment(1)
It is probably possible to write a program that deletes the .exe file or whatever, though you may have to jump through some hoops since in some environments the OS locks the .exe while executing it.Xanthochroid
Q
15

Yes.

#include <unistd.h>
int main(int argc, char* argv[])
{
  return unlink(argv[0]);
}

(Tested and works.)

Note that if argv[0] does not point to the binary (rewritten by caller) this will not work. Similarly if run through a symlink then the symlink, not the binary, will be deleted.

Also if the file has multiple hard links, only the called link will be removed.

Quench answered 1/4, 2012 at 14:35 Comment(7)
Here we get into the usual business about the reliability of argv[0] as the path to the binary. POSIX says that is should point to the binary, but does not require it and the API allows programs to set it to something else. The end result is, this usually works, but is not reliable. Moreover, even if you have a correct path, the binary may be hardlinked in more than one place.Harlamert
Doesn't actually work. @LuchianGrigore is right, after calling unlink add a sleep(30), then while the program is asleep run "lsof" in another terminal (this is a *nix utility) and you will see that the OS still has a handle to the file open. The file is gone from "ls" but it does still exist until the program ends and the OS closes its handle.Kimkimball
@Kimkimball - Yes it does. Upon completing execution, is it or is it not gone from the file system? At least that's what I was asking how to do.Hubing
@dmckee I'm interested in an example that deals with that situation.Quench
As far as I know there isn't a completely standard solution. You may be able to finesse it on linux using the /proc pseudo-filesystem.Harlamert
This answer could be really fun if it's a suid-root binary trying to delete itself... ;-)Sutra
This is not a solution using C. unlink is POSIX, not part of the requirement.Creed
A
5

I do not know that one can conveniently do it in a truly platform-independent way, but you didn't specify platform independence, so try the following, Linux-style code:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv) {
    printf("Read carefully!  You cannot print this message again.\n");
    return unlink(argv[0]);
}

How close is that to what you want?

Allpurpose answered 1/4, 2012 at 14:41 Comment(6)
That is the wackiest typing of arguments to main() I have ever seen.Quench
Those are non-standard arguments to main, incidentally. Given that, it only serves to make your example code harder for a newcomer to understand...Marmoset
By popular demand, I am revising my answer now! [I will however note that my GCC 4.4 compiler, if invoked with the -Wall and -Wextra switches, emits a warning if I fail to precede int argc with __attribute__((unused)) in this particular example. The reason is, of course, that argc is here unused.]Allpurpose
@OliCharlesworth is rightly a stickler for the standard. I had thought that I was, too, until I encountered him, but he takes it to another level. But for his comment, I would say that it lay in the freedom of the programmer to receive variable arguments as constant parameters, and that it were prudent to make most objects const when one does not mean to vary them. However, there may remain some hidden problem with my consts that Oli sees and I do not. Nonetheless, my consts have proved a distraction, so I have removed them. They weren't the main point of my answer, anyway.Allpurpose
@thb: In practice, it won't hurt anything in this situation. But in the general case, a T** is not convertible to a const T**, so it's best not to conflate the two.Marmoset
Well, I have learned something today. @OliCharlesworth has earlier noted c-faq.com/ansi/constmismatch.html, which explains his point. Interesting.Allpurpose
E
2

If you operating system allows a running program to delete its own binary, then just look for the API for file deletion, or execute a corresponding system() command.

If the OS doesn't allow this, your program (let's call it A) could construct another binary, containing another program (let's call it B). Then, A would immediately quit.

Program B would have a single loop checking if A is still running and as soon as A quits, B would erase A's binary.

Evacuation answered 1/4, 2012 at 14:37 Comment(4)
Well, the mission was to kill A, wasn't it? B can rest in some temp folder and wait to be swept off sometime.Evacuation
@Evacuation if the objective was to destroy any evidence of the original file then that will certainly workHubing
@DavidSouther +1 for Jargon File legend referenceQuench
@AlexCoplan Ok, to destroy any evidence we should also write some zeros onto the file's original position on disk ;)Evacuation
G
0

You could try to just delete the executable in the program (FILE* and stuff)... but seeing as that executable is what's being run it might not work. I see it like eating yourself, and as far as I know it's not possible, but you could certainly give it a try using the method I mentioned above.

Gainly answered 1/4, 2012 at 14:36 Comment(0)
O
0

I think it is dependent on the platform you are using. Basically, once the executable is loaded, any subsequent change to the binary does not affect the running program. In Unix, this is the case, and you can use the unlink system call.

I am not sure whether this is true on Windows or not. It may not be allowed to delete the executable image. You can try the DeleteFile() api in Windows.

Orian answered 1/4, 2012 at 14:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.