Programming and Application(编程与应用)


Content(目录)




Linux


MySQL
Office















 
PCNow 30-Day Free Trial, Remote PC Access
 
Logo_234x60

软锁驱动器程序


软锁驱动器程序

一般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();
    }
}
©董占山Zhanshan Dong

Post comments(留言)

Name(名字):

Comment(内容):


由Google提供

SunfineData Products|U's Bargain Network|Contact Me(与我联系)
© 1998-, 董占山, 版权所有, 欢迎转载文章链接。
转载文章和软件请注明出处(http://articles.sunfinedata.com/)。