Hello
I’ve written an uninstall tool that removes our software. The initial design for this software envisaged it being a downloadable tool that users (administrators) would typically run from their desktops. However, a recent development has led to the tool being included as a file within our software distribution. There’s one catch: the tool wants to remove the very directory it is running out of!
At this point, I’ve come to a partial solution in the following way:
* When the app launches, if it detects that it is in the folder it wishes to delete, it makes a copy of itself to the TEMP folder and launches that copy.
* The initial instance then exits, ensuring the file is no longer being held open (at least by itself).
* The copy running out of TEMP does the uninstallation.
* When the copy running out of TEMP finishes, it creates a CMD script that loops on TASKLIST with a filter on PID until the main process exits, then deletes the copy in TEMP, then deletes itself (because of course CMD scripts can do that :-).
In this manner, when the tool has finished running, the CMD script is able to do that last bit of cleanup and leave the system completely bare.
However, there is a caveat to this. When the uninstaller is launched from “Programs and Features”, the process that “Programs and Features” launches and is waiting upon exits almost immediately, and the actual uninstallation is performed by a child process that it does not know about. This means that when the actual uninstallation completes, “Programs and Features” does not know to refresh its view – I was able to come up with a solution using Shell.Application to force it to refresh when the copy running out of TEMP completes.
It also means, though, that if you switch back to “Programs and Features” before the uninstallation has completed, you are presented with a message that says that it looks like the uninstallation didn’t work, and would you like to try again, do nothing or assume that it worked and delete the uninstall registration. In addition, there is no way to indicate to “Programs and Features” if the user cancels the uninstallation, and the dialog appears in that scenario as well. (Though I haven’t actually been able to figure out how to indicate a cancellation to it anyway at this point, I’m sure it must be possible – *if* the signal is coming from the process that “Programs and Features” launched!)
Now, while I was poking around looking for ways to self-delete the EXE file (which ultimately led to the low-tech CMD script solution described above), I came across this:
http://www.catch22.net/tuts/self-deleting-executables
In particular, I noticed that these fancy solutions, relying on “return” addresses on the call stack to call a series of API calls after the binary’s code has been unloaded, seemed to be able to release the EXE file the process was running out of *while* the process was running. Up to Windows 2000, calling UnmapViewOfFile on handle 4 would release the file, because file handle 4 was always the handle to the executable. On XP and up, the site claims that you can call FreeLibrary on yourself – *if* you’re a DLL. So now you have to be launched via RUNDLL32. Well, that’s not very convenient.
I also stumbled across some techniques for launching processes out of memory buffers. The predominant technique seems to be to create a process off some arbitrary EXE, say CMD.EXE, with the CREATE_SUSPENDED flag. Then, before any code runs in the new process, you look up its PEB, unmap the file-backed section providing the pages of CMD.EXE to the process, and then analyze the EXE you *actually* want to load (whether it be a resource or an arbitrary memory buffer or what have you), allocate adequate memory for the image, use WriteProcessMemory to copy each section in and then VirtualProtectEx to set up the pages with the correct protection bits. When all is said and done, you can then resume that initial thread, and it’ll start running the code you copied in, instead of CMD.EXE. One thing not mentioned at all, though, I noticed, is that the process presumably still has an open file handle to CMD.EXE.
I found myself wondering if these two techniques could be combined to make an EXE that, upon launch, overwrites its own executable pages with the same data but not file-backed, and then *releases* the EXE file out from under itself. So, then you have a process running the code from the EXE, but the EXE itself is no longer implicated in the process and can be deleted.
My experimentation with this was in .NET, which I figured made a good candidate because the actual machine code would be JIT output, not file-backed. In theory, once the method doing the replacement of the EXE was JITted, it could unmap the file with the MSIL code, and then load that MSIL code back in from the file to regular old committed memory pages. As long as I suspend all other threads while I’m doing it and avoid allocating memory (which could trigger a GC), the .NET framework need never know that for a fraction of a second, the program code wasn’t present at all, right? (I’ve also considered that it might be possible to change the pages to PAGE_WRITECOPY or PAGE_EXECUTE_WRITECOPY, as appropriate, and then trigger that copy-on-write by overwriting a byte with the value already there – then there wouldn’t even be a window where the code wasn’t present.)
In my experimentation, I did see that calling ZwUnmapViewOfSection would cause the PEB to disappear from RAM, and I could then VirtualAllocEx the same pages back in. But, even though there’s no mapped view of the section, the section *still exists*. The file is still open and locked.
How can I actually release the file? Is it possible? Or would it depend on knowing a handle that is unique on each run and stored only within kernel space? Does anyone know authoritatively?
Many thanks!
Jonathan Gilbert