可执行模块的自删除技术已经被讨论的很多, 有很多极富创意的思路和想法被提出, 但有些似是而非的方案往往使人误入歧途. 举个例子来说, 很多文章认为下面的一小段代码可以实现自删除:
void main(void)
{
        TCHAR szCMD[NAME_LENGTH] = {0};
        strcpy(szCMD, "cmd /c del ");
        strcat(szCMD, ::GetProgramName());
        ::WinExec(szCMD, 0);        
}
初看起来, 这段代码表面上没有什么问题, 运行测试发现很好很奏效, 又简单又明了, 难道存在隐藏的错误? 是的! 可以很肯定的告诉大家, 这段代码从原则上来说是错误的! 它的错误可以归结为一句话: 不能无条件地假设多个进程在特定时刻的运行顺序! 
  编写上面例子代码的时候, 不知不觉的陷入了一个假相陷阱: cmd进程会在当前程序退出后开始执行(假设了cmd进程与当前应用程序进程的执行顺序). 我们可以加入一条Sleep语句来验证这个假相陷阱, 代码如下: 
void main(void)
{
        TCHAR szCMD[NAME_LENGTH] = {0};
        strcpy(szCMD, "cmd /c del ");
        strcat(szCMD, ::GetProgramName());
        ::WinExec(szCMD, 0);        
        ::Sleep(1000);
}
结果发现程序现在不能自删除了. 为什么? 就是因为cmd进程开始运行时, 当前应用程序进程仍然存在, 系统不能释放当前应用程序的可执行文件句柄, 导致文件不能被删除. 有些朋友会说: 没关系, 我在调用::WinExec(szCMD, 0);后什么也不做就退出, 这样不就OK啦? 真的这样就OK了? 实际上你无法保证在调用::WinExec(szCMD, 0);后进程立即退出且释放当前应用程序的可执行文件句柄. 因为在很多情况下, 应用程序的退出是一个相对缓慢的过程(像卸载大量的dll, 释放各种资源, C++全局对象的析构etc.)

现在给大家介绍几种简单可行的Windows可执行模块安全自删除技术
1) MoveFileEx() API, 在NT以后的Windows平台上被引入. 它的原型是 
BOOL MoveFileEx(
  LPCTSTR lpExistingFileName,
  LPCTSTR lpNewFileName,
  DWORD dwFlags
);
如果传NULL给lpNewFileName并置dwFlags为MOVEFILE_DELAY_UNTIL_REBOOT, 那么系统重启后lpExistingFileName所指定的文件就会被删除.
而在9x下, 需要修改win.ini, 给出类似 "filename= "这样的字段, 那么系统重启后"filename"所指定的文件会被删除. 
它们的共同点就是Windows系统保证文件的正确删除, 非常简单, 而且对于一些系统级,驱动级文件来说是唯一可靠的方法, 缺点是要求系统重启才能真正删除指定的文件.

2) 利用文件的FILE_FLAG_DELETE_ON_CLOSE属性实现安全自删除
当创建文件时如果指定了FILE_FLAG_DELETE_ON_CLOSE属性, 系统会在该文件的所用句柄被关闭后立刻自动删除该文件.
步骤:
1) 使用CreateFile() API创建一个新文件, 指定FILE_FLAG_DELETE_ON_CLOSE属性.
2) 使用一个可执行文件映象填充这个新文件.
3) 使用CreateProcess() API启动新文件进程.
4) 借助任意的进程间通信机制保证新文件进程在当前程序退出后安全的删除可执行文件.
5) 新文件进程结束后系统将自动删除新文件, 至此, 自删除顺利完成.
很多我的朋友使用这种方式后, 感觉很简单明了也有很强的适应性. 他们写出了各式各样的应用方法, 实践证明这种方式是可靠安全的.
最后大家可以使用以上介绍的方法自己动手尝试, 就不再给出例子啦, 自己动手最可靠, 嘿嘿. 有任何问题, 错误请指出, 谢过先.

Windows文件自删除的两种方法的更多相关文章

  1. mybatis 根据id批量删除的两种方法

    原文:https://blog.csdn.net/qq_40010745/article/details/81032218 mybatis 根据id批量删除的两种方法   第一种,直接传递给mappe ...

  2. oracle多表关联删除的两种方法

    oracle多表关联删除的两种方法 第一种使用exists方法 delete from tableA where exits ( select 1 from tableB Where tableA.i ...

  3. vba判断文件是否存在的两种方法(转)

    方法1. 用VBA自带的dir()判断,代码如下: 在 Microsoft Windows 中, Dir 支持多字符 (*)和单字符 (?) 的通配符来指定多重文件 Function IsFileEx ...

  4. VC++实现获取文件占用空间大小的两种方法(非文件大小)

    // GetFileSpaceSize.cpp : Defines the entry point for the console application. // /***************** ...

  5. Windows添加启动项的两种方法

    方案1直接将脚本放到启动文件夹里面 C:\Users\XXX\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 方案2 Win ...

  6. SpringBoot从入门到精通十一(SpringBoot文件上传的两种方法)

    前言 在企业级项目开发过程中,上传文件是最常用到的功能.SpringBoot集成了SpringMVC,当然上传文件的方式跟SpringMVC没有什么出入. 本章目标 使用SpringBoot项目完成单 ...

  7. C#实现Web文件上传的两种方法

    1. C#实现Web文件的上传 在Web编程中,我们常需要把一些本地文件上传到Web服务器上,上传后,用户可以通过浏览器方便地浏览这些文件,应用十分广泛. 那么使用C#如何实现文件上传的功能呢?下面笔 ...

  8. 清除SQLServer日志的两种方法

    日志文件满而造成SQL数据库无法写入文件时,可用两种方法:一种方法:清空日志.1.打开查询分析器,输入命令DUMP TRANSACTION 数据库名 WITH NO_LOG2.再打开企业管理器--右键 ...

  9. Delphi Windows API判断文件共享锁定状态(OpenFile和CreateFile两种方法)

    一.概述 锁是操作系统为实现数据共享而提供的一种安全机制,它使得不同的应用程序,不同的计算机之间可以安全有效地共享和交换数据.要保证安全有效地操作共享数据,必须在相应的操作前判断锁的类型,然后才能确定 ...

随机推荐

  1. Go实战--通过gin-gonic框架搭建restful api服务(github.com/gin-gonic/gin)

    生命不止,继续 go go go !!! 先插播一条广告,给你坚持学习golang的理由: <2017 软件开发薪酬调查:Go 和 Scala 是最赚钱的语言> 言归正传! 之前写过使用g ...

  2. FLASH OTP

    OTP 软件加密运用参考 为了防止软件被他人盗用,spansion flash给每个芯片植入了代表身份的unique ID,增加了OTP扇区,目前我们可以运用这两个特性,来实现软件的加密保护.软件加密 ...

  3. GIT+Gitolite+Gerrit 环境搭建 ***

    系统环境:Ubuntu12.04 服务器上安装git+gitolite+gitweb root@server: 为搭建git服务器终端,假设ID为 192.168.199.117 或域名为: http ...

  4. PHP小函数集-篇一

    一. 验证 /** * 判断用户名是否规范 */ function is_username($username) { if (preg_match("/^[a-zA-Z]{1}([0-9a- ...

  5. Spark 大数据文本统计

    此程序功能: 1.完成对10.4G.csv文件各个元素频率的统计 2.获得最大的统计个数 3.对获取到的统计个数进行降序排列 4.对各个元素出现次数频率的统计 import org.apache.sp ...

  6. 3.jeesite主从表开发

    1. 2 3. 4. 5. 6. 7. 8. 9. 10.

  7. bzoj 2733: [HNOI2012]永无乡【并查集+权值线段树】

    bzoj上数组开大会T-- 本来想用set瞎搞的,想了想发现不行 总之就是并查集,每个点开一个动态开点的权值线段树,然后合并的时候把值并在根上,询问的时候找出在根的线段树里找出k小值,看看这个值属于哪 ...

  8. bzoj 2288: 【POJ Challenge】生日礼物【链表+堆】

    参考:http://blog.csdn.net/w_yqts/article/details/76037315 把相同符号的连续数字加起来,合并后ans先贪心的加上所有正数,如果正数个数sum> ...

  9. selenium3 + python - js 内嵌滚动处理

    一.js内嵌html <!DOCTYPE html><html lang="en"><head> <meta charset=" ...

  10. Python Flask 实现移动端应用接口(API)

    引言 目前,Web 应用已形成一种趋势:业务逻辑被越来越多地移到客户端,逐渐完善为一种称为富互联网应用(RIA,rich Internet application)的架构.在 RIA 中,服务器的主要 ...