编程技术、软件应用与系统模拟

(Programming, Applicaiton and Simulation)



本站目录

 

首页
ASP/Access/IIS
DELPHI/PASCAL
PASCAL高级编程
C语言编程实例
WORD
Excel
MATLAB
MINITAB讲座
Windows
DOS
SAS
生物系统模拟
土壤水分剖析器
其他



镜像站点

 

主站
北美镜象站
欧洲镜象站(1)
欧洲镜象站(2)

本站 Google

[搜索]  [站内导航]
座右铭:
只做有益人类的事
不做有害人类的事


驱动器路径表的结构及其使用方法

董占山

一般286或386微机都有一个容量极大的硬盘,为使用方便,在硬盘上要安装许多系统软件和专用软件,同时还有很多用户开发的应用程序,由于DOS系统的安全性比较差,软件、程序或数据往往容易被他人非法复制。怎样才能防止他人非法复制呢? 人们想出许多方法,其中有给硬盘加口令字,使子目录名变为隐含等多种方法,我向大家介绍一种使逻辑驱动器失效的防拷贝方法。巧妙地使用本程序,从硬盘启动后,可以使软驱(包括A、B驱)均失崐效,当在C:\>提字符下打入A:并回车,则显示“Invalid drive specification”,键入B:时,同样显示此信息。这样在得不到许可的情况下,非法用户是很难拷贝程序和软件的。

一、获得驱动器路径表的方法

获得驱动器路径表需要用到未编入文档的DOS功能调用52H,该功能调用的用途是得到内部缓冲器的指针,该指针指向的表描述了与存储子系统有关的大多数DOS内部结构,返回指针存在ES:BX中。这个缓冲区的结构随DOS的主要版本而异,对DOS3.XX版及以上版本,此表的偏移16H处为指向驱动器路径的远指针。

驱动器路径表由多个表项组成,每个表项均包含缺省值路径、磁头位置和各种标志和指针,表项的数目等于有效逻辑驱动数加1,最后一表项的标志变量为零,没有任何有用数据。驱动器路径表项的结构如表1。

                   表1、驱动器路径表项的结构
┌────┬─────┬───────────────────────┐
│偏 移   │ 长 度    │ 说 明                                         │
├────┼─────┼───────────────────────┤
│ 0      │ 字 节    │ ASCIIZ格式的当前缺省值路径名,包含着逻辑驱动 │
│        │ (64)     │ 器字母、冒号分隔符和起始符"\"                 │
│40H     │ 双 字    │ 保留,置为0                                   │
│44H     │ 字 节    │ 标志变量,所有有效项包含一个40H,最后一项包含0│
│45H     │ 双 字    │ 逻辑驱动器参数块的远指针                      │
│49H     │ 字       │ 此逻辑驱动器的当前块或磁道/扇区编号           │
│4BH     │ 双 字    │ 远指针                                        │
│4FH     │ 字       │ 未知存储                                      │
│51H     │ 字节(7)  │ 未知存储(仅对MS DOS 5.0以上)                  │
└────┴─────┴───────────────────────┘

从表1可知,在驱动器路径表每个表项的偏移44H处的一个字节为该逻辑驱动器是否有效的标志,有效时为40H,为其它值则无效,所以要使逻辑驱动器失效可以通过DOS功能调用52H,修改这个标志为0即可。

本人用TURBO C 2.0编写了一个程序SL.C,可以用来修改逻辑驱动器路径表,使逻辑驱动器有效或失效。该程序经编译、连接,生成COM文件即可使用。

二、程序的使用方法

该程序采用命令行格式:
     SL [d:] [/switch]
其中d代表驱动器,switch为开关,可取L和U,取时L执行锁驱动器过程,取U时解锁已锁的驱动器。典型用法:
    SL -- 显示程序的帮助信息
    SL C: -- 显示C逻辑盘的当前状态
    SL C: /L -- 锁C逻辑盘
    SL C: /U -- 解锁C逻辑盘
该程序只能在MS DOS 3.0以上的操作系统下工作。
如果想在AUTOEXEC.BAT中使用该程序,又不想在每次启动系统时均输入口令字,可以利用DOS的输入输出重定向的功能来完成。具体方法是,首先建立一个含有口令字的文本文件(如A.DAT),其内容是两行同样的口令字符串,如:
AbCd
AbCd
然后,执行下面的DOS命令:
SL A: /L <A.DAT>NUL
即可将A盘锁住,对B盘只要将命令中的A:改为B:就行了。

三、作用与效果

如果能否巧妙地使用该程序,可以获得防止他人非法拷贝软件、程序或数据;如果将软驱加锁,对不知道加锁口令的用户,在未得到许可时无法使用软驱,从而可以减少在盘片交换过程中的病毒入侵机会。

经我长期使用该程序,取得了良好的效果。在软驱被锁后,减少了机器感染过病毒的可能,每当交换数据前,我们均用防毒软件对软盘进行消毒,以致于病毒很难侵入系统,这对系统的安全和数据的保密都有很好的效果。

四、源程序清单

/********************************************************/
/* 程序名称: SL.C 1.50 */
/* 作 者: 董占山 */
/* 完成日期: 1991,1995 */
/* 用 途: 软锁驱动器的程序 */
/* 编译方法: 用下列命令编译连接可以得到SL.COM: */
/* tcc -mt sl */
/* tlink c:\tc\lib\c0t+sl,sl,,c:\tc\lib\cs\lib /t */
/********************************************************/

#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <ctype.h>

char drive,sw;
int seg,ofs;
int tablelen5=0x58,tabletail5=0x14; /* DOS 5.0以上版本的参数 */
int tablelen3=0x51,tabletail3=0xd; /* DOS 3.0以上5.0以下版本的参数 */

/* 显示程序使用方法 */
void help()
{
printf("Syntax: SL [d:] [/sw]\n");
printf("Switch: /L = Lock the drive d:\n");
printf(" /U = Unlock the drive d:\n");
printf("Examples: SL -- Display help text\n");
printf(" SL C: -- Display the state of drive C\n");
printf(" SL C: /L -- Lock the drive C\n");
printf(" SL C: /U -- Unlock the drive C\n");
printf("Note: Only Using in MS DOS 3.0 and above\n");
}

/* 输入口令字符串,并将口令写到驱动器路径表中 */
void getpassword()
{
char pw[9],pw1[9];
int i=0,j;
do {
printf("Enter the PASSWORD (8 characters) : ");
scanf("%s",pw);
printf("Enter the PASSWORD again (8 characters) : ");
scanf("%s",pw1);
} while (strcmp(pw,pw1)!=0);
j = ofs - 8 - 4;
while ((pw[i])!='\0') {
pokeb(seg,j,pw[i]); /* 将口令字写入驱动器路径表中 */
i++;
j++;
}
pokeb(seg,j,0);
}

/* 输入口令并校验 */
int checkpassword()
{
char pw[9],PsWdStr[9];
int i=0,j;
printf("Enter the PASSWORD (8 characters): ");
scanf("%s",pw);
j = ofs - 8 - 4;
/* 从路径表中取出口令字 */
while ((PsWdStr[i++]=peekb(seg,j))!=0) pokeb(seg,j++,0);
PsWdStr[i]='\0';
return strcmp(pw,PsWdStr);
/* 如果输入的口令与锁驱动器时的口令相吻合,返回0,否则返回非零值 */
}

/* 取得驱动器的标识字节的地址 */
void getaddress()
{
int tablelen,tabletail;
switch (_osmajor) { /* 检查DOS系统的主版本号 */
case 3 : ; /* DOS 3.XX */
case 4 : tablelen=tablelen3; /* DOS 4.XX */
tabletail=tabletail3;
break;
case 5 : ; /* DOS 5.XX */
case 6 : tablelen=tablelen5; /* DOS 6.XX */
tabletail=tabletail5;
break;
default : printf("SL can not run under the DOS version !\n");
help();
exit(0);
}
asm SUB AX,AX
asm MOV AH,0x52 /* 取DOS内部缓冲器的指针 */
asm INT 0x21
asm MOV AX,ES:[BX+0x18] /* 取驱动器路径的远指针的段值 */
asm PUSH AX
asm MOV AX,ES:[BX+0x16] /* 取驱动器路径的远指针的偏移量 */
asm MOV BX,AX
asm POP ES
asm sub ch,ch
asm mov cl,drive
asm mov al,0x41 /* 字符A */
asm sub cl,al
asm inc cl /* 第几个驱动器 */
l1:
asm ADD BX,tablelen /* 驱动器路径表长度 */
asm LOOP l1
asm SUB BX,tabletail /* 减去表尾的字节数 */
asm mov seg,es /* 返回驱动器路径表的段地址 */
asm mov ofs,bx /* 返回驱动器路径表中标志字节的偏移量 */
}

/* 取驱动器的当前状态 */
void drivestate()
{
getaddress();
if (peekb(seg,ofs) == 0x40) /* 驱动器有效吗? */
printf("The state of the drive is unlocked !\n");
else
printf("The state of the drive is locked !\n");
}

/* 锁指定的驱动器 */
void Lockdrive()
{
getaddress();
if (peekb(seg,ofs) == 0x40) { /* 驱动器有效吗? */
getpassword(); /* 设置口令字 */
pokeb(seg,ofs,'\0'); /* 将标志字节置为无效 */
printf("This drive has been locked!\n");
}
else
printf("The state of the drive has been locked !\n");
}

/* 解锁指定的驱动器 */
void UnLockdrive()
{
getaddress();
if (peekb(seg,ofs) == 0) { /* 驱动器锁了? */
if (checkpassword()==0) { /* 检查口令字 */
pokeb(seg,ofs,0x40); /* 将标志字节置为有效 */
printf("\nYour password is correct,the drive is unlocked !\n");
}
else {
printf("\n%s\n%s\n","Your password is not correct,the drive cannot be unlocked !",
"Please ask system manager to get the password !");
}
}
else
printf("The state of the drive has been unlocked !\n");
}

/* 取系统有效驱动器个数 */
char getdrivenum()
{
char mydrive;
asm sub ax,ax
asm mov ah,52h
asm int 21h
asm sub ah,ah
asm mov al,es:[bx+20h] /* 有效驱动器个数 */
asm mov mydrive,al
return mydrive;
}

/* 执行加/解锁 */
void works()
{
switch (sw) {
case 'L' : Lockdrive();break;
case 'U' : UnLockdrive();break;
default : printf("The switch is invalid !\n");
}
}

/* 显示错误信息 */
void writeerror()
{
printf("The parameter is error !\n\n");
help();
exit(0);
}

/* 分析DOS命令行参数 */
void getparameter(argc,argv)
int argc;
char *argv[];
{
char tempstr[3],tempchar;
if (argc > 1) {
strcpy(tempstr,argv[1]);
if (tempstr[1] == ':') {
tempchar = toupper(tempstr[0]); /* 取驱动器代号 */
if (isalpha(tempchar)) drive = tempchar;
else writeerror();
}
else writeerror();
}
if (argc > 2) {
strcpy(tempstr,argv[2]);
if (tempstr[0] == '/') {
tempchar = toupper(tempstr[1]);
sw = tempchar; /* 取开关字符 */
}
else writeerror();
}
}

/* 主程序 */
main(argc,argv)
int argc;
char *argv[];
{
printf("SL version 1.50 Copyright (c) 1991,95 Dong Zhanshan\n");
getparameter(argc,argv);
if (drive >= 'A') /* 判断驱动器是否有效 */
if (drive - 'A' + 1 > getdrivenum()) writeerror();
switch (argc) { /* 执行功能模块 */
case 1 : help();break;
case 2 : drivestate();break;
case 3 : works();break;
default: writeerror();
}
}


© 1998-, 董占山, 版权所有。
转载文章请注明出处(www.sunfinedata.com/articles)。