[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[转贴] “硬盘杀手”批处理的的几点技术探讨

原文地址:http://www.cn-dos.net/forum/viewthread.php?tid=12892

前言:
  决定转载此文,并非表明本人支持编写破坏性代码,而是觉得这篇技术文章全面探讨
了其中各种技术细节,分析得十分深入、透彻,即使是技术老鸟,重新阅读此文,仍然会
觉得有所收获;而willsort兄严谨细致的作风,从尾注中即可得以管窥。  —— by namejm

关于 HDKP 的几点技术探讨
============================================================================
作者:Will Sort
日期:2005-04-22
版本:1-20050505
关键词:HDKP, %comspec%, 命令解释器, drive check, 磁盘检查, 命令行循环
摘要:对 HDKP 磁盘检查和磁盘遍历的在算法和细节上的相关讨论
----------------------------------------------------------------------------
背景
全名:Hard Drive Killer Pro
版本:通行版本为 4.0(包括 bat 版和 bat 压缩成的 exe 版),最新版本 5.0beta
作者:Munga Bunga(澳大利亚)
日期:4.0 版最晚成于2001年5月
平台:据原作者声称,此程序可以工作于 DOS/Win3.x/9x/NT/2000 等系统中,适用于
  世界上 90% 的电脑,彼时还没有 XP 和 2003
用途:毁掉或者说“清洗”电脑上所有硬盘、软盘和闪盘的所有数据。当然,因其历史
  悠久,当前流行的大部分杀毒软件都可将它杀除。
----------------------------------------------------------------------------
序言
  我最早在《批处理简单教程》中看到这篇转贴的批处理程序,教程作者在精彩程序
示例中将此程序列为压轴之作,当时因为我对一切带有所谓 Killer/Hacking 等字眼的
程序都抱有相当的敌意,所以当时只是草草瞥了两眼,并没有细看。后来,我又在“联
合 DOS论坛”中见到“神仙贝贝”兄发出的帖子中[01]转贴了这个程序,不过基于类似
的原因,我仍然只是翻看了一下有无值得留意的回复,随后顺手关闭了它,以至于后来
Climbing 兄的邀请也没有看到。
  4 月中旬我开始翻看“联合 DOS论坛”中关于批处理的旧帖,数次在 Climbing 兄
被置顶的精华帖索引[02]中看到“仔细学学”的建议,终于又点开了“神仙贝贝”的老
帖,此时早已有 wangsea兄将注释的工作漂亮的完成,我的任务就只是简单的享受他人
的劳动果实了。
  但是,遗憾的是,这篇程序里出现了太多的问题和漏洞。有些问题,比如那个无效
的格式化开关 /autoSample 和 :Sampledrv,显然都并非原作者的笔误,而像有心人或
者有心的程序特意修改的;另外一些问题,比如 dedecated 和 elapse,就不知是澳大
利亚的方言还是作者的无心之失了;剩下的一下问题,则可以肯定主要的责任人就是作
者本人。
  当然,为了讨论的公允和普适,我找到了这个程序的原始链接[03]并试图下载,可
是下载失败,我又尝试了其他几个方法,但找到的版本都与“神仙贝贝”的并无不同。
最后,我决定仍然采用后者作为讨论的基础,所以我讨论的只是代码的得失,而非作者
的得失。
----------------------------------------------------------------------------
正文
  无可否认的是,程序中确实使用了一些高级技巧,这些技巧最主要的体现就是磁盘
检查程序(drivechk.bat),但需要注意的是, drivechk.bat 并非作者本人原创,它
的原作者是 Tom Lavedas[04],这也正是作者“Except for”的原因。但是,可能作者
并没有透彻理解这个程序,只是进行了一些简单的改动,也可能作者引用的是 Lavedas
早期的程序,所以这段代码存在着一些问题。
  下面是程序中动态生成 drivechk.bat 的一段
echo @echo off >drivechk.bat
echo @prompt %%%%comspec%%%% /f /c vol %%%%1: $b find "Vol" > nul >{t}.bat
%comspec% /e:2048 /c {t}.bat >>drivechk.bat
del {t}.bat
echo if errorlevel 1 goto enddc >>drivechk.bat
  此段的目的是将下面的代码写入 drivechk.bat 之中。其过程 wangsea 兄已经分
析过,我不再细述。
%comspec% /f /c vol %1: | find "Vol" > nul
if errorlevel 1 goto enddc
  第一,“echo @echo off >drivechk.bat”一句不是必须的。因为 drivechk.bat
是一个动态生成的被调程序,它在被 call 时,会继承主调程序的 echo off 状态。
  只有用 %comspec% /c 调用时,“echo off”才可能被需要,因为 %comspec% /c
会创建一层新的命令解释环境,在这个新环境中 echo 状态会被复位。也正因此,程序
才能通过 %comspec% /e:2048 /c {t}.bat 获得被修改的命令行提示符,它就是要写入
drivechk.bat 的语句。
  第二,第二行中的“%%%%comspec%%%%”完全可以改为“%comspec%”。“%%%%”的
作用是延迟 %comspec% 的替换,使得 %comspec% 直到执行 drivechk.bat 时才被替换
为命令解释器的路径;但是这样是没有必要的,因为被调的 drivechk.bat 和主调程序
必定是运行在相同的环境下,所以替换的迟或早并没有什么分别。
  而且,我建议直接将 %comspec% 改为 command 。因为在 NT 类的命令行环境中,
%comspec% 通常指向 cmd.exe ,它与 command.com 有很多不同,比如在非英文系统中
的代码页不同,导致 find "Vol" /c 失败。而在早期的 MS-DOS 环境中, %comspec%
也有可能指向 NDOS 等非标准的命令解释器,它们的开关参数以及执行输出都可能导致
%comspec% 一句失败。而直接使用 command 最大的问题,就是它不处于当前路径或者
%Path% 路径中,但那几乎是不可能的。
  第三,“find "Vol" > nul”应该是“find "Vol" $g nul”,否则“> nul”将不
能写入 drivechk.bat ,从而可能在调用 drivechk 时造成 find 的消息“泄露”;而
在程序调用时,作者试图通过“call drivechk.bat %%a >nul”来避免了这个隐患,但
是他可能不清楚这个“>nul”对于 call 批处理是无效的。
  只有通过 %comspec% /c 来调用批处理,其输出才能被重定向或被管道传递。但即
便如此,执行 vol %1:可能有一些输出仍然无法被屏蔽,比如访问了不存在或未准备的
盘所产生的错误消息,因为它所使用的是错误设备输出,而并非标准控制台,所以不通
过管道被传递。解决办法是在 %comspec% /c 的前后加上一对 ctty nul 和 ctty con
语句。但是, ctty 只在 MS-DOS 和 9x 命令行被支持,在 XP 等 NT 类命令行 ctty
被取消了。在此类环境中,只能通过 2> nul 重定向错误消息。
  第四,“if errorlevel 1 goto enddc”忽略了很多问题。在 MS-DOS 或者 9x 命
令行中用 vol 访问存在但未准备好的盘,会有 Vol 信息输出,但程序此时并不会跳转
到结束;另外,就是可能访问到只读性的光盘或闪盘,也会有 Vol 信息输出。
  所以,程序为了补救者两个缺陷,才在后面使用了 dir | find "bytes" 检测准备
的准备情况,用 dir | find "0 bytes" 再检查只读的光盘。但被锁定的闪盘仍然无法
正确判断,可能在程序完成时,闪盘的锁定功能尚不常见吧。
  检测磁盘可读的语句也可以替代以 dir %1:\nul|find "\" ,而检查磁盘可写可以
使用 copy /y _writed_.tag %1: 和 if exist %1:_writed_.tag 来判断[05],当然这
些语句仍然都需要在 %comspec% /f/c 的外壳中运行。但是,仍然有些我们想不到的问
题,比如我在虚拟PC的共享盘中只能创建和修改文件,但却不能删除它。其他诸如网络
盘、内存虚拟盘等等,我没有对它们做更为细致的讨论。在这些细节上,专业程序也许
做得更好也不一定。
  第五,程序中还有一个较简单的技巧,就是在 :Sampledrv 中磁盘的遍历。对于使
用 For 语句进行循环式的遍历,可能是批处理编程的惯例,然而这个惯例在某些情况
下可能并不是最优的。
  事实上,在很早的时期,就有人使用更为灵活的命令行循环来处理很多 For难以解
决的问题。比如在 do 后面有多条语句时,我们必须将这些语句放在批处理中被 call
调用,但是 for的特性决定了它运行时的多次重复调用,而命令行循环的优越性在于它
只需要 call 一次,剩下的只是程序内部的 shift和 goto 。这节省了相当多的性能,
因为 call 远比 shift和 goto 占用更多的性能资源。
  第六,我们讨论 drivechk.bat 动态生成的必要性。这里并不是说 drivechk.bat
的必要性,而是说动态生成的必要性。我们可以猜测,程序之所以要费尽周章地动态生
成这段代码,而不是把它静态地嵌入在主程序中,其主要目的是可以利用它进行磁盘检
查的循环遍历。然而,可能作者并没有注意或者意识到,使用静态代码也可以完成同样
的任务。这意味着整个程序在写入 drivechk.bat 上所绕的所有的弯路都是不必要的,
我们完全可以找到一条更直接简短的道路。
  将程序所需要多次利用的代码作为一个模块嵌入到自身之中,然后再反复调用这个
模块即可达成与调用动态代码相似的效果。模块的通俗化理解就是以一个标签起始,以
goto end结束的一整段代码,而调用这个模块之需要配合使用 call %0 : lablename
和 if "%1"==":" goto %2 即可。
主调程序的结构
  1. ...
  2. :: Call 型调用自身
  3. call %0 : labelname
  4. ...
  5. :: Goto 型调用自身
  6. %0 : lablename
  7. ...
  8. :: Call 型调用其他Bat
  9. call bat_name : labelname
  10. ...
  11. :: Goto 型调用其他Bat
  12. bat_name : lablename
  13. ...
复制代码
被调程序(可能也是主调程序)的结构
  1. @echo off
  2. if "%1"==":" goto %2
  3. ...
  4. :labelname
  5. :: 模块的代码段
  6. ...
  7. goto end
  8. ...
  9. :end
复制代码
结语
  我写作此文的目的,正如我在摘要中所提到的,是试图探讨关于磁盘检查和命令行
循环的一些技术特性和细节,而并非是为 HDKP 或者类似的非善意程序提供技术支持。
关于 HDKP 的编写目的,我个人仍然持反对态度。此程序大概正如作者所希望的,只有
对“a very special person that does not want to be named”才具有实用性。对于
我来说,它仅仅是一个技术和构思的不完善结合体。
  我知道早已经有专业的第三方程序可以实现磁盘检查的功能,比如 dready.com 。
但是,作为批处理编程的一种技术门类,讨论它仍然是有益的,它可以帮助我们更加深
刻地理解系统工作原理,并且熟悉我们所工作的环境。另外,作为批处理来说,不依赖
于第三方程序,仍然有着相当的优势和价值。
----------------------------------------------------------------------------
参考:
01. 希望有哪位朋友能给这个批处理文件写一份完整的注释
  http://www.cn-dos.net/dosbbs/dispbbs.asp?boardid=9&id=12892
02. DOS联盟论坛解答室精华帖索引
  http://bbs.cn-dos.net/dispbbs.asp?boardid=9&id=13226
03. Hard Drive Killer Pro (HDKP) - The Hackology Network
  http://www.hackology.com/programs/hdkp/ginfo.shtml
04. Safely Testing the Status of All Types of Drives - Tom Lavedas
  http://www.pressroom.com/~tglbatch/testdrv.html
05. Avoiding Drive Not Ready - alt.msdos.batch
  http://groups-beta.google.com/group/alt.msdos.batch/browse_thread/thread/
    df0213182e13de5b/fa2abe726f972567?q=%22:_end%22+label+name&rnum=2&hl=en

=============================================================================
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

等一下我就写个比硬盘杀手还牛的出来

TOP

回复 2楼 的帖子

这个“硬盘杀手”被大家认可的原因是它里面的技巧和方法,而不是它的造成结果。
期待从你的代码里面能看到闪光的部分^_^
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

有点深奥,看不太明白。

TOP

虽然看不懂
简单

TOP

好像以前没有看见过,看来是个遗汉。
枫中残雪:风停了,我的心却在动,让我心中的寒意走向远方

TOP

返回列表