如何删除过程映像文件?

时间:2014-12-29 13:23:08

标签: winapi visual-c++ c++11 process executable

我希望在Windows上执行时删除可执行文件。我不认为这会对程序造成任何伤害,因为可以通过从USB执行'.exe'然后删除它来完成同样的操作 - 这无论如何都不会影响进程。

我没有运气就尝试过最简单的方法:

extern wchar_t *pExePath;

DeleteFileW(pExePath);

然后我尝试使用原生API:

UNICODE_STRING name;

static wchar_t strdrvPrefis [] {L"\\??\\"};

static wchar_t strObjectName[MAX_PATH];

name.Length = (name.MaximumLength = wcslen(pExePath) * sizeof(wchar_t) + (sizeof(strdrvPrefis) - sizeof(wchar_t)));

name.Buffer = strObjectName;

OBJECT_ATTRIBUTES objFile{};

objFile.Length = sizeof(OBJECT_ATTRIBUTES);

objFile.ObjectName = &name;

wcscat(strObjectName, strdrvPrefis);

wcscat(strObjectName, pExePath);

NtDeleteFile(&objFile);

如果我核心地退回,那么ACCES_DENIED会失败。

然后我尝试了'NtFsControlFile',但也没有成功:

HANDLE hFile;

IO_STATUS_BLOCK info;

NTSTATUS RetNt = NtOpenFile(&hFile, FILE_READ_DATA | FILE_WRITE_DATA, &objFile, &info, 0, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_OPEN_REPARSE_POINT | FILE_NO_INTERMEDIATE_BUFFERING);

RetNt = NtFsControlFile(hFile, nullptr, nullptr, nullptr, &info, 0x000900A0 /*FSCTL_DELETE_OBJECT_ID*/, nullptr, 0, nullptr, 0);

NtClose(hFile);

现在上面的代码片段将在'NtOpenFile'失败。如果我从它的第二个参数中删除'FILE_WRITE_DATA',那么'NtFsControlFile'将因'STATUS_ACCESS_DENIED'而失败。

任何想法如何实现这一目标?

我正在使用VC ++ 2013。

1 个答案:

答案 0 :(得分:2)

基本上,你不能这样做,因为当EXE运行时,进程打开文件。并且您无法删除进程已打开的文件。

正如您所注意到的,您可以通过USB记忆棒运行可执行文件,然后从USB端口拔出记忆棒。该计划继续运行。不过,我怀疑你可以做“安全删除驱动器”。

但那不会总是。 EXE不仅仅是代码。它包含可执行代码和资源,并且在EXE运行时并不是所有内容都被加载到内存中。例如,如果EXE包含大型位图资源,则在程序要求加载该资源之前,不会加载该资源。该过程保留了EXE的句柄,以便它可以根据需要加载资源。

因此,如果您的程序需要位于EXE中且尚未加载的资源,那么移除USB记忆棒会导致程序失败,如果它随后尝试加载其中一个资源。

据我所知,没有办法删除当前由另一个进程打开的文件。据我所知,你的程序无法关闭它对可执行文件的句柄。

文章http://www.catch22.net/tuts/self-deleting-executables(在重复的答案中链接)显示了一个示例,该示例创建了一个设置了delete-on-close标志的新文件。将可执行文件复制到该文件,然后执行该文件。然后删除原始可执行文件,当进程退出时,将自动删除您正在执行的可执行文件。这是我所知道的最好的方式来做你所要求的。

没有直接方式删除当前正在执行的文件。