中国开发网: 论坛: 程序员情感CBD: 贴子 144852
haitao
找回来的4年前的文章,可能有参考价值
└进程退出前删除自身EXE (文章评价:一级的棒) [haitao](3311) 17:05:47 2001-09-10
│ { 进程退出前删除自身EXE(文章评价:一级的棒)
│ { 关键字:
│ { 删除自身EXE 贴文时间
│ { 2001-9-102:54:54 文章类型:
│ { 翻译 给贴子投票
│ { 投票
│ { wl3000wlnew 翻译 出处:http://lu0.126.com
│ {
│ {
│ {
│ {
│ { 下面的代码由GaryNebbett写就.GaryNebbett乃是WINDOWSNT/2000NATIVEAPIREFERENCE的作者.乃NT
│ { 系统一等一的高手.下面就分析一些他的这段代码.
│ { 这段代码在PROCESS没有结束前就将启动PROCESS的EXE文件删除了.
│ { intmain(intargc,char*argv[])
│ { {
│ { HMODULEmodule=GetModuleHandle(0);
│ { CHARbuf[MAX_PATH];
│ { GetModuleFileName(module,buf,sizeofbuf);
│ { CloseHandle(HANDLE(4));
│ { __asm{
│ { lea eax,buf
│ { push 0
│ { push 0
│ { push eax
│ { push ExitProcess
│ { push module
│ { push DeleteFile
│ { push UnmapViewOfFile
│ { ret
│ { }
│ { return0;
│ { }
│ { 现在,我们先看一下堆栈中的东西
│ {
│ { 偏移内容
│ { 24 0
│ { 20 0
│ { 16 offsetbuf
│ { 12 addressofExitProcess
│ { 8 module
│ { 4 addressofDeleteFile
│ { 0 addressofUnmapViewOfFile
│ {
│ { 调用RET返回到了UnmapViewOfFile,也就是栈里的偏移0所指的地方.当进入UnmapViewOfFile的流程
│ { 时,栈里见到的是返回地址DeleteFile和HMODULmodule.也就是说调用完毕后返回到了DeleteFile的
│ { 入口地址.当返回到DeleteFile时,看到了ExitProcess的地址,也就是返回地址.和参数EAX,而EAX则
│ { 是buffer.buffer存的是EXE的文件名.由GetModuleFileName(module,buf,sizeofbuf)返回得到.执行
│ { 了DeleteFile后,就返回到了ExitProcess的函数入口.并且参数为0而返回地址也是0.0是个非法地址
│ { .如果返回到地址0则会出错.而调用ExitProcess则应该不会返回.
│ { 这段代码的精妙之处在于:
│ { 1.如果有文件的HANDLE打开,文件删除就会失败,所以,CloseHandle(HANDLE(4));是十分巧妙的一手
│ { .HANDLE4是OS的硬编码,对应于EXE的IMAGE.在缺省情况下,OS假定没有任何调用会关闭IMAGESECTIO
│ { N的HANDLE,而现在,该HANDLE被关闭了.删除文件就解除了文件对应的一个句柄.
│ { 2.由于UnmapViewOfFile解除了另外一个对应IMAGE的HANDLE,而且解除了IMAGE在内存的映射.所以,
│ { 后面的任何代码都不可以引用IMAGE映射地址内的任何代码.否则就OS会报错.而现在的代码在Unmap
│ { ViewOfFile后则刚好没有引用到任何IMAGE内的代码.
│ { 3.在ExitProcess之前,EXE文件就被删除了.也就是说,进程尚在,而主线程所在的EXE文件已经没了.
│ { (WINNT/9X都保护这些被映射到内存的WIN32IMAGE不被删除.)
│ {
│ { GaryNebbett果然是WIN系列平台的顶尖高手之一.能写出如此代码.独辟蹊径啊:)
│ {
│ {
│ {
│ {
│ { 对该文的评论
│ {
│ { classfactory(2001-9-1013:07:03)
│ {
│ { 术业有专攻而已。如果你整天研究别人不太注意的东西也会独辟蹊径的。
│ {
│ {
│ {
│ { asm386(2001-9-1011:47:03)
│ {
│ { 高,但是不知道,他是怎样得到这些知识的?
│ {
│ { 给你一块金子,不如给你一块点石成金的手指。
├我的一个发现是:IIS下跑的ISAPI.dll是无法删除的,但是你却可以将它改名! [haitao](0) 17:...
│ { 标题:我的一个发现是:IIS下跑的ISAPI.dll是无法删除的,但是你却可以将它改名![haitao]
│ { (0)17:06:582001-09-10
│ { 正文:--无内容--
├你们谁删掉了?我怎么试不出来呢? [goodhope](0) 10:56:57 2001-09-11
│└我试了,很成功啊 [bjwf](0) 11:15:20 2001-09-11
│ └你的环境是什么?我的是CB5+Win2k SP2+IE6。 [goodhope](0) 11:23:57 2001-09-11
│ └我win2K and vc++6.0 [bjwf](0) 12:29:57 2001-09-11
│ └转为Delphi该怎么写?我正好想将我的局域网应用增加自动更新版本的功能... [haitao]...
│ │ { 标题:转为Delphi该怎么写?我正好想将我的局域网应用增加自动更新版本的功能...[
│ │ { haitao](0)12:03:512001-09-13
│ │ { 正文:--无内容--
│ └我已改用 自动创建.bat 来实现这个功能了 8-( [haitao](0) 17:41:23 2001-09-13
├另外,我的疑问是:有些exe在运行后需要从exe文件里读取一些资源,如果删除或更新了,岂不会...
││ { 标题:另外,我的疑问是:有些exe在运行后需要从exe文件里读取一些资源,如果删除或更新了
││ { ,岂不会出错?![haitao](0)12:05:582001-09-13
││ { 正文:--无内容--
│└我想读取资源是在启动时该,或前期完成的,可以在程序要结束时再删除自已啊 [bjwf](195) 1...
│ │ { 标题:我想读取资源是在启动时该,或前期完成的,可以在程序要结束时再删除自已啊[bjwf]
│ │ { (195)12:44:532001-09-13
│ │ { 正文:当然,通常情况下想把自已删除的程序一般都不会干什么好事,估计也不会用界面,图
│ │ { 标,资源什么的
│ │ { <HRWIDTH=90%ALIGN=RIGHT>
│ │ { <IMGSRC=http://club.chinauser.com/img/1000824361xiaoyao.jpg>
│ └如何转为Delphi? [haitao](874) 12:51:00 2001-09-13
│ │ { proceduredeleteself();
│ │ { var
│ │ { module:HMODULE;
│ │ { buf:array[0..MAX_PATH]ofchar;
│ │ { begin
│ │ {
│ │ { module:=GetModuleHandle(0);
│ │ { GetModuleFileName(module,buf,sizeof(buf));
│ │ { CloseHandle(THANDLE(4));
│ │ { asm//{
│ │ { lea eax,buf
│ │ { push 0
│ │ { push 0
│ │ { push eax
│ │ { push 1//ExitProcess这个可不可以不定义?
│ │ { push module
│ │ { push 2//DeleteFile自己的删除函数?
│ │ { push 3//UnmapViewOfFile????
│ │ { ret
│ │ { end
│ │ { //}
│ │ {
│ │ { end;
│ ├ExitProcess 是否可以用 Delphi 的 ExitProc 代替? [没脾气](0) 12:55:24 2001-09-13
│ ├全是些api,可以用loadlibrary什么的取得地址再压栈。 [王中王](0) 13:36:58 2001-09-1...
│ │ { 标题:全是些api,可以用loadlibrary什么的取得地址再压栈。[王中王](0)13:36:582001
│ │ { -09-13
│ │ { 正文:--无内容--
│ ├我转了。不过Delphi下和CB下一样。删不掉自己。 [goodhope](0) 15:08:48 2001-09-13
│ │└是否它们有Form等资源需要读自exe文件,另有句柄打开着,所以不允许删除 [haitao](0...
│ │ │ { 标题:是否它们有Form等资源需要读自exe文件,另有句柄打开着,所以不允许删除[ha
│ │ │ { itao](0)15:31:422001-09-13
│ │ │ { 正文:--无内容--
│ │ └在 ExitProc 里写行么? [没脾气](0) 16:10:28 2001-09-13
│ │ └也不行。不过,Delphi里面不会引发异常,CB会。 [goodhope](0) 21:37:05 2001-0...
│ │ { 标题:也不行。不过,Delphi里面不会引发异常,CB会。[goodhope](0)21:37:052
│ │ { 001-09-13
│ │ { 正文:--无内容--
│ └不好意思,delphi我一窍不通 [bjwf](0) 15:24:39 2001-09-13
│ └呵呵哈 [没脾气](10) 16:10:09 2001-09-13
│ { 呵呵
│ {
├在Delphi里面就是不行啊。 [goodhope](0) 09:58:06 2001-09-14
└注意看 System Unit 的 _Halt0 [没脾气](0) 10:42:53 2001-09-14
└看不出门道来 [goodhope](0) 11:15:12 2001-09-14
└我对 ExitProcess 的使用还不甚了解,不过应该在这里要注意 [没脾气](95) 11:28:55 2001...
│ { 标题:我对ExitProcess的使用还不甚了解,不过应该在这里要注意[没脾气](95)11:28:552
│ { 001-09-14
│ { 正文:ifInitContext.OuterContext=nilthen
│ { ExitProcess(ExitCode);
│ {
└我把Halt的代码搬到外面来,并在ExitProcess前插入这段代码,还是不行。 [goodhope](1...
│ { 标题:我把Halt的代码搬到外面来,并在ExitProcess前插入这段代码,还是不行。[good
│ { hope](142)12:15:252001-09-14
│ { 正文:无论在哪UnmapViewOfMap肯定是起了作用的,在它后面无法访问代码段的任何内容
│ { 。程序正常终止,流程肯定也正确。但就是删不掉文件。VC里面工作正常。
├要注意,有一层函数栈的位置就不一样呀 [没脾气](0) 13:17:31 2001-09-14
│├所以不知道 program 中的 begin end 是第几层的 [没脾气](0) 13:18:37 2001-09-14
│├也许无关 [没脾气](0) 13:20:01 2001-09-14
│└没有关系的。 [goodhope](0) 13:28:11 2001-09-14
├你怎么搬的? [没脾气](0) 13:24:45 2001-09-14
│└Copy [goodhope](0) 13:27:09 2001-09-14
│ └Paste [goodhope](0) 13:27:26 2001-09-14
│ └InitContext 没有定义呀 [没脾气](0) 13:29:23 2001-09-14
│ └我是这样解决的 [goodhope](219) 13:56:42 2001-09-14
│ │ { var
│ │ { pContext:pInitContext;
│ │ { begin
│ │ { pContext:=Pointer($40648C); //AddressofSystem.InitContext
│ │ { MyInitContext:=pContext^;
│ └我靠,你太牛了,地址是怎么算出来的,跟踪??真的假的 [没脾气](0) 13:...
│ │ { 标题:我靠,你太牛了,地址是怎么算出来的,跟踪??真的假的[没脾气]
│ │ { (0)13:59:342001-09-14
│ │ { 正文:--无内容--
│ ├Project -> Options -> Compiler -> Use Debug DCUs [goodhope](0) 14:...
│ │ { 标题:Project->Options->Compiler->UseDebugDCUs[goodhope](0)14:01
│ │ { :492001-09-14
│ │ { 正文:--无内容--
│ └如果你定义MyInitContext为第一个全局变量,那么pContext := Pointer(I...
│ │ { 标题:如果你定义MyInitContext为第一个全局变量,那么pContext:=Poi
│ │ { nter(Integer(@MyInitContext)-$74);[goodhope](1635)14:28:242001-0
│ │ { 9-14
│ │ { 正文:var
│ │ { MyInitContext:TInitContext;
│ │ {
│ │ { Module:THANDLE;
│ │ { Buf:array[0..MAX_PATH]ofChar;
│ │ { pExitProcess,pDeleteFile,pUnmapViewOfFile:Pointer;
│ │ {
│ │ { procedureDeleteSelf;
│ │ { var
│ │ { Result:Boolean;
│ │ { Information:Cardinal;
│ │ { begin
│ │ { pExitProcess:=@ExitProcess;
│ │ { pDeleteFile:=@DeleteFile;
│ │ { pUnmapViewOfFile:=@UnmapViewOfFile;
│ │ { Module:=GetModuleHandle(nil);
│ │ { GetModuleFileName(Module,Buf,Sizeof(Buf));
│ │ { CloseHandle(THANDLE(4));
│ │ {
│ │ { asm
│ │ { lea eax,buf
│ │ { push 0
│ │ { push 0
│ │ { push eax
│ │ { push pExitProcess
│ │ { push Module
│ │ { push pDeleteFile
│ │ { push pUnmapViewOfFile
│ │ { ret
│ │ { end;
│ │ {
│ │ { end;
│ └这个就可以了吗?第一个全局变量?如果我有多个包含全局变量的unit,...
│ │ { 标题:这个就可以了吗?第一个全局变量?如果我有多个包含全局变量
│ │ { 的unit,哪一个算第一个全局变量?[haitao](0)14:36:432001-09-14
│ │ { 正文:--无内容--
│ └这就难说了,不同的包含次序的确会引起偏移变化。不过你可以这样:...
│ { 标题:这就难说了,不同的包含次序的确会引起偏移变化。不过你可
│ { 以这样:[goodhope](164)14:43:352001-09-14
│ { 正文:用SysInit单元中的ModuleIsLib计算偏移,它的上一个变量就
│ { 是InitContext
│ { 所以
│ { pContext :=Pointer(Integer(@ModuleIsLib)-SizeOf(MyInitContex
│ { t));
└控制台程序也不行。看来,Delphi还打开了一些资源。 [goodhope](0) 13:29:23 2001-0...
│ { 标题:控制台程序也不行。看来,Delphi还打开了一些资源。[goodhope](0)13:29:232
│ { 001-09-14
│ { 正文:--无内容--
└和控不控制台没关系,在 ExitProcess 前,他才释放的他的资源,至少包含 Windows ...
{ 标题:和控不控制台没关系,在ExitProcess前,他才释放的他的资源,至少包含Win
{ dowsAPI的DLL[没脾气](0)13:30:402001-09-14
{ 正文:--无内容--
我的blog:http://szhaitao.blog.hexun.com & http://www.hoolee.com/user/haitao
--以上均为泛泛之谈--
不尽牛人滚滚来,无边硬伤纷纷现 人在江湖(出来的),哪能不挨刀(总归是要的)
网络对话,歧义纷生;你以为明白了对方的话,其实呢?

您所在的IP暂时不能使用低版本的QQ,请到:http://im.qq.com/下载安装最新版的QQ,感谢您对QQ的支持和使用

相关信息:


欢迎光临本社区,您还没有登录,不能发贴子。请在 这里登录