经常分析SREng日志的人都会有体会,远程帮人清除病毒真是一件体力活。特别当对方是个电脑“白痴”的时候,那真是各种的无法沟通。。。你教她删文件、改注册表、停服务?算了吧,还是让windows的脚本来帮我们搞定一切吧!
折腾了2天,终于release了我的VirusCleanerUtils.js~~
由于脚本的一些局限性,我的这个病毒清除脚本还依赖于2个小工具分别是ps和spt,关于这2个文件的更多信息可以分别看下面的链接:
X-PS: http://www.unnoo.com/research/tools/xps/
spt: http://www.syssafety.com/leaktests.141.html
目前版本支持的功能包括:
- 停止服务
- 注册表键值的删除/修改/创建
- 进程终止(正常终止/借助spt的16种进程终止技术)
- 运行中进程的dll强行卸载(借助X-PS)
- 文件删除(支持绝对路径/相对路径/带环境变量)
- 文本文件修改
- 文件拷贝
- 目录删除(不支持“非法”[如autorun..和通过NativeAPI创建的dos保留关键字目录,如con]目录删除)
在源代码中加入了测试代码,方便即改即测~
使用方法:
将VirusCleanerUtils.js、ps.exe、spt.exe三个文件放在同一个目录下,通过以下命令行启动
cscript //nologo VirusCleanerUtils.js |
当然了,嫌这样麻烦,自己把上面的启动代码放到一个bat文件里,双击启动,更加傻瓜点~
源代码:VirusCleanerUtils.js
****************************************************************************** * Author: TrojanJason@NEWSMTH * Created on: 2007-12-28 * Last Modified: 2007-12-29 * Version: 0.1 */ //-----------------全局变量开始----------------------- var objWSH = new ActiveXObject("wscript.shell"); var fso = new ActiveXObject("scripting.filesystemobject"); var hasExceptions = 0; //OpenTextFile 中读写标志位 var ForRead = 1; var ForWrite = 2; var ForAppend = 8; //custom input dialog vars var vbOKCancel = 1; // 确定/取消 var vbOKOnly = 0; //确定 var vbInformation = 64; var vbCancel = 2; //终止 重试 忽略,对于Popup的返回值来说表示用户点击'取消' //special folders spec var WindowsFolder = 0; var SystemFolder = 1; var TemporaryFolder = 2; //spt kill level constant /* 1 - standard process termination; 2 - terminate process by terminating all its threads; 3 - terminate process using remote thread; 4 - terminate process by instruction pointer (IP) modification; 5 - crash process by resetting memory attributes; 6 - crash process by rewriting critical process data; 7 - terminate process as part of a job; 8 - terminate process using debuger; 9 - terminate process as a task; 10 - terminate process by sending WM_CLOSE; 11 - terminate process by sending WM_SYSCOMMAND; 12 - terminate process using windows station message; 13 - terminate process using DLL injection 1; 14 - terminate process using DLL injection 2; 15 - simulation of normal process exit; 16 - terminate process by "bruteforce" message posting; */ //-----------------全局变量结束----------------------- //-----------------全局对象定义开始----------------------- function VCHelper() { } VCHelper.prototype.stopSystemService = stopSystemService; VCHelper.prototype.deleteRegKey = deleteRegKey; VCHelper.prototype.createRegKey = createRegKey; VCHelper.prototype.readRegKey = readRegKey; VCHelper.prototype.killProcessByName = killProcessByName; VCHelper.prototype.killProcessByPid = killProcessByPid; VCHelper.prototype.findProcessByPid = findProcessByPid; VCHelper.prototype.killProcessByPidSpt = killProcessByPidSpt; VCHelper.prototype.unloadDll = unloadDll; VCHelper.prototype.deleteFile = deleteFile; VCHelper.prototype.deleteFileByEnvVar = deleteFileByEnvVar; VCHelper.prototype.writeTextToFile = writeTextToFile; VCHelper.prototype.copyFile = copyFile; VCHelper.prototype.deleteFolder = deleteFolder; function UtilsHelper() { } UtilsHelper.prototype.hex = hex; UtilsHelper.prototype.info = info; function TestVCHelper() { } TestVCHelper.prototype.buildTestCase = function(){ try{ fso.OpenTextFile("test.txt", ForWrite, true).Close(); fso.OpenTextFile("d:\\temp\\sss.txt", ForWrite, true).Close(); fso.CreateFolder("d:\\中文 目录"); fso.OpenTextFile("d:\\中文 目录\\test.txt", ForWrite, true).Close(); fso.OpenTextFile(fso.GetSpecialFolder(TemporaryFolder)+"temp.ani", ForWrite, true).Close(); }catch(Err){ } } TestVCHelper.prototype.runTestCase = function(){ var TestCase = new VCHelper(); //display program info info(); //test copy file TestCase.copyFile("test.txt", "d:\\temp\\test2222.txt"); TestCase.copyFile("test.txt","d:\\temp\\test22222.txt"); TestCase.copyFile("test.txt","d:\\nonexist\\test22222.txt"); TestCase.deleteFile("d:\\temp\\sss.txt"); TestCase.deleteFile("d:\\中文 目录\\test.txt"); TestCase.deleteFolder("d:\\中文 目录"); TestCase.deleteFileByEnvVar("%temp%\\temp.ani"); TestCase.writeTextToFile("111\n2222\n333", "test.txt", ForAppend, false); TestCase.writeTextToFile("111\n2222\n333", "test.txt", ForWrite, true); TestCase.writeTextToFile("444\n2222\n333", "test.txt", ForAppend, true); //test process termination TestCase.unloadDll("SciLexer.DLL"); TestCase.killProcessByName("calc.exe"); TestCase.killProcessByPid(3968); TestCase.killProcessByPidSpt(3532,2); //test stopping service TestCase.stopSystemService("MSIServer"); //test registry operations TestCase.createRegKey("HKCU\\Software\\ACME\\FortuneTeller\\",1,"REG_BINARY"); TestCase.createRegKey("HKCU\\Software\\ACME\\FortuneTeller\\MindReader", "Goocher!", "REG_SZ"); WScript.StdErr.WriteLine(readRegKey("HKCU\\Software\\ACME\\FortuneTeller\\MindReader")); TestCase.deleteRegKey("HKCU\\Software\\ACME\\FortuneTeller\\MindReader"); TestCase.deleteRegKey("HKCU\\Software\\ACME\\FortuneTeller\\"); TestCase.deleteRegKey("HKCU\\Software\\ACME\\"); } //-----------------全局对象定义结束----------------------- /************************************** ************ 系统服务操作 ************** **************************************/ //停止服务 function stopSystemService(srvcName) { try{ var strcomputer, objwmi, servicelist, service, sname; strcomputer ="."; objwmi = GetObject("winmgmts:\\\\" + strcomputer + "\\root\\cimv2"); //确保只停止当前状态为'Running'或'Unknown'的服务 servicelist = objwmi.ExecQuery("Select * from Win32_Service where (State='Running' or State='Unknown') and Name='" + srvcName + "'"); var e = new Enumerator(servicelist); for (;!e.atEnd();e.moveNext()) { var service = e.item(); if(service.stopservice()){ WScript.StdErr.WriteLine("!!!!!停止服务:'" + srvcName + "'失败"); }else{ WScript.StdOut.WriteLine("*****停止服务:'" + srvcName + "'成功"); } } }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } /************************************** ************ 注册表操作 *************** **************************************/ //删除注册表键值 function deleteRegKey(regKeyName) { try{ objWSH.RegDelete(regKeyName); }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } //创建/修改注册表键值 function createRegKey(regKeyName, regKeyValue, regType) { try{ objWSH.RegWrite(regKeyName, regKeyValue, regType); }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } //读取注册表键值 function readRegKey(regKeyName) { try{ return objWSH.RegRead(regKeyName); }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } /************************************** ************ 进程操作 *************** **************************************/ //进程终结 by name function killProcessByName(procName) { try{ var w = GetObject("winmgmts:"); var processlist = w.execquery("select * from win32_process where name='" + procName + "'"); var e = new Enumerator(processlist); for(;!e.atEnd();e.moveNext()){ var process = e.item(); if(process.terminate()){ objWSH.Popup("终止进程:'" + procName + "'失败"); } } }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } //进程终结 by pid function killProcessByPid(pid) { try{ var w = GetObject("winmgmts:"); var processlist = w.execquery("select * from win32_process where ProcessId='" + pid + "'"); var e = new Enumerator(processlist); for(;!e.atEnd();e.moveNext()){ var process = e.item(); process.terminate; //结束进程 } }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } function findProcessByPid(pid) { try{ var w = GetObject("winmgmts:"); var processlist = w.execquery("select * from win32_process where ProcessId='" + pid + "'"); var e = new Enumerator(processlist); for(;!e.atEnd();e.moveNext()){ var process = e.item(); return process; } }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } //进程终结 by pid 使用spt.exe function killProcessByPidSpt() { var pid, level, params; if(arguments == null || arguments.length < 2){ return; }else{ pid = arguments[]; level = arguments[1]; params = arguments[2] == null ? null : arguments[2]; } try{ if(findProcessByPid(pid) == null){//不存在pid所代表的进程 WScript.StdErr.WriteLine("!!!!!不存在进程(pid=" + pid + ", level=" + level + ")"); return; } var oExec; if(params == null || params.length < 1){ oExec = objWSH.Exec("spt " + pid + " " + level); }else{ oExec = objWSH.Exec("spt " + pid + " " + level + " " + params); } var isSuccessful = false; while(!oExec.StdOut.AtEndOfStream) { var output = oExec.StdOut.ReadLine(); if(output.indexOf("succeed") > -1){//程序执行成功 isSuccessful = true; break; } } if(!isSuccessful){ WScript.StdErr.WriteLine("!!!!!强制终止进程(pid=" + pid + ", level=" + level + ")失败"); }else{ WScript.StdOut.WriteLine("*****强制终止进程(pid=" + pid + ", level=" + level + ")成功"); } }catch(err){ objWSH.Popup("请将第三方程序spt.exe与本专杀放在同一目录下",64,"注意"); hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } //dll文件卸载 function unloadDll(dllName) { try{ var oExec = objWSH.Exec("ps /e * " + dllName); var output = ""; var isSuccessful = false; while(!oExec.StdOut.AtEndOfStream) { var output = oExec.StdOut.ReadLine(); if(output.indexOf("succeed") > -1){//程序执行成功 isSuccessful = true; break; } } if(!isSuccessful){ WScript.StdOut.WriteLine("!!!!!强制卸载dll文件:" + dllName + "失败,请确认dll文件名是否正确"); }else{ WScript.StdOut.WriteLine("*****强制卸载dll文件:" + dllName + "成功"); } }catch(err){ objWSH.Popup("请将第三方程序ps.exe与本专杀放在同一目录下",64,"注意"); hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } /************************************** ************ 文件操作 *************** **************************************/ //删除文件(根据全路径+文件名,注意路径中的斜杠是\\) function deleteFile(fileName) { try{ if(fso.FileExists(fileName)){ var v = fso.GetFile(fileName); v.attributes = 0; v.Delete(true);//force delete if read-only flag is set if(fso.FileExists(fileName)){//check if file has been deleted WScript.StdErr.WriteLine("!!!!!删除文件'" + fileName + "'失败"); }else{ WScript.StdOut.WriteLine("*****删除文件'" + fileName + "'成功"); } } }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } //删除文件(根据环境变量名+文件名,注意路径中的斜杠是\\) function deleteFileByEnvVar(fileSpec){ try{ var d = objWSH.ExpandEnvironmentStrings(fileSpec); if(fso.FileExists(d)){ var v = fso.GetFile(d); v.attributes = 0; v.Delete(true);//force delete if read-only flag is set if(fso.FileExists(d)){//check if file has been deleted WScript.StdErr.WriteLine("!!!!!删除文件'" + fileSpec + "'失败"); }else{ WScript.StdOut.WriteLine("*****删除文件'" + fileSpec + "'成功"); } } }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } //强制删除文件(借助第三方工具) //写文本文件 function writeTextToFile(txt, fileName, iomode, ForceCreate) { try{ var re = fso.OpenTextFile(fileName, iomode, ForceCreate); re.Write(txt); re.Close(); }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } //复制文件 function copyFile(src, dst) { try{ if(fso.FileExists(src)){ var tempDst = dst.substring(0,dst.lastIndexOf("\\") + 1); if(!fso.FolderExists(tempDst)){//检查是否存在目标文件所在的目录 if(objWSH.Popup("不存在目标目录" + tempDst + "自动创建?",64,"注意",vbOKCancel) == vbCancel){//放弃复制 return; } fso.CreateFolder(tempDst); } if(fso.FileExists(dst)){//检查目标文件是否已经存在 if(objWSH.Popup("目标文件" + dst + "已存在,是否覆盖?",64,"注意",vbOKCancel) == vbCancel){//放弃覆盖 return; } } fso.GetFile(src).Copy(dst); }else{ objWSH.Popup("要拷贝的源文件" + src + "不存在",64,"注意",vbOKOnly); } }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } //删除目录 function deleteFolder(folderName) { try{ if(fso.FolderExists(folderName)){ var folder = fso.GetFolder(folderName); folder.attributes = 0; folder.Delete(true); if(fso.FolderExists(folderName)){ WScript.StdErr.WriteLine("!!!!!删除目录'" + folderName + "'失败"); }else{ WScript.StdOut.WriteLine("*****删除目录'" + folderName + "'成功"); } } }catch(err){ hasExceptions ++; WScript.StdErr.WriteLine("Error " + hasExceptions + " occurred\nCode: " + hex(err.number) + "\nDescriptions: " + err.description); } } /************************************** ************ UtilsHelper类 *************** **************************************/ function hex(nmb) { if (nmb > 0) return nmb.toString(16); else return (nmb + 0x100000000).toString(16); } function info() { var _name = "Virus Clean Helper"; var _author = "All rights by TrojanJason@NEWSMTH"; var _version = "Version 0.1"; objWSH.Popup(_author + "\n" + _version, 64, _name); } //run TestCase var TestCase = new TestVCHelper(); TestCase.buildTestCase(); TestCase.runTestCase();