lllsd
驱动牛犊
驱动牛犊
  • 注册日期2001-10-01
  • 最后登录
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1420回复:7

高手们请帮帮忙啊~

楼主#
更多 发布于:2001-10-02 19:24
我在http://lu0.126.com上看了一篇程序自删除的文章,但是还是不明白,原文如下:
精妙代码
作者:陆麟
转载请征得作者同意.
2001.1.12

--------------------------------------------------------------------------------

下面的代码由Gary Nebbett写就.Gary Nebbett乃是WINDOWS NT/2000 NATIVE API REFERENCE的作者.乃NT系统一等一的高手.下面就分析一些他的这段代码.
这段代码在PROCESS没有结束前就将启动PROCESS的EXE文件删除了.
int main(int argc, char *argv[])
{
    HMODULE module = GetModuleHandle(0);
    CHAR buf[MAX_PATH];
    GetModuleFileName(module, buf, sizeof buf);
    CloseHandle(HANDLE(4));
    __asm {
        lea     eax, buf
        push    0
        push    0
        push    eax
        push    ExitProcess
        push    module
        push    DeleteFile
        push    UnmapViewOfFile
        ret
    }
    return 0;
}
现在,我们先看一下堆栈中的东西

偏移 内容
24   0
20   0
16   offset buf
12   address of ExitProcess
8    module
4    address of DeleteFile
0    address of UnmapViewOfFile

调用RET返回到了UnmapViewOfFile,也就是栈里的偏移0所指的地方.当进入UnmapViewOfFile的流程时,栈里见到的是返回地址DeleteFile和HMODUL module.也就是说调用完毕后返回到了DeleteFile的入口地址.当返回到DeleteFile时,看到了ExitProcess的地址,也就是返回地址.和参数EAX,而EAX则是buffer.buffer存的是EXE的文件名.由GetModuleFileName(module, buf, sizeof buf)返回得到.执行了DeleteFile后,就返回到了ExitProcess的函数入口.并且参数为0而返回地址也是0.0是个非法地址.如果返回到地址0则会出错.而调用ExitProcess则应该不会返回.
这段代码的精妙之处在于:
1.如果有文件的HANDLE打开,文件删除就会失败,所以,CloseHandle(HANDLE(4));是十分巧妙的一手.HANDLE4是OS的硬编码,对应于EXE的IMAGE.在缺省情况下,OS假定没有任何调用会关闭IMAGE SECTION的HANDLE,而现在,该HANDLE被关闭了.删除文件就解除了文件对应的一个句柄.
2.由于UnmapViewOfFile解除了另外一个对应IMAGE的HANDLE,而且解除了IMAGE在内存的映射.所以,后面的任何代码都不可以引用IMAGE映射地址内的任何代码.否则就OS会报错.而现在的代码在UnmapViewOfFile后则刚好没有引用到任何IMAGE内的代码.
3.在ExitProcess之前,EXE文件就被删除了.也就是说,进程尚在,而主线程所在的EXE文件已经没了.(WINNT/9X都保护这些被映射到内存的WIN32 IMAGE不被删除.)

Gary Nebbett果然是WIN系列平台的顶尖高手之一.能写出如此代码.独辟蹊径啊:)
---------------------------------------
CloseHandle(HANDLE(4)); 这一行代码根本就不能编译通过,大家能给我指点以下吗?
先谢了!
Tomgin
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2005-06-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2001-10-06 10:10
我建了一个控制台工程,将代码拷过去,加一个
#include "windows.h"
就可以编译过去了。
没有出现你说的情况。
努力呀,还有许多东西不会呢。
iamaf~1
驱动小牛
驱动小牛
  • 注册日期2001-09-23
  • 最后登录2003-06-26
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2001-10-06 10:14
了不起呀
这个论坛不支持长用户名,害得我iamafraid 只好叫iamaf~1了...
oneq
驱动牛犊
驱动牛犊
  • 注册日期2001-03-23
  • 最后登录2001-11-22
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2001-10-06 16:51
我用VC5+ME编译通过,但程序运行后依然存在。原因?
iamaf~1
驱动小牛
驱动小牛
  • 注册日期2001-09-23
  • 最后登录2003-06-26
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2001-10-06 16:59
我的运行后立刻不见了

VC6+Win2k pro
这个论坛不支持长用户名,害得我iamafraid 只好叫iamaf~1了...
Tomgin
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2005-06-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2001-10-07 09:14
程序正确在 vc6 + 2k server 上。
努力呀,还有许多东西不会呢。
Tomgin
驱动牛犊
驱动牛犊
  • 注册日期2001-08-08
  • 最后登录2005-06-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2001-10-07 09:21
vc6 + 98-2 上不正确。

看样子,这个功能代码是 nt/2k 上的,不是 98/me 的。
努力呀,还有许多东西不会呢。
oneq
驱动牛犊
驱动牛犊
  • 注册日期2001-03-23
  • 最后登录2001-11-22
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2001-10-07 20:40
哪位大虾将其移植到win9x下吧,让我开开眼。
游客

返回顶部