抛开写蠕虫导致的道德问题不谈,单就技术而言,应该承认,写这个程序的人是一个老练的Windows 程序员,代码风格不错,程序写得中规中矩,很多地方值得学习。里面也用了 不少技巧,显示出作者对Windows的了解。这个程序还是有看头的。
1、看看删除自身的函数
首先来看蠕虫删除自身的函数。Windows 应用程序是不能直接删除自身的,因为程序运行的时候系统使用了memory-mapped files 机制将文件所占的那一部分空间作缓存。要删除,最简单的法子是先创建一个批处理文件,在批处理文件中删除主文件,然后让批处理文件删除自身,或者直接在程序中调用“cmd /c del”,再就是借助系统的一些机制(详见Jeffrey Richter在MSDN January 1996 那篇“Win32 Q&A”中的论述,地址:http://www.microsoft.com/msj/archive/SF9C.aspx)。而这个蠕虫用的是另外一种巧妙的方法,这个方法是Gary Nebbett提出来的。
;call from 004012CE
:00402970 55 push ebp
:00402971 8BEC mov ebp, esp
:00402973 81EC10020000 sub esp, 00000210
:00402979 56 push esi
:0040297A 8B35A8404000 mov esi, dword ptr [004040A8] ;esi = kernel32.GetModuleFileNameA
:00402980 8D85F4FEFFFF lea eax, dword ptr [ebp+FFFFFEF4]
:00402986 6804010000 push 00000104
:0040298B 50 push eax
:0040298C 6A00 push 00000000
:0040298E FFD6 call esi ;kernel32.GetModuleFileNameA
:00402990 8D8DF4FEFFFF lea ecx, dword ptr [ebp+FFFFFEF4]
:00402996 51 push ecx
:00402997 FF1574404000 Call dword ptr [00404074] ;kernel32.GetFileAttributesA
:0040299D A801 test al, 01 ;看文件是否设置了只读属性
:0040299F 7410 je 004029B1 ;如果无则直接跳过去删除文件
:004029A1 24FE and al, FE ;如果有则去掉只读属性
:004029A3 8D95F4FEFFFF lea edx, dword ptr [ebp+FFFFFEF4]
:004029A9 50 push eax
:004029AA 52 push edx
:004029AB FF1578404000 Call dword ptr [00404078] ;kernel32.SetFileAttributesA
;以下的就是Gary Nebbett那一段经典代码:
;jmp from 0040299F
:004029B1 6A00 push 00000000 ;参数为空,返回自身句柄
:004029B3 FF157C404000 Call dword ptr [0040407C] ;kernel32.GetModuleHandleA
:004029B9 8D8DF0FDFFFF lea ecx, dword ptr [ebp+FFFFFDF0]
:004029BF 6804010000 push 00000104
:004029C4 51 push ecx
:004029C5 50 push eax
:004029C6 8945FC mov dword ptr [ebp-04], eax
:004029C9 FFD6 call esi ;KERNEL32!GetModuleFileNameA
:004029CB 6A04 push 00000004 ;文件映像的硬编码4
:004029CD FF15E0404000 Call dword ptr [004040E0] ;kernel32.CloseHandle
:004029D3 8D85F0FDFFFF lea eax, dword ptr [ebp+FFFFFDF0]
:004029D9 6A00 push 00000000
:004029DB 6A00 push 00000000
:004029DD 50 push eax ;程序本身文件名
:004029DE FF35BC404000 push dword ptr [004040BC] ;KERNEL32!ExitProcess
:004029E4 FF75FC push [ebp-04] ;映像地址,这里是00400000
:004029E7 FF35E8404000 push dword ptr [004040E8] ;KERNEL32!DeleteFileA
:004029ED FF3580404000 push dword ptr [00404080] ;KERNEL32!UnmapViewOfFile
:004029F3 C3 ret