关于对IDE的I/O操作(1F0-1F7)
编号:QA002951
建立日期: 2000年5月18日 最后修改日期:2000年5月18日
所属类别:
lyq:
操作系统:dos
编程工具:masm
问题:请提供关于对IDE的I/O操作(1F0-1F7)方面所有的资料。thanks.
回答:
这是本人98年发表在《计算机应用杂志》上的一篇文章,也许有用。
软件注册器的基本原理及实现
王有翦 甘肃·西峰(745000)
摘要:本文介绍了一种软件注册器的实现方案,并且提供了一崐个用C语言实现的例子。
关键词:软件注册器 加密 IDE接口
The basic theroy of software register and implation
Wang Youjian
China People Bank Xifeng Branch,Xifeng·GanSu 745000
Abstract: This article introduces the method of崐realization of software registrar,and provided a example of C language.
Key:Software registrar,encryption,IDE interface
目前,传统的磁盘加密和软件狗加密的技术,在层出不穷的解崐密工具的攻击下,已走到山穷水尽之地,很难对抗内存驻留程序的崐动态仿真等解密技术。为了保护软件开发者的权益,出现了使用电崐脑中的ROM、CMOS等不容易改变且不同的机器上内容不同的信息进崐行密钥生成和检验的软件注册器加密办法,为软件的加密销售找到崐了一种新的途径。同时也出现了专门的软件注册器,广泛使用的崐CCED、数据通等软件使用的就是同一种软件注册器。
一些早期软件注册器使用电脑的CMOS信息,使用户的硬件升级崐受到一定的限制。后来的软件注册器仅仅使用硬盘驱动器的一些信崐息,摆脱了对其它硬件依赖性,成为一种比较完善的加密方式。
要让应用软件确认只有一个硬盘是合法用户的硬盘,必须使用硬盘中的唯一性信息,这些信息不能受硬盘的分区和格式化等软件崐因素的影响。要得到这类信息,就要了解硬盘接口的种类及硬盘控崐制器的有关命令格式和返回值。广泛使用的IDE/EIDE接口硬盘中有崐一些ROM信息,可以用相应的硬盘控制命令读出,其中有一部分信崐息是具有唯一性的,可以用来生成密钥。
一、软件注册器实现的软硬件基础
要实现针对某一台机器或者某一块硬盘的软件注册,首先要在崐相关的硬件设备上选择适当的特征数据,利用这些数据生成硬件代崐码。可供选择的数据有主板上的ROM信息和硬盘上的ROM信息等。其崐中硬盘的ROM信息使用相对方便。UCDOS的某些版本就使用电脑主板崐上的生产日期等信息来防止硬盘上软件的非法拷贝,造成主办升级崐后软件不能使用。
目前绝大多数PC的硬盘使用的是IDE/EIDE接口。这种接口的数崐据传输速度快,集成度高,在电脑中广泛使用。386以上的电脑中崐使用的多功能卡和主板上集成了这种接口,IDE接口控制器提供了崐一些控制命令来完成硬盘的读/写/校验等操作。其中有一条硬盘测崐试命令-“0ECH”,我们可以用这条命令对硬盘控制器直接编程来崐得到硬盘的各种参数和信息。向IDE控制器送入IDE控制命令可以按崐照下面的步骤:
①向端口3F6写入控制字节,建立相应的硬盘控制方式;
②检验硬盘控制器和驱动器的状态(检测端口的第7和第6两位),崐如果控制器空闲而且驱动器就绪,即可输入命令;
③完整的输入7个字节长度的命令块,一次写入端口1F1H-1F7H,崐不论是否需要,端口1F1H-1F6H对应的前6个字节的参数必须读出,崐端口1F7H的输出命令码为“0ECH”;
④检测端口1F7H的第7和第3两位,如果控制器空闲且第3位置1,崐表示操作结束,即可读取结果;
⑤通过端口1F0H读取100H字节到缓冲区;
⑥再次读取端口1F7H,判断第0位是否为0,如果为0,表示命崐令成功,否则表示命令失败;
读出的256字节信息的主要内容如下:
┏━━━━┯━━━━━━━━━┯━━━━━┓
┃ 偏移量 │ 内 容 │长度(字节)┃
┠────┼─────────┼─────┨
┃02H │柱面数 │2 ┃
┃06H │磁头数 │2 ┃
┃08H │每磁道所含的字节数│2 ┃
┃0AH │没扇区所含的字节数│2 ┃
┃0CH │每磁道所含的扇区数│2 ┃
┃14H │产品的序列号 │20 ┃
┃2AH │硬盘缓冲区容量 │2 ┃
┃2CH │ECC校验码的长度 │2 ┃
┃2EH │硬件修正号 │8 ┃
┃36H │硬盘型号 │40 ┃
┗━━━━┷━━━━━━━━━┷━━━━━┛
在上表的内容中,产品的序列号等信息是具有唯一性的信息,崐可以在软件注册器中使用。
二、软件注册器实现的软件原理
软件注册器的原理和数字签名类似,可以从上述的数据中选择崐用来作为注册的硬件代码的数据,对这些数据进行加密变换(本文崐的例子中是把硬盘的出厂编号和硬盘类型的前十个字节进行异或运崐算)生成硬件代码后,提供给用户,由用户用这个硬件代码向作者崐注册,作者收到这个硬件代码和注册费后,对用户提供的硬件代码崐进行第二次加密变换,生成注册密码后交给用户。用户得到这个密崐码后,用注册器写入应用软件中,注册器写入时也可以再进行一次崐加密运算。
应用软件运行时,利用这个密码进行上述加密过程的逆运算得崐到硬盘的唯一性信息,和硬盘中的相应信息进行比较;或者用硬盘崐的唯一性信息进行上述加密过程而得到注册密码,和写入应用软件崐中的注册密码进行比较,由此判定注册是否正确,如果正确,就认崐为注册成功,否则认为没有注册,对应用软件的功能进行限制。
注册器、应用软件、作者和用户的关系及信息往来如下图:
┏━━━━━┓ 硬件代码和注册费┏━━━┓
┌──┨软件注册器┠───→─────┨作 者┃
│ ┗━━┯━━┛ ┗┯┯━┛
│ 写│入 ││硬
│ 注│册 ││件
↑ 密↓码 ││代
┏━┷┓ ┏━━┷━━┓ 预设密码检验算法││码
┃用户┃ ┃ 应用软件 ┠────←─────┘↓
┗━┯┛ ┗━━━━━┛ │
│ │
│ 注册密码 ┏━━━┷━━━┓
└──────←─────────┨注册密码生成器┃
┗━━━━━━━┛
本文从上述的思路出发,用C语言实现了一个软件注册器,在崐使用中效果很好,下面介绍这个注册器的一个简化版本。这个简化崐版本中的三个程序都在HP VL 5/100电脑上,用Borlandc 3.1版集崐成环境和小模式编译运行成功。
三、增强软件注册器的反破解能力
软件的加密和解密是不断发展的,软件注册器也要增强本身的崐抗破解能力,才能为保护软件作者的合法权益作贡献。以CCED注册崐版本为例,其注册信息存放在CCED50.DAT文件中,而CCED.EXE文件崐本身则用一种可执行文件压缩程序进行了压缩,这一点可以从CCED崐5.18版本中CCED.EXE文件头部的“LZ”两个字母及CCED.EXE中没有崐编译程序的相关信息来判断,大多数的可执行文件压缩程序,具有崐一种使压缩后的可执行文件不能使用相应的工具来解压缩功能。例崐如PKLITE的注册版本中的“E”参数。因此我们可以利用可执行文崐件压缩软件来压缩相应的应用软件和软件注册器,使软件具有初步崐的抗破解能力。
由于软件注册器的加密手段主要就在注册器生成的硬件代码和崐注册密码的生成还原算法上。根据CCED使用的注册器的生成的硬件崐代码分析,使用的办法可能也是利用IDE/EIDE接口硬盘的一些命令,崐得到硬盘的一些特定参数,如硬盘的类型、生产厂家和出厂序列号崐等,这一点可以从CCED的注册器在使用非IDE/EIDE接口的286级电崐脑上不能测试出硬盘的生产厂家等信息来验证。由于硬盘的出厂序崐列号具有唯一性,是用来生成注册用的硬件代码的最佳数据,而且崐这些数据存放在ROM中,读写时速度非常快,用普通的调试工具无崐法监控。即使能够对读写ROM数据的相应端口进行监控,找出读写崐的数据,也无法利用已注册的机器上信息对此进行仿真,如果进行崐仿真,则硬盘驱动程序中的硬盘控制命令将不起作用,使硬盘无法崐正常运转。
现在有用来破解软件狗加密软件的工具“打狗棒”,用这种工崐具可以对软件狗中从并行口中读数据的过程进行进行监控并仿真解崐密,因此也可能会有人用这种办法来解密软件注册器,把用一个合崐法的注册密码对应的硬盘特征数据,用仿真程序提供给注册器和应崐用软件中的检测部分,这样对于一个用合法密码注册后的软件,可崐以使用有对应的硬盘信息的仿真程序在其它的硬盘上运行注册过的崐软件。虽然上面说明这种方法一般不可能实现,但是也许会有人会崐对这种办法进行改进后用来对软件注册器进行解密,在软件注册器崐中必须设法对抗这类解密工具。
为了对抗对注册器的静态分析和动态跟踪,增加软件注册器的崐加密运算的算法的复杂性是一个有效的方法。也可以在软件中使用崐其他加密软件中常用的反跟踪手段,如封锁键盘、关闭显示器等。
由于本文的例子使用C语言写的,增强抗破解能力的实现非常崐方便,读者可以充分发挥自己的创造力来增强抗破解能力。例如利崐用C语言中的“&”运算符的取地址能力,确定密码检测函数代码的崐位置和代码,然后仅对这个函数进行加密,而在这个函数执行前再崐解密,详细实现请参考有关的资料。
/*程序一,交给用户的注册器,用于生成硬件代码和对软件进行注册*/
#include
#include
/*取得IDE/EIDE接口硬盘的参数信息*/
void ide_para(unsigned char *buff)
{
unsigned char *p;
int i;
unsigned int flag2;
unsigned char flag;
p=buff;
outportb(0x1f6,0xa0);
outportb(0x1f7,0xec);
while(flag!=0x58)
flag=inportb(0x1f7);
for(i=0;i<256;i++) /*读出256字节的信息*/
{
flag2=inport(0x1f0);
*p++=(flag2<<8)>>8; /*把且出的字分割成两个字节*/
*p++=(flag2>>8);
}
cprintf("\n\r柱面数=%d",(int)(buff[3]*256+buff[2]));
cprintf("\n\r磁头数=%d",(int)(buff[7]*256+buff[6]));
cprintf("\n\r扇区数=%d",(int)(buff[0x0d]*256+buff[0x0c]));
cprintf("\n\r硬盘出厂编号=");
/*读出的信息中的两个字节位置颠倒,显示时反转*/
for(i=20;i<40;i++)
if(i%2==0)
cprintf("%c",buff[i+1]);
else
cprintf("%c",buff[i-1]);
cprintf("\n\r硬盘类型=");
for(i=54;i<94;i++)
if(i%2==0)
cprintf("%c",buff[i+1]);
else
cprintf("%c",buff[i-1]);
return;
}
main()
{
unsigned char buf[512],code[10],code2[20];
int i,choice,temp;
long int offset=5866L;
/*注册密码在应用软件文件中存放位置的偏移量,可以用工具崐软件从后面的CS.EXE中确定*/
FILE *fp;
cprintf("\n\r软件注册程序1.0版,王有翦,1998\n\r");
cprintf("1-生成注册硬件代码\n\r");
cprintf("2-注册\n\r");
cprintf("0-退出\n\r");
choice=getch();
switch(choice)
{
case '1':
ide_para(buf);/*读取硬盘信息*/
cprintf("\n\r这个硬盘的硬件代码为:");
for(i=0;i<10;i++)
{
code[i]=buf[20+i]^buf[54+i];/*生成硬件代码*/
/*用三位十进制整数显示硬件代码中的每个字符*/
if(code[i]<100&&code[i]>=10)
printf("0%d",code[i]);
else
if(code[i]<10)
printf("00%d",code[i]);
else
printf("%d",code[i]);
}
break;
case '2':
cprintf("输入你的注册密码:");
/*用三位十进制整数的形式接收注册密码中的每个字符*/
for(i=0;i<10;i++)
{
scanf("%3d",&temp);
code[i]=temp;
}
fp=fopen("cs.exe","r+w+b");
if(fp==NULL)
{
cprintf("文件cs.exe不存在\n");
exit(0);
}
fseek(fp,offset,SEEK_SET);
fwrite(code,sizeof(char),10,fp);
fclose(fp);
break;
case '0':exit(0);
}
return ;
}
/*程序二,软件作者使用的注册密码生成器,用于对用户提供的硬崐件代码进行确认和变换,并生成相应的注册密码*/
#include
#include
unsigned char code[20],c[4];
int temp,i;
main()
{
cprintf("软件注册密码生成程序1.0版,王有翦,1998\n\r");
cprintf("请输入注册的硬件代码:\n\r");
setmem(code,10,0);
for(i=0;i<10;i++)
{
scanf("%3d",&temp);
code[i]=temp;
}
/*对注册的硬件代码进行变换,生成注册密码*/
for(i=0;i<10;i++)
code[i]=code[i]^(i+128);
cprintf("注册密码为:");
/*用三位十进制整数输出注册密码中的每个字符*/
for(i=0;i<10;i++)
if(code[i]<100&&code[i]>=10)
printf("0%d",code[i]);
else
if(code[i]<10)
printf("00%d",code[i]);
else
printf("%d",code[i]);
}
/*程序三,在应用软件中对用户的注册情况进行检验,编译后的.EXEXE文件名为CS.EXE*/
#include
#include
void get_ide_para(unsigned char *buff)
{
unsigned char *p;
int i;
unsigned int flag2;
unsigned char flag;
p=buff;
outportb(0x1f6,0xa0);
outportb(0x1f7,0xec);
while(flag!=0x58)
flag=inportb(0x1f7);
for(i=0;i<256;i++)
{ flag2=inport(0x1f0); *p++=(flag2<<8)>>8; *p++=(flag2>>8); }
return;
}
main()
{
unsigned char buf[512],code2[10],code1[11]=" register \0";
/*code1中存放注册密码*/
int i,l; FILE *fp;
printf("软件注册器测试程序,王有翦,1998\n");
get_ide_para(buf);
for(i=0;i<10;i++) code1[i]=code1[i]^(i+128); /*密码还原成硬件代码*/
/*由读取的硬盘的有关硬件参数生成硬件代码*/
for(i=0;i<10;i++) code2[i]=buf[20+i]^buf[54+i];
if(strcmp(code2,code1))
printf("这个软件你尚未注册!");
else printf("注册成功!");
}
(主持人注:可以进一步参考:http://xiaoyueer.top263.net/note/ide.htm)
此问题由王有翦回答。
| |
|
|
| |
|
|