☰
VBS整人脚本原理与安全边界:从WSH宿主到熔断清理
2026/11/3 22:39:29 网站建设 项目流程

简介:这份VBS整人代码大全以Word文档形式收录多段恶作剧脚本示例,面向刚接触VBS、希望了解脚本基础语法与常见整人套路的入门读者。内容围绕MsgBox弹窗、CreateObject(“Wscript.Shell”)调用系统命令、Do...Loop无限循环、InputBox条件判断、SendKeys键盘模拟以及WMPlayer.ocx媒体播放等展开,可供读者认识脚本如何触发关机、重启、循环弹窗和页面刷新等行为,并据此理解其潜在风险。压缩包内共1个docx文件,大小约192KB,篇幅集中、便于查阅,已有11805人学习下载。读者可从中获得可直接对照的代码片段与运行效果说明,适合作为VBS语法练习、课堂案例或安全提醒素材;需注意部分代码可能造成关机、蓝屏或重复操作,建议仅在虚拟机或受控环境中测试,不要用于他人电脑。

1. VBS 整人代码不是玄学:一条 MsgBox 就能测出你对脚本宿主的理解

很多人第一次接触 VBS 整人代码,场景都差不多:同事发来一个几 KB 的 .vbs 文件,双击之后桌面开始无限弹窗,鼠标点得手酸也关不掉,最后只能长按电源键。这类脚本之所以"有效",不是因为写了什么高深算法,而是它精准踩中了 Windows 脚本宿主的三件事——文件关联、COM 对象调用、单线程消息循环。把这三件事拆开看,所谓整人代码就是 MsgBox、InputBox、WScript.Shell、SendKeys 这几个原语的排列组合,理解成本并不高。

这份资源合集收录的正是这类脚本:弹窗循环、假重启提示、倒计时关机、模拟蓝屏、光驱弹出、无限刷新等,从几行到几百行都有,后半段还混进了一个会自复制到各盘符并写 autorun.inf 的蠕虫式脚本。它适合两类人:一类是想搞懂 WSH 脚本能力边界的安全入门者,另一类是需要给团队做"陌生脚本不要乱点"演示的运维。本文按"能跑起来 → 能改参数 → 知道哪里会翻车 → 怎么安全地关进笼子"这条线走。

2. 从记事本到 wscript.exe:VBS 整人代码的落地执行链路

脚本能不能跑,跟你写得多花哨关系不大,跟它落在哪个宿主进程里关系极大。同一段代码,用记事本存成 .txt 双击是打开文本,存成 .vbs 双击是启动 wscript.exe,右键选"用命令脚本宿主运行"又是 cscript.exe。这一段把链路捋清楚,后面所有调试都省事。

2.1 后缀之争:为什么 .vbs 双击才跑得起来

Windows 认扩展名,不认内容。资源原文反复强调"一定要存为 VBS 格式",说的就是注册表里的文件关联:.vbs映射到VBSFile这个 ProgID,再往下指到shell\open\command,默认值是wscript.exe "%1" %*。双击的本质是资源管理器把文件路径当参数塞给 wscript.exe。存成 .txt 时这条链断在第一步,双击只会拉起记事本,代码一行都不会执行。

验证方法很简单,开一个命令行敲:

assoc .vbs ftype VBSFile

第一条输出.vbs=VBSFile,第二条输出VBSFile="%SystemRoot%\System32\WScript.exe" "%1" %*。如果第二条被改成了 notepad.exe,那就是某些"安全加固"工具干的事,此时双击 .vbs 只会打开编辑器,很多人以为脚本坏了,其实是关联被人动过。要临时绕过关联,直接显式调用宿主:

wscript.exe D:\demo\hello.vbs cscript.exe //nologo D:\demo\hello.vbs

参数说明://nologo是 cscript 的开关,用来关掉启动横幅;路径带空格时必须整体加引号,否则 wscript 会把空格后的部分当成第二个参数吞掉,脚本里WScript.Arguments读出来就是残缺的。这是新手最常翻的车之一。

还有一个隐藏坑:记事本默认"另存为"的编码在旧版本是 ANSI,新版本是 UTF-8。VBS 解释器对无 BOM 的 UTF-8 中文支持不稳,容易出现乱码或者直接语法错误。稳妥做法是保存时把编码选成 ANSI,或者代码里所有中文都用ChrW()拼,别指望编辑器。

2.2 最小可运行骨架:MsgBox 四个参数位怎么填

合集里绝大多数脚本的第一行都是 MsgBox。它的完整签名是MsgBox(prompt, buttons, title, helpfile, context),日常只用前三个:

' demo_msgbox.vbs —— 最小骨架,演示按钮常量与返回值 Dim ret ret = MsgBox("继续执行吗?", vbYesNo + vbQuestion, "演示") If ret = vbYes Then MsgBox "你点了【是】", vbInformation, "结果" ElseIf ret = vbNo Then MsgBox "你点了【否】", vbInformation, "结果" End If

逻辑说明:第一参数是正文,支持用vbCrLf或Chr(10)换行;第二参数是"按钮类型 + 图标类型"相加,vbYesNo的值是 4,vbQuestion是 32,实际传给 API 的是 36;第三参数是标题栏文字,不填就显示宿主默认标题。返回值决定分支走向,vbYes是 6、vbNo是 7、vbCancel是 2。

参数上最容易出错的是把vbYesNo和vbOKCancel混着判断。资源里那段"假重启"脚本写的是vbOKCancel + vbInformation,然后判断= vbCancel,逻辑没错;但如果有人改成vbYesNo却还在判断vbCancel,条件永远不成立,脚本会静默走完,看起来像"没反应"。我的习惯是先把常量对应的数值打在注释里,改的时候对着看,比背常量靠谱。

2.3 wscript 与 cscript 两种宿主的调试差异

同一份脚本,wscript 是窗口模式,所有WScript.Echo都弹成对话框;cscript 是控制台模式,WScript.Echo打到标准输出。调试阶段一律用 cscript,因为弹窗会阻塞执行流,几十个 Echo 就是几十次点击,血泪经验。

cscript //nologo //X D:\demo\demo_msgbox.vbs

//X参数会在调试器里启动脚本,前提是机器上装了对应调试工具;没有的话去掉即可。更实用的做法是在关键节点写日志:

' 把执行痕迹落到文本,避免全靠弹窗观察 Dim fso, logFile Set fso = CreateObject("Scripting.FileSystemObject") Set logFile = fso.OpenTextFile("D:\demo\run.log", 8, True) ' 8 = 追加写 logFile.WriteLine Now & " 进入主流程" logFile.Close

OpenTextFile的第二参数 8 表示 ForAppending,文件不存在时第三参数 True 会自动创建。这个写法比WScript.Echo更适合排查"脚本到底执行到第几行",因为日志不怕阻塞。注意路径别写相对路径,wscript 的当前目录有时是C:\Windows\System32,相对路径会落到意想不到的地方,这也是很多人找不到日志文件的原因。

3. 三大原语拆解:MsgBox 分支、InputBox 校验、shutdown 倒计时

合集里真正让人"中招"的脚本,基本都建立在三个原语上:用 MsgBox 制造心理压力,用 InputBox 卡住用户双手,用 shutdown 制造真实后果。这一章把这三个原语的参数、返回值和可逆性讲透,你才知道哪些能改、哪些改了就出事。

3.1 MsgBox 返回值判断:vbYes / vbCancel 的常量陷阱

资源里有一段"你是猪头吗"的脚本,vbYesNo弹窗,选"是"继续嘲讽,选"否"走惩罚分支——惩罚分支里调了ntsd -c q -pn winlogon.exe。这条命令的作用是让调试器附加到 winlogon 进程并强制退出,在 NT/2000/XP 上会直接触发蓝屏。也就是说,无论用户点哪个按钮,脚本作者都设计了"后果",这是整人类脚本的典型结构:用对话框拿走选择权,让用户误以为自己有得选。

从技术角度看,这里要盯住两点。第一,按钮常量与返回值必须配对,vbYesNo只可能返回 6 或 7,永远不会返回 2。第二,vbCritical、vbExclamation这类图标只是视觉修饰,不改变返回值,但很多人以为加了红色叉号就是"严重操作",其实程序该干嘛还干嘛。

' 演示:用返回值做白名单,只放行明确点击 Dim ans ans = MsgBox("此操作会关闭记事本窗口,是否继续?", vbYesNo + vbExclamation, "确认") Select Case ans Case vbYes ' 这里才是真正的动作分支 WScript.Echo "用户确认" Case vbNo WScript.Echo "用户取消" Case Else WScript.Echo "窗口被直接关闭,返回 -1" End Select

注意Case Else:用户点右上角叉号时返回 -1,如果不处理,脚本可能落入默认分支继续执行。资源里那些"点了取消还是关机"的脚本,十有八九就是漏了这个分支。

3.2 InputBox 输入校验循环:怎样留一条退出路径

InputBox 是整蛊脚本的第二件武器。它的签名是InputBox(prompt, title, default, xpos, ypos),返回值是字符串;用户点取消或叉号时返回空字符串,这一点和 MsgBox 不同,很多人会误判成vbCancel。

原合集里那段"输入 abc 否则关机"的脚本,循环体是这样的:读输入 → 判断是否等于目标串 → 不等就继续弹。问题在于它没有处理"用户点取消"的情况,空字符串永远不等于 "abc",循环就永远出不来,用户只能强杀进程。正确的骨架应该带三条出口:

' 带退出条件的输入循环:正确输入 / 主动取消 / 超时 Dim sh, ans, deadline Set sh = CreateObject("WScript.Shell") deadline = Timer + 30 ' 30 秒后自动放弃 Do ans = InputBox("请输入 abc 以继续", "校验", "", 4000, 3000) If ans = "" Then MsgBox "已取消,流程结束", vbInformation, "提示" Exit Do End If If LCase(Trim(ans)) = "abc" Then MsgBox "校验通过", vbInformation, "提示" Exit Do End If If Timer > deadline Then MsgBox "超时退出", vbExclamation, "提示" Exit Do End If Loop

逻辑说明:Timer返回从午夜零点起的秒数,用它做截止时间是最省事的熔断方式;LCase(Trim(ans))做大小写和空格归一,避免用户输入 "ABC " 被判错。参数说明:InputBox 的 xpos / ypos 单位是缇,4000 大概是屏幕偏左的位置,填 0 让系统居中。第四、五参数省略时窗口会居中,观感更好。

这里有个必须提醒的边界:把 InputBox 循环和 shutdown 绑在一起,本质是拿别人的工作现场当赌注,一旦用户刚好在编译、在保存、在渲染,损失不可逆。这类脚本我只在虚拟机快照里验证逻辑,绝不在真实环境跑。

3.3 shutdown 参数表与可撤销设计

shutdown 是整蛊脚本里"后果"的来源,也是最该被讲清楚的一条命令。常用参数如下:

参数含义常见误用
-s关机与-r同时写,实际只认最后一个
-r重启未加-t时默认立即执行
-t 秒延迟时间,默认 30写成负数或超大值会报错
-a中止倒计时必须在下一次关机动作为止前执行
-c "注释"关机对话框里的提示文字内部含引号需转义成""
-f强制关闭无响应程序会丢未保存数据,慎用

可撤销设计的关键是:倒计时一旦启动,同会话里任何进程都能用shutdown -a撤销。所以整蛊脚本想"锁死"用户,往往会循环重发-s,或者干脆不给你敲命令的机会。反过来,作为被整的一方,记住Win+R输入shutdown -a这一招就够了,前提是还能操作桌面。

' 可撤销的倒计时演示:启动后立刻给撤销入口 Dim sh, seconds seconds = 120 Set sh = CreateObject("WScript.Shell") sh.Run "shutdown -s -t " & seconds & " -c ""演示:120 秒后关机,输入 shutdown -a 可撤销""", 0, False MsgBox "倒计时已启动,点确定后自动撤销", vbInformation, "演示" sh.Run "shutdown -a", 0, False

参数说明:Run的第二个参数 0 表示隐藏窗口,第三个参数 False 表示不等待返回。如果第三个参数写 True,脚本会阻塞到 shutdown 命令自己退出,倒计时可能已经走完,撤销就来不及了。这个细节在合集里几乎没人提,但它是"能不能救回来"的分水岭。

4. 循环类整蛊的失控点:Do…Loop、SendKeys、COM 对象

前三类脚本靠对话框,杀伤力有限;真正让人抓狂的是循环类和 COM 对象类——它们不弹窗,直接吃掉 CPU、刷屏、弹光驱,用户连关的入口都找不到。这一章讲清楚它们为什么会失控,以及怎么写一个带熔断的版本。

4.1 无限循环为什么会把桌面顶死

Do ... Loop本身不复杂,问题出在循环体里放的是 MsgBox。wscript.exe 是单线程的 STA 宿主,弹出一个模态对话框后,线程阻塞在对话框的消息泵上,只有用户点击才返回。理论上点一次就往前走一次,但脚本立刻又弹下一个,用户点得再快也追不上,视觉上就是"关不完"。

更糟的是资源里那段createobject("wscript.shell").run chr(34) & wscript.scriptname & chr(34)的写法:脚本不断启动自身的新副本,进程数指数增长。这时候任务管理器打开都卡,因为 CPU 被几十个 wscript 实例瓜分。这类脚本没有"优雅退出"路径,唯一解是断尾——用命令行强杀:

taskkill /f /im wscript.exe taskkill /f /im cscript.exe

如果连命令行都拉不起来,就进安全模式或者用另一台机器远程执行。我一般会在测试机上先建快照,跑完直接回滚,比事后杀进程干净得多。

写带熔断的循环其实很简单,把Timer当截止时间就行:

' 带超时熔断的循环:10 秒后无论是否完成都退出 Dim sh, i, deadline, interval Set sh = CreateObject("WScript.Shell") i = 0 interval = 300 deadline = Timer + 10 Do While Timer < deadline i = i + 1 WScript.Sleep interval Loop MsgBox "循环结束,执行 " & i & " 次", vbInformation, "统计"

参数说明:WScript.Sleep单位是毫秒,300 毫秒既能让循环有存在感,又不至于把 CPU 打满;Timer在跨午夜时会回绕成小数,长循环要改用DateDiff("s", startTime, Now),这是隐蔽坑,白天测没事,凌晨跑就变成死循环。

4.2 SendKeys 的时序依赖与前台窗口

WScript.Shell.SendKeys的原型是往当前前台窗口注入按键消息,它不知道你想发给谁。资源里那句ws.SendKeys "{F5}"放进死循环,效果取决于脚本启动那一刻的焦点在哪——在浏览器里是刷新,在资源管理器里是刷新,在编辑器里可能什么都没发生。这种"看运气"的行为,是整蛊脚本最不稳定的部分。

可控的写法是先激活目标窗口,再发按键,并且给足间隔:

' 定向发送:先激活记事本,再输入文本 Dim sh Set sh = CreateObject("WScript.Shell") If sh.AppActivate("记事本") Then WScript.Sleep 500 sh.SendKeys "hello from vbs" Else MsgBox "目标窗口没找到", vbExclamation, "提示" End If

逻辑说明:AppActivate接受窗口标题或进程 ID,返回 True 表示激活成功;返回后必须留一点时间让窗口完成焦点切换,否则按键会打到上一个窗口。参数说明:SendKeys 的特殊字符要用花括号包起来,比如{ENTER}、{F5}、{TAB},加号、百分号、波浪号这些本身有修饰含义,需要写成{+}、{%}、{~}。

风险边界也得说清楚:这个能力一旦被滥用,可以对准任何前台程序输入任意内容,包括密码框、命令行窗口。所以我只把它当"自动化测试的土办法",用完就删,绝不留在共享目录里。

4.3 CD-ROM 与 WMPlayer 组件的兼容性翻车

合集里有一段CreateObject("WMPlayer.ocx")然后cdromcollection.item(0).eject的脚本,思路是用 Windows Media Player 的 COM 接口弹光驱。这段代码在十几年前确实好用,现在跑起来大概率报错:一是新系统默认不装 WMP,ProgID 注册不上;二是很多机器根本没有光驱,cdrom.count是 0,item(0)直接抛异常。

' 先探测再操作,别上来就 item(0) On Error Resume Next Dim wmp, cds Set wmp = CreateObject("WMPlayer.OCX") If Err.Number <> 0 Then WScript.Echo "WMP 组件不可用,错误码:" & Err.Number WScript.Quit End If Set cds = wmp.cdromCollection If cds.Count = 0 Then WScript.Echo "本机没有可用的光驱设备" Else cds.Item(0).Eject End If Err.Clear

On Error Resume Next是 VBS 里唯一的错误处理手段,它不处理错误,只是让执行流跳过出错行。所以必须配Err.Number判断,否则错误被吞掉,脚本表现为"什么都没发生",排查起来像黑匣子。Err.Clear用来复位错误状态,避免影响后续判断。

同样的道理适用于Scripting.FileSystemObject、WScript.Network这些常见对象——不是每台机器、每个权限上下文都能创建成功。写法上养成"创建 → 立即判错 → 再使用"的三段式,能省掉大量玄学问题。

5. 避坑与排查:五类翻车现场的现象、原因与解法

前面讲的是怎么让脚本跑起来,这一章讲它跑歪了怎么收拾。以下五条都是我在虚拟机里反复撞过的,按"现象 → 原因 → 解决"记录,顺序按发生频率排。

5.1 双击没反应,图标还是记事本

现象:.vbs文件双击后弹记事本,代码原样显示,或者干脆毫无反应。

原因:文件关联被改。常见于装过某些"脚本防护"工具、做过系统加固、或者手动用"打开方式"把 .vbs 绑到了编辑器上。另一可能是文件其实是.vbs.txt,资源管理器隐藏了已知扩展名,看上去像 .vbs。

解决:先在文件夹选项里勾掉"隐藏已知文件类型的扩展名"确认真实后缀;再执行assoc .vbs=VBSFile和ftype VBSFile="%SystemRoot%\System32\WScript.exe" "%1" %*恢复关联;临时验证可以直接wscript.exe 完整路径显式调用。改完注销一次让资源管理器刷新图标缓存。

5.2 关机倒计时误伤自己

现象:本来只想给同事演示,结果自己的机器跟着倒计时关机,改代码都来不及。

原因:shutdown是系统级动作,没有"只对某个窗口生效"这种说法;脚本里-t给得太短(合集里出现过-t 5、-t 6),人反应不过来。

解决:第一反应永远是Win+R敲shutdown -a;来不及就长按电源键但注意别在写盘时断电。更根本的做法是把-t调到 60 以上,并在脚本里先给撤销入口再执行关机命令。我的习惯是调试期一律把 shutdown 替换成WScript.Echo "模拟关机",逻辑跑通再换真命令,最后一步才在快照里验证。

5.3 弹窗刷屏后任务管理器都点不到

现象:桌面上叠了上百个对话框,点掉一个立刻补一个,Ctrl+Shift+Esc按了也没用,鼠标移动都卡。

原因:循环体里MsgBox无延时、无退出条件,且脚本可能启动了自身多个副本。wscript 单线程,每个副本都占一个消息泵,进程数一多,系统调度就跟不上。

解决:优先用命令行taskkill /f /im wscript.exe,前提是能调出运行框;调不出就进安全模式(开机连按 F8 或从系统设置里选"高级启动"),安全模式下脚本不会自动运行;再不行用另一台机器远程taskkill /s。事后一定要查启动项,确认没有残留的自启动副本。

5.4 杀软静默删除与"文件消失"

现象:脚本刚保存就被删,或者运行到一半进程消失,没有任何报错。

原因:行为特征命中查杀规则。合集后半段那个自复制脚本会遍历盘符、写autorun.inf、修改文件属性、复制自身到各分区,这是典型的蠕虫行为链,任何一款主流安全软件都会拦。即便是无害的 MsgBox 循环,如果文件来源是压缩包、文件名带诱导性,也可能被静态特征命中。

解决:认清一件事——被删不是误报,是这类行为本身就在黑名单里。做安全演示时,用无害的等价代码(Echo 代替 shutdown、日志代替文件复制),并在隔离环境里关闭实时防护后限定目录测试,测完立刻恢复防护。不要为了"能跑"去加白名单,那等于给自己留后门。

5.5 自复制脚本残留:怎么确认清干净了

现象:删掉了桌面上的 .vbs,过一会儿又出现;或者各盘根目录多出autorun.inf、隐藏属性的 .vbs 文件。

原因:脚本运行时会把自己复制到其他位置,并通过autorun.inf或启动项实现再次触发。合集里那段代码还改文件夹属性、写回收站目录的desktop.ini,清理不彻底就会复活。

解决:按"进程 → 启动项 → 文件 → 属性"四步走。先杀掉所有 wscript / cscript 进程;再检查启动文件夹、注册表 Run 键、计划任务;然后逐个盘符根目录找autorun.inf、隐藏的 .vbs 和异常文件夹;最后用attrib -h -s -r去掉隐藏和系统属性再删。下面这几条命令可以当检查清单用:

tasklist | findstr /i "wscript cscript" reg query HKCU\Software\Microsoft\Windows\CurrentVersion\Run reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Run dir /a /s C:\*.vbs attrib -h -s -r C:\autorun.inf

dir /a会列出隐藏和系统文件,/s递归子目录;attrib三个开关分别对应隐藏、系统、只读,去掉之后普通删除才生效。检查完记得把结果记下来,同一台机器反复中招,往往就是某个角落的文件没清掉。

6. 把整蛊脚本关进笼子:快照、熔断与清理清单

玩这类脚本的正确姿势,是把它当"有爆炸半径的实验",而不是双击就完事的小玩意。我现在的固定流程是四步:开虚拟机 → 打快照 → 断网运行 → 回滚。快照这步千万别省,它是唯一的后悔药;断网是为了防止自复制类脚本往外扩散;回滚比手工清理可靠得多,尤其是涉及文件属性和启动项的场景。

熔断机制建议写进每一份测试脚本的头部,模板如下:

' 统一熔断头:超时自退 + 日志落盘 + 单实例锁 Dim fso, sh, startAt, limitSec Set fso = CreateObject("Scripting.FileSystemObject") Set sh = CreateObject("WScript.Shell") startAt = Now limitSec = 60 If fso.FileExists("D:\demo\lock.tmp") Then WScript.Quit ' 已有实例在跑,直接放弃 End If fso.CreateTextFile("D:\demo\lock.tmp", True).Close Do If DateDiff("s", startAt, Now) > limitSec Then fso.DeleteFile "D:\demo\lock.tmp", True WScript.Quit End If WScript.Sleep 500 Loop

逻辑说明:DateDiff("s", ...)比Timer稳,不受跨午夜影响;单实例锁用临时文件实现,防止脚本自我复制后开出多个副本;退出前删锁文件,避免下次误判。参数说明:limitSec按脚本实际耗时给,演示类 60 秒足够,需要人工交互的给 180 秒。

最后给一份动手前的检查表,照着勾一遍能避开八成麻烦:

检查项通过标准
运行环境虚拟机或独立测试机,已打快照
网络状态已断开,防止自复制外扩
脚本内容已通读,确认无文件遍历与启动项写入
退出路径有超时或明确的 Exit Do
善后知道taskkill、shutdown -a、回滚三个动作

说个自己的教训。早年在办公机上图省事,直接双击了一份来路不明的"弹窗玩笑"脚本,结果它是自复制变种,写进了启动项,第二天开机又弹。那次之后我给自己定了条死规矩:任何 .vbs 先丢进虚拟机、先看代码里有没有FileSystemObject的Copy和RegWrite,再决定要不要跑;跑完必回滚,绝不用"应该删干净了"这种话安慰自己。脚本能力本身没有对错,但爆炸半径是自己选的。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询