近几年杀毒软件泛滥,很多人不知道该如何选择合适的杀毒软件,也许杀毒软件并非是必需的,但这不是今天要谈论的话题,今天要谈的是杀毒软件究竟是个什么东西,它到底是如何杀死病毒的,也许当你了解了它的工作原理和运行模式,你也许对病毒也会有所认识,不再感到畏惧。
杀毒软件(Anti Virus),也称反病毒软件,以下可简称AV软件,是一种保护用户的数据和信息的一套安全系统。从类别上划分,它可以分为几种类型,如扫描型,防御型,主动控制型等。
扫描型(Scan),这是一种最原始的方式,由于病毒出现得比较早,从DOS和win3.x时代就开始流行,那时候的病毒可能只是几行简单的代码,不过破坏力却是不可小视的。说到病毒,其实它和其它普通的程序没什么不同,所不同的只是它们的立场,一个是保护,一个是破坏,只此而已。所谓扫描病毒,就是扫描病毒程序本身的特征,然后与杀软病毒库中的特征码作对比,找到了说明它是个病毒,否则就是无危险的程序,随着病毒种类的增多,病毒库的体积也会越来越大。直到后来进入Windows时代,就出现了一种防御型的杀毒软件。
主动防御控制型,也叫HIPS(主机入侵防御系统),它可以是单独的一种软件,如E盾(EQSecure)、360的Malware Defender、Comodo(科摩多),也可以是附加的功能,如卡巴斯基,360等,现在它是大部分杀软都具有的功能,有些以扫描为主,有些则以主防为主,扫描型病毒比较经典的我只记得有一个macfee(麦咖啡)的软件,主防型的有东方微点主动防御软件。
除此之外,还有几种形式,其实可以把它们看作是主防的变形,这种程序叫做沙盘(SandBox)、沙盒或沙箱,这是一种主动控制型的,沙盒程序控制了系统比较重要的API,所以目标程序的行为基本都会在沙盒的监控之中。但是注意,会有漏沙的可能,而且前面说了它只是控制了关键API,而不是所有,所以沙盒并不是绝对的安全,只能说它在一定程度上是安全的。"在沙盒中运行程序既能保证安全又不影响程序原本的功能"这种说法严格讲是不对的,因为这两者是矛盾的,沙盒既不能保证绝对的安全,又不能做到完全不影响程序自身的功能,事实上,市面上普通的安全工具在沙盒中运行就无法发挥它的原有功能,例如一个进程管理器要结束系统进程,不用说,沙盒肯定会阻止。那有没有绝对安全的呢?有,那就是另一种更强大的沙盒,也就是虚拟机。虚拟机程序是利用驱动控制计算机的硬件,达到从逻辑上创建若干虚拟主机的目的,在虚拟机里,所有的程序都无法与真实操作系统中的程序直接传递信息,所以虚拟机可以说是绝对的安全,除非你能找到它的漏洞,但是这种概率非常低,虚拟机里的病毒想穿透机器到原始系统中搞破坏几乎是不可能的。其它这些形式并没有严格的区分,反病毒软件可包含以上所有功能,它可能有自己的虚拟运行环境,可能有病毒数据库,也可以有主防系统。
再看杀毒软件的杀毒机制。一般来说,杀软都有自己的数据库,里面存放病毒程序的特征,理论上只有一个文件存在这个特征,就会被认定是有危险的,无论它的格式是什么,哪怕是一个TXT,也会被当作病毒被隔离,甚至这个文件是它自己的东西。当然杀毒软件一般不会自己杀自己,那是因为它自己的文件都会有一个签名,倘若签名丢失,那它就瓦解了,换句话说,连自己都不认识了。前不久有个叫熊猫卫士的产品,据说是因为数字签名损坏,所以把自己的一个核心程序当作病毒杀掉了,结果也就无法再启动。这还不算讽刺,前几天发现了个可疑驱动DMProtectEx.sys,删掉后会再生,以为是病毒,没想到最后经诊断居然是ADSafe的广告拦截驱动。所以有了签名就不会被杀,那么如果我购买一个签名,就相当于向杀软公司交了保护费,这样以后凡是我写的程序,该杀软都会认为是正常的程序。这么看,就算杀毒软件不理,也并不意味着它是安全的,其实事实远不止于此,据说有些杀毒软件厂商甚至还自己制造病毒,然后再拿来杀掉,以提高自己产品的知名度,以上这些不知道是否是杀毒界的潜规则。
主动防御的任务,就是在目标程序对系统进行破坏之前拦下它。那怎么看目标是否是一个有害的程序呢?判断标准是通过行为特征分析,观察和监控它的动作,看它是否做出一些出格的举动。例如,一个程序运行后先是创建自己的副本,之后立即将该副本注册为开机启动对象,这样的行为是病毒或木马的典型特征,再者将自己注入系统进程、安装系统消息钩子、安装和加载驱动等等,这些全都属于危险行为。那么,问题是杀毒软件怎么知道这些的?它怎么知道目标程序具体都做了些什么?下面不得不简要说一下Windows的原理。
在Windows上运行的程序,能够执行的有EXE、DLL、SYS、OCX等,这些都叫做可执行文件(Executable File),也就是包含CPU指令、可以控制电脑硬件和指挥电脑的一类程序。这些可执行文件属于PE(Protable Executable)文件,是一种可移植的执行格式,这是一种具有特殊结构的程序,程序中包含数据、资源和指令。而文档(Document)又称数据文件,里面不含任何指令,但是能被可执行文件读取。病毒可以是EXE,也可以是DLL、SYS等,但是不可能是BMP、TXT之类的程序,因为这些程序都不能执行命令,当然不排除病毒伪装成普通档案的情况。有些病毒将自己命名为test.txt.exe,如果系统扩展名没有显示,表面上并不能看出它的文件类型。照这么说,如果一个文件名字的结尾确实是.txt,那就代表它一定没有危险吗?当然不是,因为文件名其实并不能说明什么,重要的是文件内容和格式,因为但凡稍微改动一下注册表,就会让一个扩展名为txt的应用程序能够双击触发,这个牵涉到系统的文件关联(Association)机制,后面会讲到。用记事本(notepad)打开一个txt,如果开头是MZ,说明它极可能是一个可执行程序(EXE或DLL等),紧接着后面还会有这样一句话:This program cannot be run in DOS mode. 意思是:这个程序不能运行在DOS模式,说明它是Win32位应用程序,而DOS系统下只能运行16位的程序,而且后面会看到PE两个字符,这些是EXE的通用格式,所有EXE都是如此,否则就无法执行。DLL(Dynamic Link Libraries)是动态链接库文件,也属于可执行文件的一种,能够被其它EXE间接调用并执行,从某个角度而言,DLL比EXE更加危险,EXE运行后至少有一个进程(Process),而DLL则没有进程,它的代码位于进程内部,要查看进程的DLL模块,就要用到第三方软件。进程(Process)是指程序活动的地方,内存中的一片区域,一个空间,一个场地。一个程序,比如Windows记事本,文件名叫notepad.exe,运行后会创建一个进程,进程名也叫notepad.exe,路径是C:\Windows\System32\notepad.exe,其实这个路径是模块路径,进程本身是没有路径的,它就是一个空间,里面存放着各种不同的资源,其中包括一个exe和多个dll,这些exe和dll到了内存中,叫做模块(Module),模块路径就是文件路径,进程路径是指EXE模块的文件路径。进程只是一个区域,执行任务的则是线程(Thread)。一个进程可以有多个线程,没有线程,它就成了僵尸进程,什么也做不了。如果我要同时做一些不同的任务,只需多创建一些线程即可。
杀毒软件要控制另一个程序,就必须控制系统的API调用。API(Application Programming Interface,应用程序编程接口)函数是软件完成相应功能必须要调用的东西,一个API对应一个功能,参数决定功能的细节。API的本质就是一段代码,这些代码位于系统的DLL中,一个DLL文件含有若干API。举例说明,例如"结束进程",就要调用一个TerminateProcess的API,任务管理器(Taskmgr.exe)里面终止一个进程,就是调用了它。当然,其它进程管理软件大多也是调用它。这个函数位于kernel32.dll中,而这个函数的代码里,会继续调用另一个更底层的API:ZwTerminateProcess(NtTerminateProcess),Zw/Nt系列函数位于文件ntdll.dll中,也就是说ntdll.dll比kernel32.dll里的代码更接近系统底层,所以,你也可以直接调用ZwTerminateProcess去终止一个进程。然而,单独靠这个函数是无法结束其它进程的,还要有其它函数配合使用才行,要结束一个进程,首先要"打开"(Open)这个进程,OpenProcess(打开进程)函数正是负责干这个的。Windows下的每一个进程都有一个进程ID(ProcessId),它是进程唯一的标识符,要打开进程,就要指定进程ID,标明你究竟要打开哪个进程,例如记事本notepad.exe的进程Id是1234,你就要OpenProcess这个1234,获取目标进程的句柄。句柄(Handle)你可以理解为一把钥匙,一种权限,有了对象的句柄,你才可以访问这个对象,就像有了钥匙才能开门一样。比如刚才我们打开了记事本的句柄,得到句柄值0x100,然后再TerminateProcess这个0x100,意思是终止句柄值为0x100这个进程,这样就把记事本给杀掉了。那么,如果我打开了记事本的进程得到0x100后,然后用另一个程序调用TerminateProcess去结束这个0x100,能把记事本给结束掉吗?答案是不能,因为首先句柄值是会变的,你这次打开得到0x100,下次再打开就可能会变成0x200,每次打开的值都是不同的,而且这个0x100是私有对象,只对打开它的程序有用,也就是说,0x100这个值属于你自己内部的东西,只对你有意义,对其它程序来说,0x100不代表任何进程。进程句柄属于内核对象句柄,除此之外,还有一种叫做GDI的句柄,这种句柄是不变的,例如窗口句柄(HWND),窗口在创建后其句柄就保持不变,直到窗口销毁(Destroy),也就是我们平时所说的关闭窗口。窗口句柄是公开的,完全暴露给用户,通常情况下任何进程都能访问。
现在,当你在任务管理器里去结束一个进程,结果却提示拒绝访问,这是怎么回事呢?这是因为,你没有权限访问目标进程。一种可能是,你不是管理员(Administrator),另一种可能是,这个进程被Hook(钩住、控制、拦截)了。为什么会被Hook呢?因为有进程采用了Hook API技术修改了这个函数地址,它钩住了OpenProcess这个API函数,当发现你要结束的进程是它时,它就跳过这个API,什么也不执行,直接返回。所以你收到的就不是进程句柄,而是0,既然打开失败,下一步结束进程就别谈了,只有当你有了句柄,有了所有权,你才能结束它,读写它,或者做其它什么都行,没有句柄,就什么也做不了。杀毒软件Hook了NtOpenProcess、NtTerminateProcess这些API,所以你想用普通的方法结束杀毒软件的进程,是没有用的,但是不代表不能用其它方法结束它的进程,如通过结束GUI界面来结束它。同样的,杀毒软件能够监控你的行为,得到你的一举一动,并随时准备kill掉你,也全是因为hook了和系统安全相关的API,所以才如鱼得水。
杀软要监控系统,是从创建进程(CreateProcess)开始的,每一个进程都是由其它进程创建,记事本所以能运行,是因为你双击了一个TXT文件,而TXT又和Notepad.exe关联,所以系统就调用了Notepad,顺便传给它一个命令行参数(Command Line),参数就是TXT文件的路径,Notepad运行后会检查自己后面是否带有参数,有的话就把它当成一个文件路径并打开它,如何处理参数则是程序员的事情。双击notepad.exe,或者从开始程序中选择记事本,或从开始->运行中输入notepad并打开,notepad都是由Explorer.exe这个进程来创建的,notepad的父进程就是Explorer.exe(Windows Shell进程),就是我们通常所说的桌面进程。如果在cmd中输入命令并启动,这时启动后的程序的父进程就是cmd.exe。而Explorer.exe的父进程是userinit.exe,创建完Explorer后它就退出了,userinit的父进程是winlogon.exe(登录进程),winlogon.exe的父进程是smss.exe(会话管理器,第一个进程,由内核创建)。杀软hook了NtCreateProcessEx、NtCreateSection等API,这样,任何进程启动都在它的监控之中,如果有可疑动作就弹窗提示或直接隔离。那么,hook究竟做了什么呢?其实hookAPI就是改掉目标进程API入口地址,跳转到它自己的地址,如果是这样的话,病毒运行后难道不会检查自己进程内存是否被修改过,从而再改回来吗?其实hook也分很多种,杀毒软件hook的不是目标进程的数据,而是系统内核数据,这就要谈到进程内存管理。
Windows系统每个进程的内存都各自独立,一个进程的崩溃不会影响到另一进程,更不会影响到操作系统进程,这是因为为了避免用户的代码波及系统内核代码,系统把内存划分开来,一个是用户内存,一个是内核内存,应用程序代码工作在用户模式(user mode),操作系统的代码运行在内核模式(kernel mode),这样用户进程发生的错误由自己承担,而不会引起系统崩溃。当程序需要到内核请求服务时,它会通过指令从用户模式切换到内核模式,完成服务后控制权会切换回来。Win32下每个进程都有一个虚拟的4GB内存空间,用户代码只能访问2GB以下空间,驱动程序代码可以访问全部空间,不过有一个64KB的区域,地址从0x7FFF0000-0x7FFFFFFF,这个地方它们都不能访问。EXE、DLL都在用户内存活动,而不会跑到内核内存,操作系统则在内核内存中运行,要访问内核内存的数据,就要写成驱动程序(Drivers)Sys格式,只有sys格式的可执行文件才有权限进入系统内核,从而获取系统的完全控制权。所以,杀毒软件都会有自己的驱动,也就是至少有一个sys文件,运行后加载到内存,便可充分进入Windows系统。如果驱动的代码存在漏洞,则可能会导致系统内核崩溃,从而引起蓝屏(BSOD)。蓝屏是驱动程序代码发生异常的结果,而EXE的代码是不会造成系统崩溃的,因为它没有访问系统内存的权限。从用户空间(ring3)进入内核空间(ring0),需要经过一道门----SSDT(System Services Descriptor Table),称"系统服务描述符表",这是一张系统服务表,ntdll.dll中的NT系列函数最终要访问的就是SSDT,所以要最终结束一个进程,必然要经过SSDT中的NtTerminateProcess函数,杀软在驱动中拦截了NtTerminateProcess、NtTerminateThread、NtOpenProcess等系统服务,从而保证自己不被ring3下的EXE程序干掉。SSDT最终要通往系统内核,去执行真正的代码,所以,要挂得彻底,就要挂钩内核,也就是inline Hook。不过,相对而言,SSDT更稳定,所以有些程序还是挂的SSDT,当然也有挂内核的,例如360。那如果病毒也进入内核怎么办?病毒一旦进入内核,杀毒软件就无法再对其进行安全控制,系统就被完全劫持,杀软的主防也就彻底失去了作用。所以,驱动病毒(Rootkit)是最危险的,如果一个程序要安装驱动,一定要确定它是安全的才能放行。
可是,有些杀毒软件已经过滤了终止进程的服务,可为什么还是会被其它进程Kill掉呢?这是因为杀进程不一定要用标准的终止进程函数,还可以从它的GUI(图形用户界面)下手。早期的安全软件自我保护不够彻底,只单单保护了进程和线程,而没有保护窗口界面。Windows有一个消息通信机制,依靠消息传递来和窗口进行通信,窗口创建后会收到许多系统消息,如果病毒进程向杀毒软件发送了这些消息,杀软进程将会出现问题,甚至挂掉。比如要杀掉一个窗口,就向目标窗口发送WM_CLOSE、WM_QUIT、WM_DESTROY等消息,窗口就会被销毁,进程也随之退出。不过现在的杀软保护机制比以前要完善,这些消息如今已经过时了。但没有绝对的安全,任何程序都有漏洞(bug),要干掉AV软件,就要寻找它的漏洞,然后给它致命一击。除此之外,Windows的消息还有好多,如WM_MOVE(移动窗口),WM_SIZE(改变窗口大小)等等。那我有没有办法控制其它进程的窗口呢?办法是有的,还是调用系统API,例如我要移动记事本notepad的窗口,就必须先得到它的句柄(hWnd),然后MoveWindow它或SetWindowPos它到任意位置。句柄怎么获取呢?可以通过EnumWindows、GetWindow、FindWindow等函数遍历系统所有窗口,然后再得到其标题和类名,就能大致找到它。
但是,有些窗口却无法关掉,即使向它发送了WM_CLOSE,这是怎么回事?因为目标窗口Hook了WM_CLOSE消息,将它拦了下来。不急,我们还有其它方法,就是隐藏(Hide)它。系统有许多窗口,大部分都处于隐藏状态,只有少数能看见,"隐藏"属于窗口样式(Window Style)的一种,窗口样式也叫窗口风格,是指一个窗口的外观,就像人的相貌一样,不同的人长相不同,窗口也是如此。有些窗口能改变大小,有些不能,有些有最小化最大化按钮,有些一直位于顶层,还有些没有标题栏,甚至有些窗口是透明的,鼠标点击不到等等,这些都属于窗口的样式,要获取窗口的样式,就要GetWindowLong,改变一个窗口的样式要SetWindowLong,比如要隐藏一个窗口就要把它的WS_VISIBLE样式去掉,当然通常的做法是ShowWindow(显示窗口),ShowWindow可以将目标窗口隐藏或显示、最小化及最大化,实际上依然是改变了窗口的样式。同样的,要让一个窗口永远处于最前面,就要用SetWindowPos,给它添加一个WS_EX_TOPMOST样式。有些窗口比较特别,它们是编程中的控件(Control),比如TextBox、ListBox,Button等,控件本质也是窗口,只不过是子窗口,是属于某个窗口内部的窗口,这样的窗口不能移出它的父窗口,子窗口除了具有标准窗口的样式之外,还有它自己独特的Style,子窗口可以再有子窗口,如此形成窗口树,这一点和进程差不多。获取子窗口用GetWindow,获取父窗口可以用GetParent,不过不建议使用,因为GetParent这个API有问题,它有时会取到"所有者"(Owner)窗口,获取父窗最好用GetAncestor。每个窗口都有一个顶级父窗,叫做"桌面"(Desktop),这个桌面不是Explorer的桌面,而是系统内核win32k.sys创建的窗口,属于win32子系统进程csrss.exe的窗口,但是有些可能不属于Desktop,例如消息(Message)窗口。另外,窗口还有其它属性,比如窗口大小,获取窗口尺寸用GetWindowRect,这个API会取到一个矩形(Rect),Rect由两个点(Point)组成,一个是窗口左上角坐标,一个是窗口右下角坐标,当窗口最小化时是取不到的,只能用GetWindowPlacement得到它的还原矩形。窗口是由进程创建的,确切地说是由线程创建的,所以每个窗口一定都有一个对应的进程和线程,比如桌面图标窗口(Progman)、任务栏窗口(Shell_TrayWnd)以及文件管理器窗口(ExploreWClass),都属于Explorer.EXE进程。当我们双击一个txt或jpg也会产生一个窗口,这个窗口是个exe程序,或者说是一个软件,软件和相关文件类型存在关联所以才能自动调用EXE,而txt和jpg是不会有窗口的。窗口除了窗口矩形,还有客户矩形(Client Rect),客户矩形是一个窗口的工作区,是可以通过代码控制的部分,是程序员可以直接访问的那片区域,而非客户区(Not Client)则由Windows系统控制,标题栏(CaptionBar)、菜单栏(MenuBar)、窗口边框(Border)都属于非客户区。注意,菜单栏不一定是含有菜单的栏目,它也可能是伪菜单栏,比如工具栏(ToolBar)或自绘控件。工具栏是一个窗口,属于窗口类,而菜单栏不是窗口,没有句柄,它只是窗口非客户区的一个区域罢了,如资源管理器中的菜单栏,实际上是一个ToolBar窗口,仍然属于客户区部分。获取窗口属性的常用工具有Spy++、ViewWizard等。
所谓知己知彼,百战百胜,杀软要对付病毒,就要知道它的原理,知道它一般要干些什么事。早期的病毒一般是感染,感染可执行文件,病毒遍历所有EXE文件并将它自己的文件Bytes写入EXE之前,这样双击一个EXE,首先启动的就是病毒程序,病毒程序获取控制权后,再回到原始文件的代码入口执行原来的程序代码,这样用户便发现不了它的踪迹,还有些则是纯属玩笑程序(Joke)。而如今的病毒程序一般以木马为主,他们利用木马入侵用户的计算机并从中获取利益。典型的木马程序有键盘记录(Keyboard Logger)、勒索程序等。
键盘记录的方式有很多,比如消息钩子、定时截取按键、过滤驱动等。消息钩子最为常见,病毒启动后通过SetWindowsHookEx注册一个系统钩子,然后就能监控到系统全局的按键。一种方式是通过DLL注入系统所有GUI进程获取记录,另一种是通过低级钩子(WH_KEYBOARD_LL)捕获记录,定时截获一般是通过GetKeyState、GetAsyncKeyState等函数截取记录,DirectX游戏按键记录等,更底层的则是直接释放一个键盘过滤驱动(Filter Driver)到用户电脑。另一种形式是通过发送WM_GETTEXT、EM_GETPASSWORDCHAR获取编辑框和密码框的内容,来达到记录用户输入信息的目的。钩子的作用不仅限于键盘记录,它还有其它许多作用,相比之下,另一种技术则显得有些过时,它是远线程注入(Insert Thread),一般的程序不需要什么注入其它进程,所以但凡调用CreateRemoteThread则基本会被认定是木马。还有种病毒属于恶意程序,专门搞破坏,比如删除文件,格式化磁盘,改文件夹图标,伪装成文件夹等,这种病毒行为虽然简单,但破坏性却很为严重,看似简单的东西反而是最危险的。与EXE病毒相比,DLL病毒则更加可怕,如LPK.dll病毒,它和系统文件lpk.dll同名,运行后在本机搜索WinRAR等压缩器程序,然后将自己写入到压缩包中去,属性设为隐藏。当用户双击EXE后,EXE会在当前目录下寻找lpk.dll,找到的话就加载,随之病毒就从Dll入口处执行目标代码。对付它的办法是在注册表中声明该DLL库,使程序在运行后先到系统目录(system32)中寻找该DLL,而不是先到应用程序目录下寻找该库文件。所以说设置成"显示所有文件"是有必要的,真正重要的东西不必隐藏,而应该加密。中了病毒重装系统就没事了吗?并不是的,有时病毒会将自己复制到所有分区下,恢复系统只是恢复了系统盘(C盘),而其它盘并没有发生改变(D盘可能会被安装些程序),所以如果你不小心又运行了其它盘的病毒,那就悲剧了。病毒的启发方式也有很多,如改变注册表关联,改IFEO(映像劫持),写Autorun.inf等。在资源管理器中双击一个程序,并没有立即为它创建进程,而要到注册表寻找其对应的另一个程序,病毒将目标程序篡改,从而达到偷粱换柱的目的。一个进程运行的步骤是:shell32.ShellExecute->kernel32.CreateProcess->ntdll.ZwCreateProcessEx,最后是SSDT的NtCreateProcessEx。双击是从ShellExecute开始执行的,到了ntdll时,进程目标才得以确定,中途可以在注册表中改掉目标。
仅运行了起来是远远不够的,病毒还要将自己写入自启动列表,以便长久落脚。自启动是一项很复杂的机制,有开始菜单启动、注册表开机启动,还有服务启动、驱动启动、DLL启动等。自启目标未必是EXE,只要代码到了内存就会执行,有时一个程序后台启动了,但却无论如何找不到它的启动项,这是因为它采用了DLL的方式启动。工欲善其事,必先利其器,要查看这些启动项就要用到利器,Autoruns就是专门干这个的。要阻止病毒,就要充分了解启动项,从一定上意义讲,阻止了自启,就等于阻止了病毒。只要它不自启,重启电脑后它也就不会再运行,不运行就没有控制权,那么我们就有时间揪出潜藏在深处的恶意程序。
病毒要生存就要首先保护自己。隐藏(Hide)和伪装是一个有效的方法,首先要隐藏进程,那要就hook掉获取进程的API,最基本的是在系统的任务管理器(Taskmgr)中隐藏自己,Taskmgr获取进程用的是NtQuerySystemInformation,那病毒就要hook掉该API,抹去自己。然后是伪装,比如伪装成系统进程的名字,如svchost.exe,或者修改模块PEB伪装自己的路径。接下来是隐藏文件,hook掉NtQueryDirectoryFile(查询目录文件),在资源管理器就看不到它了。除了隐藏和伪装,还可以保护,比如像杀软一样过滤掉NtOpenProcess等API,就能防止Taskmgr结束自己,但如果碰到驱动级管理器就无效了,带驱动的辅助工具称为ARK,也就是反内核工具,它工作在ring0层,属于手杀工具的一种,它不但能够保护自己,还能检查系统内核的状态,判断内核代码是否异常,当然还具有强杀功能,比较有知名度的软件代表是IceSword(冰刃)、PCHunter(原XueTr)、PowerTool等,ring3下的工具比较少,比如我编写的FxIce(XP下可用,现已开源)。进程要删除一个文件,必须用到DeleteFile,包括Explorer在内,DeleteFile前要先SetFileAttributes,以便移除文件的只读(ReadOnly)属性,因为"只读"文件是无法删除的。病毒要防止自己被删除,就要在内核中的Hook NtDeleteFile和NtSetInformationFile,防止自己被访问就要Hook NtCreateFile、NtOpenFile。和进程一样,文件也有文件句柄hFile,要读写一个文件,首先要OpenFile或CreateFile这个文件,得到一个句柄(Handle),然后才能对其WrieFile或ReadFile,句柄用完要关闭(CloseHandle)它,以便释放资源。最后是保护窗口,首先是隐藏,这里是指改变它的Style,让自己不再拥有Visible(显示)属性,其次是在内核中隐藏自己的信息或者挂上内核钩子,让ring3(用户模式)下的进程无法获取到自己的信息,比如在ShadowSSDT中Hook NtUserQueryWindow、NtUserFindWindowEx等。
测试一个程序是否是病毒,最安全的环境是虚拟机,把可疑程序扔到虚拟系统中就可以放心大胆地运行它了。隐藏是相对的,存在是绝对的,完全隐藏对象是不可能的,因为至少操作系统能够检测到它的存在,那么其它程序就也能。所以没有不透风的墙,病毒的隐藏是暂时的。病毒一般是网上下载的程序,或者来自可移动盘里的程序,而且都是因为你无意的点击或者一时疏忽,才让病毒有了可乘之机,侵入了系统。少数病毒可能会自动运行,比如移动盘自动播放触发了病毒,或者某些程序设置了自动运行功能等,比如自解压+自运行,对于这种情况,可以选择使用HIPS软件,不必驻留内存,测试完了退出即可,程序运行过程发现存在异常行为直接中止,另外还要不定期查看系统启动项的状态及驱动状态,避免自动程序过多以及病毒落脚。那病毒或木马会不会远程侵入电脑?这个是不会的,远程控制实际上仍然是本机控制,木马能够控制你的电脑,说明它已经进入了你的系统,而且已经成功地进入内存。不过,如果没有把握对抗病毒,还是装个防护软件比较好。