长期以来,许多人就超级用户口令被忘记的问题发表了各种看法。一部分人认为,一旦忘记了超级用户口令,只能重装操作系统,此外别无它法。另一部分人则坚决反对这种“重装论”,他们提出了一些经过成功实践的解决方案,使得“重装论”者败下阵来。现在我们可以肯定地说,忘记超级用户口令是有办法解决的。但同时我们也不得不承认,现行的解决方案有很大的局限性,这些局限性决定了现有方案无论怎样变化和发展也不可能成为一种有着强大生命力的最彻底的解决方案。
传统解决方案的局限性
上面已经谈到,目前有多种针对超级用户口令被忘记问题的解决方案。为了叙述上的方便,本文将这些方案统称为传统解决方案。传统方案乍看起来似乎各不相同,但经过认真分析和归纳后就会发现,它们实际上大同小异,都有以下共同点:
1. 必须有一套(两张)Emergency Boot Floppy (紧急启动软盘)。这套软盘均为文件系统格式,必须在SCO UNIX上制作,并且在不同类型机器上制作的紧急启动软盘相互不能通用。
2. 用紧急启动软盘启动后,将硬盘根文件系统mount到某个目录下(一般为/mnt目录),然后进入该目录(即进入硬盘根文件系统的根目录),修改相关目录下与超级用户口令有关的信息(各种方案的不同之处主要体现于此)。最后回到软盘根目录,拆卸/dev/hd0root,重启机器。
这些共同点实际上反映了传统方案的局限性:
一、操作平台局限性:要求自始至终必须在SCO UNIX操作系统平台上实施。
二、操作工具局限性:对紧急启动软盘的依赖性太大。万一软盘发生损毁,必须找一台类型相同的机器再制作一套,这就是前面所说的“专盘专用”的限制。
三、操作对象局限性:必须依靠硬盘根文件系统的支持。即操作者与修改对象(指与超级用户口令有关的信息)被文件系统隔开,操作者不能直接修改对象,只能调用文件系统提供的服务修改。这种方式本是信息科学中倡导的层次化思想的一种体现,在正常情况下应予称道;但任何事物都是有两面性的,在非常情况下 ?? 诸如解决忘记超级用户口令这一类问题时 ?? 该方式反而有可能带来麻烦。
三大局限性说明了传统解决方案可行性的脆弱和狭窄,也决定了它们作为凌驾于文件系统之上的高层方案所必然具有的弊端。于是,打破这些局限性,探索出一种全新的解决方案,就成为了摆在一切UNIX研究者面前的新课题。
新课题
所谓新课题,就是找到一种能够突破传统方案局限性的新方案。究竟从何处下手呢?
让我们再来看一看三大局限性。
操作平台局限性似乎不好突破,因为其它操作系统识别不了UNIX的文件系统格式。
操作工具局限性好象就更难了,因为紧急启动软盘既要在UNIX上制作,又要在UNIX上使用,所以如果操作平台局限性突破不了,它就更突破不了。
最后看看操作对象局限性。操作对象完全由文件系统管理,操作者必须通过文件系统访问它们。万一文件系统崩溃,那么即使它下面的文件完好无损,操作者也只能认为这些文件已全部丢失 ?? 因为文件系统无法访问(例如mount不上来)。其实这个时候还是有办法找到那些文件的,方法就是直接访问物理硬盘。道理很简单:就本质而言,文件系统只不过是一个构筑于物理硬盘之上的逻辑组织,平时我们是通过它来访问物理硬盘的;现在这个组织寿终正寝,不能再为我们服务了,于是我们只好“自己动手,丰衣足食”。直接访问物理硬盘不但可以使文件“失”而复得,而且还有另外一个重要意义 ?? 突破了操作对象局限性。
操作对象局限性一旦突破,我们就会惊奇地发现突破另外两大局限性简直可以说是顺理成章了。因为虽然其它操作系统识别不了UNIX的文件系统格式,但在任何操作系统上,我们都可以访问物理硬盘;而只要是带有访问物理硬盘功能的软件,都可以成为我们的操作工具。
现在我们要做的仅仅是:找一个大家最熟悉的操作系统和一个最易寻觅的可以访问物理硬盘的软件。
大家最熟悉的操作系统无疑是DOS。可以访问物理硬盘的软件很多,但最易寻觅的莫过DEBUG.EXE。所谓最易寻觅,是因为DEBUG是DOS本身的一条外部命令,可以说只要是在安装了DOS的机器上都可以找到它。对DEBUG略知一二的人可能会指出该命令并没有提供访问物理硬盘的选项,但请不要忘记 DEBUG是DOS提供给用户的一个汇编语言调试程序,我们完全可以利用它编写、调试和执行一个汇编小程序去访问物理硬盘。应该说,这对一个能够取得系统管理员身份的人并不困难。
综上所述,在DOS上运行DEBUG来破除UNIX管理员口令,这就是本文提出的解决SCO UNIX超级用户口令被忘记问题的新方案。
新方案的应用
新方案已经提出,下面我们来看看它是如何应用于实践的。
我们假设一台装有SCO OpenServer Release 5的超级用户口令被忘记。
首先,随便找一台安装了DOS的计算机,制作一张DOS系统盘,并在系统盘上拷贝一个DEBUG.EXE文件。
COS>format/s a:
COS>copy debug.exe a:
然后将该盘插入COMPAQ服务器A驱,开机启动DOS操作系统,执行DEBUG命令。
A:>debug
现在我们就编写一段汇编语言程序,来读出硬盘0柱0头1扇区的内容。该扇区存放的是主引导记录,读出它是为了确定SCO UNIX分区的起始位置。该程序是调用中断13H实现的,以后我们还要反复用到它,当然入口参数将随所读内容物理地址的变化而变化。
-a
2039:0100 MOV AX,0201
2039:0103 MOV BX,1000
2039:0106 MOV CX,0001
2039:0109 MOV DX,0080
2039:010C INT 13
2039:010E INT 20
2039:0110
-g
Program terminated normally
-d 1180
2039:1180 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:1190 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:11A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:11B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:11C0 01 6E 06 3F 20 96 00 70-03 00 00 48 01 00 00 00 .n.? ..p...H....
2039:11D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:11E0 01 97 05 3F E0 FF 00 B8-04 00 00 C8 1B 00 80 00 ..c?............
2039:11F0 01 01 63 3F 20 6D 00 08-00 00 00 68 03 00 55 AA ..c? m.....h..U.
从分区表中可看出硬盘上共有三个分区,其中类型标志字节为 63H的分区是SCO UNIX分区。该分区起始于1柱面0磁头1扇。
下面,读出UNIX根文件系统i-node表的第一个扇区,以确定根目录的位置。
先读 i-node 表。由于UNIX分区始于1柱0头1扇,所以根文件系统必定始于2柱0头1扇。并且,由于2柱0头1扇是引导块,2扇是专用块,3、4扇为间隔,所以 i-node 表必定始于第5扇。
-a
2039:0100 MOV AX,0201
2039:0103 MOV BX,1000
2039:0106 MOV CX,0205
2039:0109 MOV DX,0080
2039:010C INT 13
2039:010E INT 20
2039:0110
-g
Program terminated normally
-d 1000
2039:1000 00 80 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:1010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:1020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:1030 00 00 00 00 0A 4B 32 33-0A 4B 32 33 0A 4B 32 33 .....K23.K23.K23
2039:1040 ED 41 10 00 00 00 02 00-80 02 00 00 DA 05 00 00 .A..............
2039:1050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:1060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:1070 00 00 00 00 E1 83 C5 35-46 82 C5 35 46 82 C5 35 .......5F..5F..5
现在我们看到的是 i-node 表的前两项。从偏移1040H至107FH的64个字节是2号i-node ,即根目录的 i-node 。
下面我们就根据 i-node 计算根目录在硬盘上的物理地址。
我们从偏移1040H看起:
ED41H表示文件类型与存取权限为“drwxr-xr-x”;
1000H表示文件连结数为16;
0000H表示文件属主ID为 0;
0200H表示文件组ID为 2;
80020000H表示文件字节数为 640个;
DA0500H表示第一个数据块地址。由于其它12个数据块地址均为 0,所以可断定根目录在硬盘上只占了一个数据块。现在我们必须依据DA0500H计算出这个数据块存放在硬盘的第几柱面、第几磁头、第几扇区。如何计算?作者专门总结了一套公式:
C = TRUNC ( P/(H*S) )
C1 = C0 + C
H1 = TRUNC( (P-C*H*S)/S )
S1 = P - C*H*S - H1*S + 1
其中:
C1、H1、S1分别为数据块物理地址柱面号、磁头号、扇区号
P等于数据块地址翻译成十进制数后再乘以 2
H为硬盘磁头数
S为每磁头扇区数
C0为根文件系统起始柱面
C只是一个中间量
将DA0500H代入上述公式,并根据H=64,S=32,C0=2,可算出C1=3,H1=29,S1=21。因此根目录在硬盘上的物理地址为: 3柱面 29头 21扇。
下面就把它读出来。
-a
2039:0100 MOV AX,0201
2039:0103 MOV BX,1000
2039:0106 MOV CX,0315
2039:0109 MOV DX,1D80
2039:010C INT 13
2039:010E INT 20
2039:0110
-g
Program terminated normally
-d 1000
2039:1000 02 00 2E 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:1010 02 00 2E 2E 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:1020 03 00 64 65 76 00 00 00-00 00 00 00 00 00 00 00 ..dev...........
2039:1030 0C 00 62 69 6E 00 00 00-00 00 00 00 00 00 00 00 ..bin...........
2039:1040 1F 00 75 73 72 00 00 00-00 00 00 00 00 00 00 00 ..usr...........
2039:1050 22 00 65 74 63 00 00 00-00 00 00 00 00 00 00 00 ".etc...........
2039:1060 4B 00 73 68 6C 69 62 00-00 00 00 00 00 00 00 00 K.shlib.........
2039:1070 4E 01 2E 6C 61 73 74 6C-6F 67 69 6E 00 00 00 00 N..lastlogin....
上面列出的就是根目录的前八项,从中可以看出 /etc 目录的 i-node 号为 22H,即34D。
因为每个扇区有8个 i-node,所以34号 i-node 必定在2柱面0头9扇。
-a
2039:0100 MOV AX,0201
2039:0103 MOV BX,1000
2039:0106 MOV CX,0209
2039:0109 MOV DX,0080
2039:010C INT 13
2039:010E INT 20
2039:0110
-g
Program terminated normally
-d 1000
2039:1000 C9 81 01 00 02 00 02 00-36 9F 00 00 04 07 00 05 ........6.......
2039:1010 07 00 06 07 00 07 07 00-08 07 00 09 07 00 0A 07 ................
2039:1020 00 0B 07 00 0C 07 00 0D-07 00 0E 07 00 00 00 00 ................
2039:1030 00 00 00 00 DA 83 C5 35-7C 22 A5 2B 37 4B 32 33 .......5|".+7K23
2039:1040 FD 41 16 00 02 00 15 00-00 12 00 00 2D 07 00 B8 .A..........-...
2039:1050 17 00 78 1A 00 68 83 00-28 9E 00 00 00 00 00 00 ..x..h..(.......
2039:1060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:1070 00 00 00 00 2A 31 C1 35-C7 83 C5 35 C7 83 C5 35 ....*1.5...5...5
偏移1040H至107FH正是 /etc 目录的 i-node 。我们把它的数据块也读出来。先读第一个数据块。将2D0700H代入公式,算出 /etc第一个数据块物理地址是3柱面50头27扇。
-a
2039:0100 MOV AX,0201
2039:0103 MOV BX,1000
2039:0106 MOV CX,031B
2039:0109 MOV DX,3280
2039:010C INT 13
2039:010E INT 20
2039:0110
-g
Program terminated normally
-d 1000
2039:1000 22 00 2E 00 00 00 00 00-00 00 00 00 00 00 00 00 "...............
2039:1010 02 00 2E 2E 00 00 00 00-00 00 00 00 00 00 00 00 ................
2039:1020 23 00 54 49 4D 45 5A 4F-4E 45 00 00 00 00 00 00 #.TIMEZONE......
2039:1030 24 00 62 61 64 74 72 6B-00 00 00 00 00 00 00 00 $.badtrk........
2039:1040 25 00 62 63 68 65 63 6B-72 63 00 00 00 00 00 00 %.bcheckrc......
2039:1050 26 00 64 65 66 61 75 6C-74 00 00 00 00 00 00 00 &.default.......
2039:1060 2B 00 64 69 76 76 79 00-00 00 00 00 00 00 00 00 +.divvy.........
2039:1070 2C 00 64 6B 69 6E 69 74-00 00 00 00 00 00 00 00 ,.dkinit........
-d
2039:1080 2D 00 65 6D 75 6C 61 74-6F 72 00 00 00 00 00 00 -.emulator......
2039:1090 2D 00 65 6D 75 6C 61 74-6F 72 2E 6D 73 00 00 00 -.emulator.ms...
2039:10A0 2E 00 66 64 69 73 6B 00-00 00 00 00 00 00 00 00 ..fdisk.........
2039:10B0 2F 00 66 73 63 6B 00 00-00 00 00 00 00 00 00 00 /.fsck..........
2039:10C0 30 00 66 73 63 6D 64 2E-64 00 00 00 00 00 00 00 0.fscmd.d.......
2039:10D0 37 00 66 73 73 74 61 74-00 00 00 00 00 00 00 00 7.fsstat........
2039:10E0 38 00 67 72 6F 75 70 00-00 00 00 00 00 00 00 00 8.group.........
2039:10F0 39 00 68 61 6C 74 73 79-73 00 00 00 00 00 00 00 9.haltsys.......
-d
2039:1100 39 00 72 65 62 6F 6F 74-00 00 00 00 00 00 00 00 9.reboot........
2039:1110 3A 00 68 64 62 6F 6F 74-30 00 00 00 00 00 00 00 :.hdboot0.......
2039:1120 3B 00 68 64 62 6F 6F 74-31 00 00 00 00 00 00 00 ;.hdboot1.......
2039:1130 3C 00 69 6E 69 74 00 00-00 00 00 00 00 00 00 00 <.init..........
2039:1140 AD 13 69 6E 69 74 74 61-62 00 00 00 00 00 00 00 ..inittab.......
2039:1150 3E 00 69 6F 63 74 6C 2E-73 79 73 63 6F 6E 00 00 >.ioctl.syscon..
2039:1160 3F 00 6D 61 73 74 65 72-62 6F 6F 74 00 00 00 00 ?.masterboot....
2039:1170 40 00 6D 6B 66 73 00 00-00 00 00 00 00 00 00 00 @.mkfs..........
-d
2039:1180 41 00 6D 6B 6E 6F 64 00-00 00 00 00 00 00 00 00 A.mknod.........
2039:1190 42 00 6D 6F 75 6E 74 61-6C 6C 00 00 00 00 00 00 B.mountall......
2039:11A0 0C 02 70 61 73 73 77 64-00 00 00 00 00 00 00 00 ..passwd........
2039:11B0 44 00 70 69 70 65 00 00-00 00 00 00 00 00 00 00 D.pipe..........
2039:11C0 45 00 73 63 73 69 62 61-64 62 6C 6B 00 00 00 00 E.scsibadblk....
2039:11D0 46 00 73 65 74 6D 6E 74-00 00 00 00 00 00 00 00 F.setmnt........
2039:11E0 47 00 73 77 61 70 00 00-00 00 00 00 00 00 00 00 G.swap..........
2039:11F0 48 00 74 74 79 74 79 70-65 00 00 00 00 00 00 00 H.ttytype.......
偏移11A0H至11AFH是 /etc 目录下的passwd文件名。我们把它改成zls。
-e 11a2
2039:11A2 70.7a 61.6c 73.73 73.00 77.00 64.00
-a 100
2039:0100 MOV AX,0301
2039:0103
-g
Program terminated normally
现在退出DEBUG命令。
取出软盘,重启机器,引导UNIX操作系统。
按照引导顺序,UNIX显示出硬件配置信息后就该提问超级用户口令了,但就在此时它却突然发现 /etc/passwd 文件失踪了!(其实只是被改名为zls,但UNIX对此一无所知。)
没有了这个文件,UNIX无法提问超级用户口令,于是它只好在屏幕上显示如下信息并允许用户以系统管理员身份直接进入系统维护态:
su: Unknown id: root
/etc/tcbck: file /etc/passwd is missing or zero length
/etc/tcbck: either slash (/) is missing
from /etc/auth/system/files or there
are malformed entries in /etc/passwd or /etc/group
/etc/smmck: restore missing files from backup or distribution.
INIT: SINGLE USER MODE
**** PASSWORD FILE MISSING! ****
Entering System Maintenance Mode
#
现在既然已经进入维护态,当然就可以“为所欲为”了。但最好先设置一个新的超级用户口令。
首先,我们必须恢复passwd文件名。
#mv/etc/zls /etc/passwd
然后,就可以用passwd命令设置新的超级用户口令了。
# passwd
Setting password for user: root
Choose password
You can choose whether you pick a password,
or have the system create one for you.
1. Pick a password
2. Pronounceable password will be generated for you
Enter choice (default is 1): 1
Please enter new password:
New password:
Re-enter password:
# reboot
以后就可以用新口令登录系统了。
结束语
在本文行将结束时,我们再来作一个小小的总结。
传统方案有操作平台、操作工具和操作对象局限性。新方案则突破了这三大局限性。
一、新方案突破了操作平台局限性。传统方案的操作平台必须是UNIX,而新方案则是DOS。DOS比UNIX普及得多,中国的绝大部分计算机用户对UNIX陌生,但对DOS却相当熟悉,使用起来也有亲切感。
二、新方案突破了操作工具局限性。传统方案的操作工具必须是两张紧急启动软盘,而新方案仅使用一张DOS系统盘,其上只需拷贝一个DEBUG.EXE文件。紧急启动软盘只能专盘专用,DOS系统盘却不存在这个问题 ?? 用任何一台机器上的DOS制作出的系统盘,可以用来解决任何一台机器上的UNIX超级用户口令被忘记的问题。至于用来访问物理硬盘的软件,当然更不是非 DEBUG不可,任何软件??只要支持访问物理盘??均可。作者推荐使用Norton 8.0 软件包里的diskedit程序,对不懂汇编语言编程的人来说该程序无疑是一个最好的选择。
三、新方案突破了操作对象局限性。传统方案的操作对象是文件系统管理下的文件,而新方案撇开了文件系统,直接在底层修改数据。
最后需要强调的是,本文的要旨所在绝非仅仅体现在解决超级用户口令被遗忘的问题上。事实上,利用这种直接读取硬盘物理扇区的方法,还可以恢复那些在UNIX上被误删除的文件。
关于这一点,如果有机会,作者会加以适当的补充。