欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

如何让exe自己删除自己??

程序员文章站 2022-06-10 14:43:35
...

我们都知道,当一个exe程序在启动之后,操作系统会把这个可执行文件加载到内存中去,在程序处于运行状态时,如果我们想要把这个文件删除,那就会出现以下情况:
如何让exe自己删除自己??
那我们将不得不等到程序执行完毕之后,手动的来删除这个文件,但是有没有一种办法可以直接在程序退出的时候,就自动删除这个可执行文件呢??
加入我们想要用我们的程序做一些“坏事”,比如说是我们要实现一个IATHook,我们需要一个启动进程,在目标进程地址空间中申请空间,进而实现dll的注入,启动dll。
当我们的启动进程完成对目标进程的注入这些事情之后,能不能功成身退,拂袖而去,不带走一片云彩呢?
请收看小白先生今日测试血泪史:
我前两天还写了启动进程的各种方法,今日果然用到了,大体思路就是:

  • 填充SHELLEXECUTEINFO结构体的各个字段
  • 调用ShellExecuteEx启动进程
  • 调用SetPriorityClass设置进程优先级
  • 调用SetThreadPriority设置当前线程优先级
  • 调用SHChangeNotify通知Windows资源管理器
  • 完成工作

但是我在测试的过程中,碰了一鼻子灰,运行之后出现了以下情况:
如何让exe自己删除自己??
看似删除成功了,刷新文件夹之后,灰太狼又回来了??
如何让exe自己删除自己??
因为我启动cmd隐藏删除该文件,网上查找资料之后,说是cmd要删除的文件必须是未被占用的,当我的程序执行完自杀函数之后,我的主程序并没有退出,当一个运行中的应用程序被删除之后,操作系统会自动重建,所以会出现上面那种情况。导致主程序没有被真正删除,只是SHChangeNotify通知资源管理器,说我把文件删除了,才会出现假删除现象。。
测试到这里的时候,居然还有点小小的激动,感觉自己的Demo像一个流氓软件一样,删也删不掉,hhhhhh。
自动重建这个现象同样也会发生在dll身上,我之后也测试了将dll自删除,发现那是根本不可能的,因为dll已经被目标程序加载,如果自己删除自己,还是会重建。
解决办法:将getchar()那句拦截代码删除掉,这样在代码中设置的优先级才有意义嘛。。。我可真是够蠢的,一开始在代码中设置优先级,就是为了主程序完美退出之后,再去执行cmd程序。。
下面附上最终测试结果:
如何让exe自己删除自己??
运行之后,程序闪退,然后就被删除了。。
我这个测试只是一个简单的测试,我也在自己的IATHook的启动程序中测试了,没有什么问题,可以直接删除启动程序,不带走任何一片云彩!
附上测试源码:

//.h
#pragma once
#include<iostream>
#include<Windows.h>
#include<tchar.h>
using namespace std;


BOOL SelfDelete();
//cpp
#include"Demo.h"
#include<Shlobj.h>//SHChangeNotify使用

void _tmain()
{
	
	printf("Current Process Id:%d\r\n", GetCurrentProcessId());

	if (SelfDelete())
	{
		printf("Success\r\n");
	}
}
BOOL SelfDelete()
{
	SHELLEXECUTEINFO ShellExecuteInfo;
	TCHAR ModuleName[MAX_PATH], CmdPath[MAX_PATH], Paramdters[MAX_PATH];

	// 获得文件名.
	if ((GetModuleFileName(0, ModuleName, MAX_PATH) != 0) &&
		(GetShortPathName(ModuleName, ModuleName, MAX_PATH) != 0) &&
		(GetEnvironmentVariable("COMSPEC", CmdPath, MAX_PATH) != 0))
	{
		// 设置命令参数.
		lstrcpy(Paramdters, "/c del ");
		lstrcat(Paramdters, ModuleName);
		lstrcat(Paramdters, " > nul");

		// 设置结构成员.
		ShellExecuteInfo.cbSize = sizeof(ShellExecuteInfo);
		ShellExecuteInfo.hwnd = 0;
		ShellExecuteInfo.lpVerb = "Open";
		ShellExecuteInfo.lpFile = CmdPath;
		ShellExecuteInfo.lpParameters = Paramdters;
		ShellExecuteInfo.lpDirectory = 0;
		ShellExecuteInfo.nShow = SW_HIDE;
		ShellExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;

		// 执行shell命令.
		if (ShellExecuteEx(&ShellExecuteInfo))
		{
			//设置命令行进程的执行级别为空闲执行,使本程序有足够的时间从内存中退出. 
			SetPriorityClass(ShellExecuteInfo.hProcess, IDLE_PRIORITY_CLASS);
			//设置当前进程为实时进程
			SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
			SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

			//通知Windows资源浏览器,本程序文件已经被删除.相当于一个刷新文件夹的作用
			SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, ModuleName, 0);
			return TRUE;
		}
	}
	return FALSE;
}

今天正好是母亲节,祝我亲爱的妈妈节日快乐,身体健康!祝福全天下的母亲永远年轻快乐,身体健康!

“生活像一把无情刻刀,改变了我们模样。”–老男孩
参考书籍:
《Windows应用程序捆绑核心》

相关标签: Windows应用层开发