24

How can I make my C# app erase itself (self-destruct)? Here's two ways that I think might work:

  • Supply another program that deletes the main program. How is this deleter program deleted then, though?
  • Create a process to CMD that waits a few seconds then deletes your file. During those few seconds, you close your application.

Both of those methods seem inefficient. I have a feeling that there's some built-in flag or something in Windows that allows for such stuff. How should I do it? Also, can you provide some sample code?

UPDATE: Thanks for all your answers! I'm going to try them, and see where that gets me.

First of all, some people have asked why I'd want my app to do this. Here's the answer: a few days ago, I read the Project Aardvark spec that Joel Spolsky posted on his blog, and it mentioned that the client app would delete itself after the remote session. I'm wondering how this works, and how, if I ever need to do this, I can accomplish such a feat.

Here's a little overview of what's been suggested:

  • Create a registry entry that tells Windows to delete the file on reboot
  • Launch CMD with a ping command to wait a few seconds and then delete the file

Both of those, of course, have their disadvantages, as outlined in the comments.

However, would such a method as outlined below work?

There are two executables: Program.exe and Cleaner.exe. The former is the program itself, the latter is the app that deletes Program.exe and itself (if it's loaded into memory, as I'm about to explain). Is it possible for Program.exe (which has dependencies) to load all of Cleaner.exe, which doesn't have any dependencies, into memory and run it?

If this is possible, could Cleaner.exe be packaged inside Program.exe, loaded into memory, and run?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Maxim Zaslavsky
  • 17,787
  • 30
  • 107
  • 173
  • 1
    Do you really need to delete the program or just disable it? I just want to see if I understand the business logic completely because usually completely disabling something is safer than deleting. – Tim C Feb 11 '10 at 14:51
  • Yes, disable it instead of deleting it. –  Feb 11 '10 at 14:52
  • 4
    Why would you need to do this? It sounds like the app is up to no good and you need to get rid of the evidence. – AGoodDisplayName Feb 11 '10 at 14:53
  • 1
    @AGoodDisplayName: Actually there are some reasons to do this. F.e. for a executable which should do something one time only (like opening a remote connection), or enforcing deletion because the license is terminated etc.. – Bobby Feb 11 '10 at 14:57
  • 7
    @Bobby: There's almost always a legitimate reason to do most suspicious-looking things. But for most legitimate reasons, there's usually a better, less-suspicious way of accomplishing the same thing. – John Feminella Feb 11 '10 at 14:59
  • 2
    Why not load it into memory and execute it? – leppie Feb 11 '10 at 15:07
  • 2
    For all the people who are wondering why I'm asking this, here's the answer: yesterday, I read the Project Aardvark spec that Joel Spolsky posted on his blog, and it mentioned that the client app would delete itself after the remote session. I'm wondering how this works, and how, if I ever need to do this, I can accomplish such a feat. – Maxim Zaslavsky Feb 11 '10 at 23:25
  • Looks like I haven't visited my own question in quite a while... time to re-read the answers! – Maxim Zaslavsky Mar 15 '10 at 11:04

11 Answers11

20

There's a MoveFileEx API, which, when given a MOVEFILE_DELAY_UNTIL_REBOOT flag, will delete specified file on next system startup.

Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
10

There's a great CodeProject Article about this topic.

Edit: Basically it's a simple cmd-call which will delete the specified files after some seconds.

Process.Start("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del " + Application.ExecutablePath); 
Application.Exit();
Bobby
  • 11,419
  • 5
  • 44
  • 69
  • 7
    I think this is the "wait a second and then delete" method (2nd bullet from OP). – FrustratedWithFormsDesigner Feb 11 '10 at 14:53
  • For deleting full folder: Process.Start("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & RD /s /q " + Path.GetDirectoryName(Application.ExecutablePath)); Application.Exit(); – Glebka Sep 05 '18 at 13:19
  • 1
    Probably moved here: https://www.codeproject.com/Articles/31454/How-To-Make-Your-Application-Delete-Itself-Immedia – Engin Feb 15 '21 at 20:03
  • I also needed to specify `WorkingDirectory` for ProcessStartInfo. Otherwise cmd was started in the same directory and the folder was not deleted – mihails.kuzmins Jan 06 '22 at 10:13
7

You will never be able to guarantee that this will work, as long as you require a physical presence on the machine. For example:

  • What if the app fails to release a resource in a timely fashion while you're trying to delete it? An error occurs, and the app remains.
  • The behavior of one app starting another which then deletes the first app is very suspicious from an AV perspective. You are likely to trigger defenses on a user's machine which may kill the process that's trying to kill your original app.
  • If you do something like delete a file at reboot, what if the user moves your file in between or makes a copy? It's not in the original spot anymore, and the app remains.

If your application requires this level of security, consider hosting it on a machine you control (e.g., by providing a web service and letting a stub client access it that way).

On a somewhat related note, one is also tempted to speculate about the motives of someone who (1) requires a physical presence on someone's machine and (2) wants to delete the evidence that the app existed.

John Feminella
  • 303,634
  • 46
  • 339
  • 357
  • 1
    some of the problem of the delete on reboot an be fixed by storing the app in temporary files, hardly anyone looks there i bet – RCIX Feb 13 '10 at 23:29
  • _Theoretically_ something should be possible. RAM is volatile, so if you put the program in memory, you should be able to wipe it from the HD while it runs. Then, no matter what happens to the machine, it won't come back unless you take a snapshot of memory. I don't know how that would work in practice, though. – Chris Mar 17 '10 at 20:32
  • @Chris: No, because you can't guarantee that the memory supplied by an operating system is bound to volatile storage. (In fact, if this weren't true, it would defeat the entire point of things like virtual memory and ReadyBoost.) – John Feminella Mar 17 '10 at 21:56
  • Ooh, good point. I suppose it improves your odds but doesn't guarantee anything. (@John: Could you improve the odds more by going through the video card's RAM? Is that possible?) – Chris Mar 22 '10 at 14:33
  • @Chris: I'm not sure you could do that in a way that would be hardware-independent. At the least it would require some low-level poking and an end-run around your virtual memory manager. – John Feminella Mar 22 '10 at 15:06
4

A correction to @Bobby answer, in case people will find it useful - executable path needs to be quoted. Additionally, below is setting cmd.exe window to be hidden (otherwise it flashes as a black console window) and converted to run without relying on System.Windows.Forms assembly (the Application class).

 
var exepath = Assembly.GetEntryAssembly().Location;              
var info = new ProcessStartInfo("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del \"" + exepath + "\"");
info.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(info).Dispose();
Environment.Exit(0);
Lev
  • 91
  • 2
  • 5
  • The IP `1.1.1.1` is now taken by CloudFlare, so this will not wait for 3s but return in some ms. – hdev Mar 22 '19 at 07:32
1

Think CMD

int sectosleep = 5000;
string exename = "yourexe.exe";
string location = @"c:\yourexe.exe"
Process.Start("cmd.exe", "/C taskkill /f /im " + exename + " & ping 1.1.1.1 -n 1 -w " + sectosleep + " > Nul & Del /F /Q \"" + location + "\"");

;>

Homer Simpsons
  • 271
  • 1
  • 3
  • 16
1

There is also FileOptions.DeleteOnClose, but that requires the file to be open for writing. You might be able to do it with a sequence like this (untested):

  • Program launches as Original.exe, and detects (from its own name) that it needs to trigger the self-destruct function.
  • Original.exe creates a new file Temp.exe with FileOptions.DeleteOnClose and copies its own content into it, but does not close it yet
  • Original.exe opens a second, read-only handle to Temp.exe and closes the first write handle. The read-only handle can co-exist with an execute handle, whilst keeping the file open to delay auto-deletion.
  • Original.exe launches Temp.exe. Temp.exe detects that it has been launched from the temp directory and bypasses the self-destruct sequence and continues normal operation.
  • Original.exe exits (taking its read-only handle to Temp.exe with it.)
  • Temp.exe continues running. When it exits, the file Temp.exe will no longer be in use so it will be deleted automatically.

Edit #2: Actually I don't think this is possible, because it relies on the kernel opening the file with the FILE_SHARE_DELETE flag, which is unlikely.

finnw
  • 47,861
  • 24
  • 143
  • 221
1

sorted by NJ c# the other codes does not work so its simple if u create bath file that loops to del application and the batch file itself u can use takkill command to kill the process if u dont want to use application.close method

        `string delname = "test.cmd";
        string fileurl = Application.ExecutablePath;
        System.IO.StreamWriter file = new System.IO.StreamWriter(delname);
        file.WriteLine(":Repeat");
        file.WriteLine("del \"" + fileurl + "\"");
        file.WriteLine("if exist \"" + fileurl + "\" goto Repeat");
        file.WriteLine("del \"" + delname + "\"");
        file.Close();
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.CreateNoWindow = true;
        startInfo.UseShellExecute = false;
        startInfo.FileName = delname;
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        Process.Start(startInfo);`

` Th3 3e3 one is not 3d parts ov one I5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

cOd3r
  • 11
  • 2
0

I know reflector deletes itself if you use an old version and choose not to update. You might try to figure out what it does. I would start with FileMon and see if it spawns any processes to achieve this.

Austin Thompson
  • 2,251
  • 1
  • 17
  • 23
0

Since my application (a Windows Service) is installed via the Windows Installer, I self-delete using this:

Dim uninstall_params As String = "/x {MY-PRODUCTS-GUID} /qn /norestart REBOOT=ReallySuppress"
proc.StartInfo = New ProcessStartInfo("msiexec.exe", uninstall_params)
proc.Start()
Environment.Exit(-1)

Sorry--it's in VB, but it should be easily convertible to C#.

Aaron C. de Bruyn
  • 2,347
  • 1
  • 30
  • 40
0

Works in Windows 7 & 8, **ENSURE you run your application with admin privileges or you will get an error.

This code exists elsewhere so I can't take full credit I found I made it work for me by adding "Application.Exit();"

static void autodelete()
{
    string batchCommands = string.Empty;
    string exeFileName = Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", string.Empty).Replace("/", "\\");

    batchCommands += "@ECHO OFF\n";                         // Do not show any output
    batchCommands += "ping 127.0.0.1 > nul\n";              // Wait approximately 4 seconds (so that the process is already terminated)
    batchCommands += "echo j | del /F ";                    // Delete the executeable
    batchCommands += exeFileName + "\n";
    batchCommands += "echo j | del deleteMyProgram.bat";    // Delete this bat file

    File.WriteAllText("deleteMyProgram.bat", batchCommands);

    Process.Start("deleteMyProgram.bat");
    Application.Exit();
}
hransom
  • 11
  • 1
0

This is the Uninstall.exe:

  1. Shutdown.

  2. Wait for 3 sec.

  3. Try to kill that task if it is still running.

  4. Wait for 3 sec.

  5. Delete the app directory with the Uninstall.exe in it.

     public void Uninstall()
     {
         var delPath = AppDomain.CurrentDomain.BaseDirectory;
    
         var procId = Process.GetCurrentProcess().Id;
    
         var psi = new ProcessStartInfo
         {
             FileName = "cmd.exe",
             Arguments = $"/C timeout 3 & Taskkill /F /PID {procId} & timeout 3 & rd /s /q \"{delPath}\"",
             CreateNoWindow = true,
             WindowStyle = ProcessWindowStyle.Hidden
         };
         Process.Start(psi);
         Application.Current.Shutdown();
     }
    
Hrvoje Batrnek
  • 535
  • 1
  • 5
  • 15