当前位置:C++技术网 > 精选软件 > 程序自删除技术实现源码分享和技术实现详细分析

程序自删除技术实现源码分享和技术实现详细分析

更新时间:2016-06-26 15:37:24浏览次数:1+次

    曾经做了一个软件,然后想防盗版,就研究了这种自删除的防盗版技术。这是一种防盗版严厉的打击技术,盗版的软件,也就是没有得到授权的程序,一旦运行,就会自己删除自己,然后盗版软件也就没有了。商业上可能不会这么做,因为太严格了。作为技术研究,我还是将这个实现过程分享出来,并免费分享这份源码。

    我之前的做法就是联网验证是否正版用户。如果离线状态,软件无法启动。如果联网后,检测到用户机器的相关标识是注册过的,就可以正常使用。如果验证不通过,就是在其他机器上使用的复制版本,这样程序就会将复制版本删除,不对正版的用户电脑上的软件造成影响。这样的话,即使正版用户将软件复制给其他人用,也是不行的,而且软件还会被自动删除。

    至于联网验证正版用户,这就不是这里的主题。我们这里讨论运行中的程序如何删除自己。首先来看一个流程图:

运行中的程序如何删除自己原理流程图

【运行中的程序如何删除自己原理流程图】

    大体的流程就是:创建一个临时的exe,并启动一个影子进程。影子进程会监视本体程序,一旦本体程序结束,影子进程就会删除本体程序的exe文件。当然还可以删除更多的文件。然后影子进程自己结束运行,影子进程结束后,影子进程对应的exe文件在临时目录,而且是退出时删除状态,这样系统就会在影子进程结束后删除影子进程的exe,这样exe就不存在于电脑中了。

    结束进程和创建进程都是容易实现的,关键就是如何让exe被完全删除,就算是临时文件也得删除,这样才不会留下任何痕迹,斩草除根呀!!

    为了方便理解,我就先将源代码贴出来。实际上,这个代码我已经封装成一个独立的函数了,你只要将这个代码放在你的程序里就可以了。下面是完整的代码:


void DelMyself()
{
	//判断是本程序还是克隆程序,如果命令行参数等于1,本程序,如果大于1,则是克隆程序
    if (__argc == 1) 
    {
		//本程序:引发克隆程序去删除本程序
		//复制本程序的映像文件到用户临时目录中
		TCHAR szPathOri[_MAX_PATH], szPathClone[_MAX_PATH];
		GetModuleFileName(NULL, szPathOri, _MAX_PATH);//获取当前运行的exe文件的绝对路径
		GetTempPath(_MAX_PATH, szPathClone);//获取临时文件目录路径
		GetTempFileName(szPathClone, _T("cjjjs.com"), 0, szPathClone); //获取临时文件名,1临时文件路径,2前缀文字,3临时文件序号,4接受临时文件名的缓冲区
		CopyFile(szPathOri, szPathClone, FALSE);//将文件复制到临时文件中
		// 使用 FILE_FLAG_DELETE_ON_CLOSE 打开克隆程序
		HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
		// 传递本程序进程句柄和本程序的全路径名来引发克隆程序执行
		TCHAR szCmdLine[512];
		HANDLE hProcessOri = OpenProcess(SYNCHRONIZE, TRUE, GetCurrentProcessId());
		wsprintf(szCmdLine, _T("%s %d \"%s\""), szPathClone, hProcessOri, szPathOri);
		STARTUPINFO si;
		ZeroMemory(&si, sizeof(si));
		si.cb = sizeof(si);
		PROCESS_INFORMATION pi;
		CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
		CloseHandle(hProcessOri);
		CloseHandle(hfile);
		// 本程序现在终止
        exit(-1);//终止运行后,系统会删除临时目录下的exe文件
	}
	else 
	{
		// 克隆程序: 当本程序终止,删除本程序文件
		HANDLE hProcessOri = (HANDLE) _ttoi(__targv[1]);
		WaitForSingleObject(hProcessOri, INFINITE);
		CloseHandle(hProcessOri);
		DeleteFile(__targv[2]);
		// 在此处插入代码删除子目录
		// 系统将会自动删除克隆程序因为它打开的模式是FILE_FLAG_DELETE_ON_CLOSE
     exit(-1);
     }
}
     前面说了一个大体思路,然后要实现,还有很多细节问题。我们就慢慢展开来讲。


    我们这里就只有一个函数,就可以完成运行中的程序删除自己。当然,运行是激发删除自己,并不是说,运行中的程序能够将进程映射的exe文件在进程不结束的时候删除。这样是不允许的。因为进程不可能凭空在内存中的,这是Windows的机制。但是我们可以让进程结束后干掉自己嘛。

    那么问题就来了,既然自己都结束了,如何干掉自己呢?好像有点自相矛盾。实际上并不是的。当需要干掉自己的时候,我们需要创建一个影子程序exe和影子进程。就好像自己的双胞胎一样。在主体程序和影子程序的基因里,是含有自删除的基因的。就好像人类自杀一样的基因。当主体程序不想活了,就激发自己的影子进程,等自己结束运行的时候,影子进程就删除自己的EXE文件。实际上,这里已经存在了两个程序Exe和两个进程。所以,不存在前面的Windows运行的进程必须有exe文件的存在的限制。

    问题是,影子程序exe和本体程序exe是一模一样的,你只是删除了本体的exe,万一人家找到了影子程序exe,将它当做本体程序exe也是可以的。那岂不是搬石头砸自己脚。所以,影子程序exe也是需要被删除掉的。

    我们始终知道一点,进程自己结束后没法删除自己的exe,本体程序exe依靠影子程序来删除自己,可以影子程序靠谁删除自己呢?答案就是操作系统。那为什么本体程序不能靠系统呢?那这个就和系统的一个机制有关了。 

   系统有一个机制就是,以FILE_FLAG_DELETE_ON_CLOSE标志打开一个文件,也就是在文件关闭的时候,同时不被其他程序使用的时候,系统就会将这个文件删掉。这个机制一般用在临时文件中。刚好,我们的影子程序也起着临时作用,所以可以用上。

    当影子程序结束后,那么系统就可以将影子程序对应的临时的exe删掉。而这个临时的exe可以放在临时目录下面,这个目录对于普通的用户来说是不容易接触的。算是一个不易发现的角落。在临时目录中,时刻有各种临时文件创造出来,然后不久就被干掉了。因为本体程序一定是在正规的目录中存在,方便用户使用的,而且正常情况下,本体程序不能在退出时删除自己,所以本体程序无法利用这个机制,所以才利用二级删除。影子程序删除本体程序,系统删除临时的影子程序。这样就相当于系统删除了本体程序。

    了解了这些背景之后,你也就明白了,为什么我们要利用临时文件,为什么要用FILE_FLAG_DELETE_ON_CLOSE标志,为什么要用影子程序?为什么不能自己删除自己,而在内部借助他人删除自己。人类的自杀,也无法自己杀自己,而是借助工具或者外界环境来杀自己,试想一个人用拳头能打死自己吗?当然,失血身亡是另外一回事。

   本体程序和影子程序就是同一个exe的两种基因,两种基因必然不会同时起作用。正常的情况下是本体程序基因发挥作用,在需要自杀的时候,会激发影子程序基因来自杀。所以,在程序中,要激发自杀,也就是调用DelMysef函数来激发自杀基因。如果不调用DelMysef函数,也就是正常的基因在运作。

    而影子程序一开始是不存在的,所以需要先激发自杀基因,即调用DelMysef函数时创造。而且,DelMysef函数在本体程序和影子程序都是存在的。我们只能让本体程序创造影子程序,而不能让影子程序创造影子程序。所以要对本体程序和影子程序做一个判定。判定的依据就是命令行参数。

    在本体程序启动时,shell加载程序会传递一个“exe路径”这个参数,也就一个参数。而创建影子程序时,本体程序创造影子程序时会传递额外的两个参数,一共有三个参数。所以基于此,我们就可以判断本体程序和影子程序。

    __argc参数是记录的cmd的参数的个数,如果为1,也就是本体程序了。如果大于1,就是影子程序了。所以在__argc等于1的时候做一些工作,包括创造影子程序临时exe,创建影子进程,并给影子进程传递命令行参数。传递的参数有本体进程的句柄和本体程序exe的路径。然后在__argc大于1的时候,等待本体进程结束,然后执行删除本体exe的操作,然后影子程序自己结束。系统就会删除临时的并且结束后就删除的exe文件。

    那么具体的代码,基本都有详细的注释了,就不再解释了,如果有不懂的请留言。最关键的就是上面分析的实现思路。

    我们如何使用DelMysef函数呢?我们在程序初始化的时候,判断程序是否是正版的,如果不是正版的,执行DelMysef函数就可以了。如果不是正版的,本体程序执行了一下DelMysef函数,创造了影子程序exe和影子进程,然后本体程序结束了。影子进程运行的时候,也会检查一下程序是否为正版,当然此刻检查出来的也不是正版,所以就执行了__argc不为1的代码,也就是删除本体的exe文件。然后影子程序结束,系统删除了影子程序的exe。

    那么到此,所有的分析就完毕了。当然这个技术不仅仅是用于自删除上,其他方面也是可以使用的。比如安装文件的安装完后可以让系统删除一些临时安装产生的exe和其他文件。我们这里实现的就是启动隐藏的进程帮助主进程做一些无法做的事情。扩展之后,应用很多,请一定不要仅仅局限于自删除的应用中。