I
import
Unregistered / Unconfirmed
GUEST, unregistred user!
磁盘卷序列号的显示和修改 西南师范大学物理系
陈昌友
---- DOS4.0以上的版本,在磁盘格式化时给磁盘设置了一个卷系列号,即磁盘ID,用作磁盘的标识信息,可以使用dir命令显示卷系列号,如:
Valume in drive C is KSW100
Valume Serial Number is 4160-9FE5
...
---- 其中开始的第二行为卷系列号显示,DOS是利用卷系列号与驱动器上的磁盘保持联系的。
---- 由于format命令格式化磁盘时生成的卷系列号是一固定格式的随机数,两次格式化磁盘生成的卷系列号相同的几率几乎为零,因此一些商业软件或共享软件经常利用卷系列号进行软件加密。比如,某些共享软件要求你用C盘的序列号到他们的互连网主页上去申请软件的授权号或许可证,有了授权号你才能安装该软件或是获得许可证后你才能使用该软件的所有功能(通常也是最重要的功能),如果你要将该软件安装于多台微机上,就得为每一台微机申请一个授权许可证,或是你重新格式化硬盘后,也得再去申请授权许可证。
---- 那么,磁盘序列号可不可以进行修改呢?
---- DOS的INT21H中断的69H功能号为我们提供了这样的一个功能,其入、出口参数如下:入口 AH=69H
BL=驱动器号(0=当前,1=A,2=B,3=C,...)
DSX=缓冲区地址(用于存放磁盘的ID信息等)
AL=00H取介质ID
AL=01H置介质ID
出口 CF=0操作成功
CF=1操作失败
AX=错误码
---- 取、置介质时介质ID都放在缓冲区中,缓冲区大小为25字节,用字符数组buffer[25]给出,其中卷系列号在第3~6字节(即buffer[2]~buffer[5],注意高字节在后),第7~17字节(buffer[6]~buffer[16])是卷标。在置介质ID时除卷标和卷序列号外buffer的其它字节最好不要改动,应特别注意对FAT32的 WINDOWS最后8字节不要改动,否则WINDOWS将不能启动。
---- 因此,程序处理过程是首先将磁盘ID读出到缓冲区buffer中,再对第3~6字节进行修改后回写,即可改变磁盘卷序列号又不会改变其它字节内容。
---- 由于DOS不能存取FAT32,要对FAT32的WINDOWS磁盘操作,可以在WINDOWS的MSDOS模式下运行该程序,或者将程序中DOS功能调用改为使用ROMBIOS的INT13H中断调用(可读写磁盘任意扇区),但相对DOS功能号调用要复杂得多(首先必须借助于分区表信息定位要修改的ID所在的物理扇区,其次还要注意FAT16和FAT32的卷序列号在扇区的偏移量也是不同的)。
---- 下面就DOS软中断功能号调用给出Turbo C源程序:
#include< stdio.h >#include< conio.h >#include
< dos.h >#include< stdlib.h >void main(){int i=1,j;
union REGS regs;
struct SREGS sregs;
unsigned char ch, buffer [25];
clrscr();
while(i){ printf("select disk..."
printf("--Current disk 1--disk A
2--disk B 3--disk C..."
ch=getch();
if((ch<48)||(ch >57)) i=1;
else i=0;
j=ch-48;
}
regs.h.ah=0x69; regs.h.al=0x00; regs.h.bl=j;
regs.x.dx=FP_OFF(buffer); sregs.ds=FP_SEG(buffer);
intdosx(?s,?s,&sregs);
if(regs.x.cflag==0)
{printf("disk serial number is "
printf("%02X%02X-%02X%02X.",buffer
[5],buffer[4],buffer[3],buffer[2]);
}
else {printf("get serial number is failure."
getch();
exit(1);}
printf("or not set
this disk's serial number?(Y/N)"
ch=getch();
if((ch==89)||(ch==121))
{printf("enter eight HEX
numerals(such as 1f23e35b):"
scanf("%2x%2x%2x%2x",&buffer[2],
&buffer[3],&buffer[4],&buffer[5]);
ch=buffer[5];buffer[5]=buffer[2];buffer[2]=ch;
ch=buffer[3];buffer[3]=buffer[4];buffer[4]=ch;
regs.h.ah=0x69; regs.h.al=0x01; regs.h.bl=j;
regs.x.dx=FP_OFF(buffer); sregs.ds=FP_SEG(buffer);
intdosx(?s,?s,&sregs);
if(regs.x.cflag==0) printf
("operation is successful!"
}
return 0;
}
陈昌友
---- DOS4.0以上的版本,在磁盘格式化时给磁盘设置了一个卷系列号,即磁盘ID,用作磁盘的标识信息,可以使用dir命令显示卷系列号,如:
Valume in drive C is KSW100
Valume Serial Number is 4160-9FE5
...
---- 其中开始的第二行为卷系列号显示,DOS是利用卷系列号与驱动器上的磁盘保持联系的。
---- 由于format命令格式化磁盘时生成的卷系列号是一固定格式的随机数,两次格式化磁盘生成的卷系列号相同的几率几乎为零,因此一些商业软件或共享软件经常利用卷系列号进行软件加密。比如,某些共享软件要求你用C盘的序列号到他们的互连网主页上去申请软件的授权号或许可证,有了授权号你才能安装该软件或是获得许可证后你才能使用该软件的所有功能(通常也是最重要的功能),如果你要将该软件安装于多台微机上,就得为每一台微机申请一个授权许可证,或是你重新格式化硬盘后,也得再去申请授权许可证。
---- 那么,磁盘序列号可不可以进行修改呢?
---- DOS的INT21H中断的69H功能号为我们提供了这样的一个功能,其入、出口参数如下:入口 AH=69H
BL=驱动器号(0=当前,1=A,2=B,3=C,...)
DSX=缓冲区地址(用于存放磁盘的ID信息等)
AL=00H取介质ID
AL=01H置介质ID
出口 CF=0操作成功
CF=1操作失败
AX=错误码
---- 取、置介质时介质ID都放在缓冲区中,缓冲区大小为25字节,用字符数组buffer[25]给出,其中卷系列号在第3~6字节(即buffer[2]~buffer[5],注意高字节在后),第7~17字节(buffer[6]~buffer[16])是卷标。在置介质ID时除卷标和卷序列号外buffer的其它字节最好不要改动,应特别注意对FAT32的 WINDOWS最后8字节不要改动,否则WINDOWS将不能启动。
---- 因此,程序处理过程是首先将磁盘ID读出到缓冲区buffer中,再对第3~6字节进行修改后回写,即可改变磁盘卷序列号又不会改变其它字节内容。
---- 由于DOS不能存取FAT32,要对FAT32的WINDOWS磁盘操作,可以在WINDOWS的MSDOS模式下运行该程序,或者将程序中DOS功能调用改为使用ROMBIOS的INT13H中断调用(可读写磁盘任意扇区),但相对DOS功能号调用要复杂得多(首先必须借助于分区表信息定位要修改的ID所在的物理扇区,其次还要注意FAT16和FAT32的卷序列号在扇区的偏移量也是不同的)。
---- 下面就DOS软中断功能号调用给出Turbo C源程序:
#include< stdio.h >#include< conio.h >#include
< dos.h >#include< stdlib.h >void main(){int i=1,j;
union REGS regs;
struct SREGS sregs;
unsigned char ch, buffer [25];
clrscr();
while(i){ printf("select disk..."
printf("--Current disk 1--disk A
2--disk B 3--disk C..."
ch=getch();
if((ch<48)||(ch >57)) i=1;
else i=0;
j=ch-48;
}
regs.h.ah=0x69; regs.h.al=0x00; regs.h.bl=j;
regs.x.dx=FP_OFF(buffer); sregs.ds=FP_SEG(buffer);
intdosx(?s,?s,&sregs);
if(regs.x.cflag==0)
{printf("disk serial number is "
printf("%02X%02X-%02X%02X.",buffer
[5],buffer[4],buffer[3],buffer[2]);
}
else {printf("get serial number is failure."
getch();
exit(1);}
printf("or not set
this disk's serial number?(Y/N)"
ch=getch();
if((ch==89)||(ch==121))
{printf("enter eight HEX
numerals(such as 1f23e35b):"
scanf("%2x%2x%2x%2x",&buffer[2],
&buffer[3],&buffer[4],&buffer[5]);
ch=buffer[5];buffer[5]=buffer[2];buffer[2]=ch;
ch=buffer[3];buffer[3]=buffer[4];buffer[4]=ch;
regs.h.ah=0x69; regs.h.al=0x01; regs.h.bl=j;
regs.x.dx=FP_OFF(buffer); sregs.ds=FP_SEG(buffer);
intdosx(?s,?s,&sregs);
if(regs.x.cflag==0) printf
("operation is successful!"
}
return 0;
}