编写自杀程序

在开发程序过程中,有许多情况中都需要执行程序自己把自己从物理磁盘上删除,例如,卸装程序,一些黑客程序获取信息后自清除等,我们把这些具有自删除功能的程序统称为自杀程序。对于一名程序员,想必都有在程序中使用代码删除物理磁盘文件的经历吧,我们只需要简单的调用DeleteFile   API函数就可以搞定,但是该函数并不能删除自己,当它执行删除自己时,将会导致出现无法删除文件:拒绝访问。源文件可能正被使用的错误提示,其原因是由于本程序在执行删除自己代码时仍处于内存中,在Windows中,不可以删除正在执行中的程序。

为了实现程序自删除功能,我们可以通过多进程的方法解决这个问题。可执行文件在结束返回前,创建一个运行命令窗口的新进程(在Windows98中为Command进程,在Windows2000/XP中为CMD进程),当然该命令窗口以隐藏方式执行,并通过传递参数执行删除功能。为了避免可执行文件的映像还在内存中就执行删除,需要把当前进程设置为实时优先级,而命令窗口进程设置为很低的IDLE优先级,这样首先可执行文件结束返回,再运行命令窗口的删除命令,就实现了该文件自身的删除功能。

 

下面我们就一起动手制作自杀(具有自删除功能)程序,程序在Visual   C++6.0中开发编译。

首先,启动Visual   C++6.0,新建一个MFC   AppWizard(exe)类型的项目,项目名为SelfDelete,选择基于对话框模式创建程序框架。

接下来,打开资源编辑器,添加一个按钮控件,设置内容为开始自杀,如图一所示:

启动ClassWizard,为新添加的控件新建CLICK事件处理函数,再打开该函数,添加自杀代码如下:

void   CSelfDeleteDlg::OnButton1()

{

      //TODO   Add   your   control   notification   handler   code   here            SHELLEXECUTEINFO   sei;

      TCHAR   szModule   [MAX_PATH],szComspec[MAX_PATH],szParams   [MAX_PATH];

      //获取文件路径名

      if((GetModuleFileName(0,szModule,MAX_PATH)!=0)   &&

        (GetShortPathName(szModule,szModule,MAX_PATH)!=0)   &&  

GetEnvironmentVariable( "COMSPEC ",szComspec,MAX_PATH)!=0))

{     //设置命令行参数

         lstrcpy(szParams, "/c   del   ");

         lstrcat(szParams,   szModule);

lstrcat(szParams,   "   >   nul ");


            //
初始化SHELLEXECUTEINFO结构成员  
            sei.cbSize   =   sizeof(sei);
 //设置类型大小。  
            //
命令窗口进程句柄,ShellExecuteEx函数执行时设置。  
            sei.hwnd   =   0;  
            sei.lpVerb   =   "Open ";
                //执行动作为打开执行  
            sei.lpFile   =   szComspec;             //
执行程序文件全路径名称。  
            sei.lpParameters   =   szParams;   //
执行参数。  
            sei.lpDirectory   =   0;  
            //
显示方式,此处使用隐藏方式阻止出现命令窗口界面。  
            sei.nShow   =   SW_HIDE;  
            //
设置为SellExecuteEx函数结束后进程退出。  
            sei.fMask   =   SEE_MASK_NOCLOSEPROCESS;  
            //
创建执行命令窗口进程。  
            if(ShellExecuteEx(&sei))  
            {     //
设置命令行进程的执行级别为空闲执行,这使本程序有足够的时间从内存中退出。      
                  SetPriorityClass(sei.hProcess,IDLE_PRIORITY_CLASS);  
                  //
设置本程序进程的执行级别为实时执行,这本程序马上获取CPU执行权,快速退出。      
                  SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);  
                  SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);      
                  //
通知Windows资源浏览器,本程序文件已经被删除。  
                  SHChangeNotify(SHCNE_DELETE,SHCNF_PATH,szModule,0);  
                  //
执行退出程序  
                  EndDialog(0);  
              }  
      }  
}  

       
如果上面代码中的注释还不能帮助你理解代码的意义,请不要着急,后面我们还要对这些代码做详细的讲解。现在,你可以开始编译该程序项目,运行一下程序,请在Windows资源浏览器中仔细观察程序文件,当你按下开始自杀按钮后几秒,该程序文件从Windows资源浏览器中消失了,这也正在本程序想要得到的效果。  
       
体验了自杀程序的神奇之后,让我们回过头来好好的分析一下实现自杀功能的代码。      
       
前面我们已经谈过,实现自杀功能的核心是在程序中创建一个命令窗口新进程,通过向命令窗口进程传递del命令和参数来删除程序文件。命令窗口程序是由环境变量COMSPEC定义的,Win9x/ME使用COMMAND.COMWinNT/2K/XP使用CMD.COM。程序把命令字符串“/c   del   filename   >   nul”传递给命令窗口,其中filename是需要删除文件的全路径文件名,文件名需要转换为8.3格式;/c开关用于命令窗口退出。      
       
在实现代码中,首先就需要获取当前程序模块的全路径,并将其转化为命令窗口需要的8.3格式。代码中GetModuleFileName(0,szModule,MAX_PATH)函数实现了获取当前程序模式的全路径名称,并存放到变量szModule中。接着使用GetShortPathName(szModule,szModule,MAX_PATH)函数将szModule变量中的程序模块全路径名称转换成命令窗口需要的8.3格式。另外,还调用GetEnvironmentVariable( "COMSPEC ",szComspec,MAX_PATH)函数从系统环境变量COMSPC中获取了命令窗口程序的全路径。接下来,需要将存放在变量szModule中的具有8.3格式的程序模块全路径字符串组合成命令字符串“/c   del   ”+szModule+   “>   nul”      
       
有了这些信息之后,就可以调用ShellExecuteEx()   API函数创建一个新的命令窗口进程,该函数需要一个SHELLEXECUTEINFO类型的参数,调用ShellExecuteEx()函数必须需要初始化这个类型参数,有关SHELLEXECUTEINFO类型的详细说明请参阅MSDN。本处通过该参数将命令窗口进程的执行动作设为Open、执行文件为命令窗口(路径由szComspec提供)、执行文件参数为上面组合而成的命令字符串、显示方式为隐藏方式(隐藏方式可以阻止出现命令窗口界面)。      
       
命令窗口通过调用ShellExecuteEx()函数以单独的进程运行,它的窗口句柄在SHELLEXECTUEINFO结构中的成员变量hProcess定义。自删除需要解决一个特殊的问题,即主程序必须在命令窗口删除它之前退出并关闭其打开的文件句柄。为了做到这一点,我们必须同步两个独立、并行的进程:当前程序进程和命令窗口进程。这可以通过操作CPU资源优先级来临时降低命令窗口的运行优先级别。这样,主程序将分配到CPU的所有资源直到其正常退出,而阻塞其它任何命令窗口的执行直到主程序结束。下面代码实现调整两个进程的执行优先级:      
        //
设置命令行进程的执行级别为空闲执行,    
        //
这使本程序有足够的时间从内存中退出。      
        SetPriorityClass(sei.hProcess,IDLE_PRIORITY_CLASS);      
        //
设置本程序进程的执行级别为实时执行,    
        //
这本程序马上获取CPU执行权,快速退出。      
        SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);      
        SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);      

       
到此,自杀功能基本实现。最后还需要做的事是调用SHChangeNotify(SHCNE_DELETE,SHCNF_PATH,szModule,0)   函数通知Windows资源浏览器已成功删除了程序文件。如果用户当前Windows资源浏览器窗口正处于程序文件目录的话,这个通知是非常必要的,它会导致Windows资源浏览器马上从程序文件目录列表中删除该程序文件项。做完了以上工作,一定要调用退出程序的代码,此处使用了EndDialog()函数,如果不及时退出程序的话,命令窗口进程就不能正常删除程序文件,其原因在前面我们已经研究过。      
       
当你阅读完本文之后,一定与我有一个共同的感受:自杀也同样如此精彩!

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值