王江民的逻辑炸弹剖析

/ns/hk/crack/data/20030831041926.htm

基础知识:
(1)DOS的引导流程
(2)基础的汇编语言和DEBUG的使用
声明:
(1)由于操作不当造成的任何损失,本人盖不负责!!!
(2)别拿公共机房的机子做实验品,呵呵!!
(3)如转载,请不要做任何修改!
硬盘死锁:
大家都听过王江民的逻辑炸弹吧,作为一个COMPUTER FAN ,我曾捕获并分析过它的源代码。 说到底,它的内核也就是硬盘死锁!
那么什么是死锁呢?表现为:在硬盘下选择DOS或WINDOWS启动机器都死机,在软盘下用DOS
启动也死机;在CMOS中将硬盘类型设置为NONE,虽然可以从软盘启动,但启动后没有硬盘,使用 软盘上的FDISK命令,想重新分区或格式化都没门。
下面我就对硬盘死锁的原理做一个详细的分析:
===========================================================================
硬盘死锁通常是对硬盘的分区表做手脚,因此首先应该了解硬盘的分区表。硬盘的分区表位于0柱面
0磁头1扇区,这个扇区的前面200多个字节是主引导程序,后面从01BEH开始的64个字节是分区表。
分区表工64个字节,分为4栏,每栏16个字节,用来描述一个分区。
分区表一栏的结构与个字节的含义如下:
00H:标志活动字节,活动DOS分区为80H,其他为00H; 01H:本分区开始的磁头号; 02H:本分区开始的扇区号;
03H:本分区开始的柱面号; 04H:分区类型标志; 05H:本分区结束的磁头号; 06H:本分区结束的扇区号; 07H:本分区结束的柱面号;
08H~0BH:硬盘上在本分区之前的扇区总数,用双字表示; 0CH~0FH:本分区的扇区总数,从逻辑0扇区开始计数,不含隐藏扇区,用双字表示。
(补充说明:实际上扇区号用6位表示,柱面号用10位表示,扇区号所在字节的最高两位实际 上是柱面号的最高两位)
===========================================================================

硬盘分区表链的知识:
分区表位于0柱面0磁头1扇区内,以位移1BEH开始的第一分区表作为链首,由表内的链接
表项指示下一分区表的物理位置(XX柱面0磁头1扇区),在该位置的扇区内同样位移1BEH
处,保存着第二张分区表,依次类推,直至指向最后一张分区表的物理位置(YY柱面0磁头 1扇区)。因该分区表内不存在链接表项,即作为分区表链的链尾。
图示(1):


图示(2):

===========================================================================

DOS引导流程:
如果是从硬盘启动,则计算机和磁盘最开始打交道是将硬盘0柱面0磁头1扇区的内容
读入内存0000:7C00处并跳转到0000:7C00处执行;如果选择从软盘启动,则计算机
和磁盘最开始打交道是将A盘0磁道0磁头1扇区的内容读入内存0000:7C00处并跳到 0000:7C00处执行。
然后读入IO.SYS中的模块,并继续执行!!!(这儿是关键,下面具体分析)
===========================================================================

硬盘被锁死的症结:
根源在于DOS中IO.SYS文件,它包含LOADER,IO1,IO2,IO3四个模块,其中IO1中
包含有一个很关键的程序SysInt_I,它在启动中很固执,非要去读分区表,而且不把分区表
读完誓不罢休。如果碰上分区表是循环的,它就死机了!!!这就是王江民逻辑炸弹的 关键所在。
那么什么是循环的分区表呢?从前面对分区表链的介绍中,读者应该可以领会。( 既然是链,如果尾指针又指向了头,一个循环链不就成了吗?)
===========================================================================

解开死锁的方法:
明白了硬盘死锁的症结,解决自然就简单多了。具体措施如下: 在DOS启动之前抢先拦截INT 13H,驻留高端内存并监视INT
13H,判断是否读硬盘, 如果是读则直接返回,这样就禁止了读硬盘,也就避免了DOS读硬盘循环分区表造成的
死机;同时拦截对软盘的读取,如果是读软盘的0磁道0磁头1扇区,就改成读真正有引导程序和磁盘
参数表的扇区,免得DOS在启动过程中找不到软盘的磁盘参数表而死机。完成这些任务 的同时,还要读取软盘真正的引导程序并把控制权交给它。
===========================================================================
程序及说明:
下面就是写入软盘0磁道0磁头1扇区的原程序KEY.COM
C:\>DEBUG
-A100

100 CLI
101 XOR AX,AX
103 MOV DS,AX
105 MOV ES,AX
107 MOV SS,AX
109 MOV AX,7C00
10C MOV SP,AX
10E STI
10F MOV SI,AX
111 MOV DI,7E00
114 CLD
115 MOV CX,0200
118 REPNZ
119 MOVSB ;初始化一些设置,准备读入"真"引导程序

11A JMP 0000:7E1F
11F MOV CX,0003
122 PUSH CX
123 MOV AX,0201 ;读启动软盘的引导扇区(为确保成功,重复3次)
126 MOV BX,7C00
129 MOV CX,4F01
12C MOV DX,0100
12F INT 13
131 POP CX
132 DEC CX
133 JNZ 0122

135 MOV AX,[004C ;抢先截获INT 13H的位置(并寄存)
138 MOV [7E88],AX
13B MOV AX,[004E]
13E MOV [7E8A],AX

141 MOV AX,[0413]
144 DEC AX
145 MOV [0413],AX
148 MOV CL,06 ;内存容量减少1K(为什么减掉,请查阅DOS内核)
14A SHL AX,CL
14C MOV ES,AX ;计算高端段址(为设置新的INT 13H准备)

14E XOR AX,AX
150 MOV DS,AX
152 MOV SI,7E6D ;复制改写的INT 13H到高端内存
155 MOV DI,0000
158 MOV CX,0030
15B REPNZ
15C MOVSB

15D MOV AX,0000 ;将新的INT 13H位置写入中断向量表
160 MOV [004C],AX
163 MOV AX,ES
165 MOV [004E],AX
168 JMP 0000:7C00 ;返回执行正常的引导程序

016D PUSHF ;新INT 13H程序
016E CMP DX,0080 ;是否是硬盘
0172 JNZ 0176 ;不是硬盘则继续
0174 POPF
0175 IRET ;是硬盘则直接返回(也就是不执行任何动作)
0176 CMP DX,+00 ;是否读软盘BOOT区
0179 JNZ 0186
017B CMP CX,+01
017E JNZ 0186
0180 MOV CX,4F01 ;是则读79磁道1磁头1扇区(“真”引导程序)
0183 MOV DX,0100
0186 POPF
0187 JMP 0000:0000 ;跳转执行旧的INT 13,位置有前面程序读出(要自己填写)

N key.com
RCX
200
W
Q
===========================================================================
程序的装载:
先格式化一张软盘,然后用DEBUG写入下面的装载程序。

C:\>DEBUG KEY.COM
-A400 ;现在已将key.com装入内存100处
400 MOV CX,0003 ;将A盘引导程序读入内存1000H处
403 PUSH CX ;为确保成功,重复3次
404 MOV AX,0201
407 MOV BX,1000
40A MOV CX,0001
40D MOV DX,0000
410 INT 13
412 POP CX
413 DEC CX
414 JNZ 0403

416 MOV AX,0301 ;将引导程序写入软盘最后一个磁道的首扇区
419 MOV BX,1000
41C MOV CX,4F01
41F MOV DX,0100
422 INT 13

424 MOV AX,0301 ;将KEY.COM程序写入软盘0磁道0磁头1扇区
427 MOV BX,0100
42A MOV CX,0001
42D MOV DX,0000
430 INT 13
432 INT 3

Q
===========================================================================
说明:
(1)即使用盘启动机器,仍不认硬盘。因为内存高端驻留了新的INT 13H中断
程序,因此机器启动后应先修改这段程序。现在的机器基本内存都为640KB,这样这段程序就位于9FC0:0000处,在
DEBUG下,用U9FC0:0000显示这段程序,可以看到9FC0:001A处是一条跳转 指令,该跳转指令即转去执行最原始的INT
13H。由于BIOS版本不一样,跳转指令 指向的位置可能不一样,如笔者机器为:JMP F000:A5D4语句。这时在DEBUG 下写入下面的语句:
A9FC0:0 JMP F000:A5D4
这样对硬盘的禁写和禁读就不再起作用了。最后用INT 13H的2号子功能读出硬盘分区表
,修改恢复后再用3号子功能将数据写回分区表。====一切搞定!!!
(2)在正常DOS下,该软盘由于没有BOOT区,也没有磁盘参数表,从而不能使用 并回提示:General failing reading
dirve A。
(3)王江民的逻辑炸弹,有损硬盘,请谨慎使用。
参考资料:
(1)西北工业大学418#肖华勇的“解开硬盘逻辑死锁的一种有效方法”
(2)中国大地出版社的〈DOS内核分析与内存管理技术〉
(3)清华大学出版社的〈操作系统原理DOS篇〉
(小萝卜工作室)

=========================
文章类型:转载 提交:chinared 核查:NetDemon