怎样向CMOS里面指定位置写标志信息?(不是想搞破坏,如CIH病毒,而是想利用该原理做软件的安装次数或日期限定的加密处理)(200分)

  • 主题发起人 主题发起人 2000
  • 开始时间 开始时间
2

2000

Unregistered / Unconfirmed
GUEST, unregistred user!
怎样向CMOS里面指定位置写标志信息?(不是想搞破坏,如CIH病毒,而是想利用该原理做软件的安装次数或日期限定的加密处理)
 
I/O地址70H是CMOS的地址口,71H是数据口,不同的主板
所用的CMOS存储器数量肯定不同,所以究竟把标志写在哪
才能躲开BIOS数据区并且不影响校验和恐怕得下一番工夫。

另:你要做的与CIH不同,你只写CMOS,CIH主要是写
BIOS程序区。
 
Routines here:

procedure WriteCMOS(Addr, Data:Byte);
begin
asm mov al , Addr
or al , 80h
out 70h, al
mov al , Data
out 71h, al
end;
end;

procedure ReadCMOS(Addr: Byte; var Data: Byte);
var
readData: Byte;
begin
asm mov al , Addr
or al , 80h
out 70h, al
in al, 71h
mov readData, al
end;

Data := readData;
end;

很可笑, 我没有办法在嵌入汇编里给引用参数赋值,
哪位大侠教我?
 
move @data, al
 
天,旧 CMOS 才 64 字节,新 CMOS 也不过 128 字节,你要用来干什么?破坏系统?
罢了,你要玩也就只能:
其中有几位是没有用(或者说是保留的:要是2000问题也象这样就好了),这就是
你能用的,不过需要重新计算效验值,不然保证出错!好象清华很久以前有一本介绍
286硬件 的书,上有关于 CMOS 数据的详细介绍。祝好运。
另 我对 CMOS 病毒不懂,的确不懂,因为CMOS既要存储系统信息,又要保存病毒
代码,这是我怎么也理解不了的,才128字节呀?!我搞了一个什么也不破坏的都
用了300多字节,谁能解惑?谢谢
 
CMOS病毒只是一个程序的入口而已, 最多几句jmp...
 
Attention CMOS-busters:

Here's what's happening for those not so sharp on their assembly language
directives.

To read from CMOS do the following:

write to port $70 with the address value to read or write.
write to port $71 with the new value or read the value of interest
from port $71.

CMOS is reasnably generic in some locations. Most noteable are the
locations $0-$F, (the time,date and timer settings) and the locations from
$10-$1F, (general system settings). The locations above $20 are usually
more subject to the whims of mfg's than the others which are reasonably
standard.

My example will be in C as ASM was just represented! I'll get to Delphi in
a minute.

write to port $70 (hex) with the address value of the CMOS memory location
that you are interested

outp(0x70,0x31); { tells CMOS we want to 'talk' to CMOS location 31hex }

next, read the desired value at port $71 or write a new value to the port.

outp(0x71, 0x10); { this writes the value 10 hex (16
dec) to CMOS location 31as previously defined }

OR

x = inp(0x71); { this reads the hex value from
CMOS location 31 as previously declared }

it is also good form to include a delay between the write to
port 70 and the read or write at port 71. This is more important in
assembly routines and maybe real fast cpu's then in higher level languages.
That's the purpose of the NOP in Leif's code example and also generally
recommended.

You will note that in Leif's ASM code two locations are stuffed into the
AX, 30 and 31. This is to allow for a quick load to search two addresses.
This code contains two instances, both CMOS reads. The memory values are
stored in two consecutive locations but I believe it's a case of most
significant byte last. And they also only concern the amount of memory
beyond 1 Mb as also stated below.

OK, ok, I know this is supposed to be Delphi but I'm a C programmer
reasonably new to Delphi and Pascal so to do this in Delphi probably
involves using Port or PortW but I haven't tried it yet so don't know exact
syntax. Probably pretty similar to C style though. Would be interested in
hearing from anyone that has done it that way. Couldn't really find an
example yet and haven't had time for exploring.

Of a rather important note, it should be pointed out that this method will
only read so much memory. Back in the old days, no one considered the vast
amounts of RAM available today system-wise and I believe that certain large
sizes of RAM will not be correctly loaded into CMOS. Therefore this is not
a cure-all concept. Some of this is caused by BIOS
shortcomings/short-sightings. Also, you will need a CMOS map to show what
locations are loaded for which system parameters. Some differences can
exist between different mfg's. This can be a rather messy job...

Here's the most important thing for budding CMOS editors to remember:

IF you edit a location between $10 and $2F then you WILL NEED to
calculate the NEW checksum by adding together all the location values from
$10-$2F and THEN WRITE the new value to $3E, $3F or YOU WILL GET A CMOS
CHECKSUM ERROR WHEN YOU REBOOT! GUARANTEED!!! THIS should concern you...

Also, don't try to test the values $0 - $1F. Time marches on, don't
you know...

[Monte Saager, kidvolt@teleport.com]
 
To Another_eYes:
Thanks a lot! *-^
 
警告:
最好不要改CMOS,而改用硬盘加密,软件加密不应有这么大
的权限,KV300就是你的前车之鉴。
 
嘿嘿,我就是搞反病毒的……
^-^
CMOS中是没有病毒的,所谓CMOS病毒只是会破坏CMOS数据信息的病毒,
如果这样也叫“CMOS病毒”,岂不是破坏硬盘的就叫“硬盘病毒”了?
破坏显示器显示信息的就叫“显示器病毒”了?——乱了嘛!

写CMOS信息的程序Pegasus已经给出了。至于写128byte的CMOS数据,也
是端口操作,但由于不通用,所以你也不要想了。 :(

如果要想加密,不必考虑CMOS,那儿不可能执行任何程序。cHengyAng的
问题提得很到位:"因为CMOS既要存储系统信息,又要保存病毒代码……",
这是不可能的!因为CMOS中永远不可能有一个Jmp指令可跳进去,也不可
能有一个Jmp可跳出来,它是数据块!而指令执行前是放在Mem中,执行中
是在CPU中,最多有cache可过渡!与CMOS是无关的!

CMOS中存放信息也不安全,因为鬼知道主板商什么时候发神经,要加点东
东在里头?

要加密,考虑硬盘吧!——在硬盘上找个扇区写数据就成了。——记得磁盘
卷标么?它只在目录项表中占一个记录,而没有指向任何的磁盘簇。由它申
请一个簇,慢慢记录吧! :)这是一种方法,尽管不好,但是一个思路。
至于更深的,你也不大能做得到!在win32中操作物理扇区,只有一个方法:
用VxD!!!这个,这个,嘿嘿,我也没搞懂!而且什么磁头步进,停放空间和
停放迟滞之类在DOS中能用的技术,一律只有考虑VxD了,而且安全性值得考
虑!

:(((((
 
又查了一下:目前有用 256 字节的 CMOS .可惜后面的都有专用性,不能占用 :-(.
另外现在的主板有些在启动时将 CMOS数据 调入BIOS ?!@#$(怎么可能,看来是我
没看懂),我记得有篇文章讲如何在'瘟9X'下如何直接对 I/O端口读写及调用中断,
如果那作者不是瞎说,从0面0柱2扇区到63扇区都可以使用(通过INT 13),
岂非..加密问题..随便找个位置..解决了?!
后语:
象往 CMOS 里写数据的方式,在不同主板上可能导致系统崩溃,我不太赞成.
在'晕倒死9X'里,我建议使用 REGISTER方法处理安装次数或日期限定,诸位意下如何?
一则:有大家风范
二则:安全、可靠
三则:减少编程麻烦、程序运行可靠性得到提高
谢谢 aimingoo 解惑。
 
1 You cannot write virus in Cmocs
2 agree amingoo and chenke donnot use cmocs to encrypt your software
use could use other media like hdd.
3 to write to a specify sector u could use VXD and u must write VXD
with C++ or other VXD writer program, and winnnt do not support VXD
the later version of windows do not use VXD
 
有劳各位大侠费心,谢谢!
对以上想法的解释:
我们都是做软件开发的,我相信有很多人都是以此谋生,近几年来作过许多工程,完成后¥¥¥总收不回来,搞的你心烦!当然,可以用软件狗做加密(姑且不说被解),但专用系统是不允许的,因此就琢磨用限定日期、安装次数、读取网卡的系列号(要求机器里必须有一块网卡)、CPU指纹、硬盘加密等等。
从以上大侠的讨论可知,对CMOS、BIOS写信息不通用,因此就不可实现!

aimingoo大侠的高见,给我很多启发,若对硬盘上的特殊位置写信息,而对硬盘做格式化又不破坏写的信息(如软盘指纹加密),也就能解决限定日期、安装次数等加密处理了!

不知各位大侠有无这方面的研究???
 
在分区表胡写一通.
 
多人接受答案了。
 
关于CMOS加密一问题,特引用易伟一文以C语言为例进行讨论:

CMOS有一个特点,就是关机后其中的信息不会丢失,除非电池没电或者人为使其受到破坏。
而且正常的DOS操作无法涉及到它,具有非常好的隐蔽性。在计算机系统中要实现CMOS的读写
可以通过70H和71H两个I/O(输入输出)端口来操作。端口70H是一个字节的只写端口,可以
用它来设置在CMOS中读取数据的位置。71H用来读写由70H所设置的CMOS读取位置上的数据。
因此,我们可以用程序来实现任意一个CMOS单元的读写,自然也就可以利用CMOS来进行加解密了。
如果想使软件只在固定的机器上运行,可以在安装软件时将CMOS数据中第10H至2DH字节(因为00H
至0FH字节的数据随时可能改变)读出,写入某一个磁盘文件,再在软件的主执行程序中加入检查配置
是否改变的程序段,如检查发现不正确则拒绝执行。逐个字节检查的方法最准确,但是太麻烦,通常
我们只需检查第10H至2DH字节的和便可以满足要求。下面用C语言给出实现这一操作的程序。其它语言
的实现与此类似,只是访问I/O端口的指令和函数不同而已。
在安装程序中加入以下程序段,可以将CMOS中第10H至2DH字节的数据之和写入文件USER_ID.CHK。
#include ″stdio.h″
main()
{
unsigned int i,cmosnumsum=0;
FILE ?fp;
for(i=0x10;i<=0x2d;i++)/?求得安装软件的机器的CMOS中10H至2DH字节的
和?/
{  outportb(0x70,i);
cmosnumsum+=inportb(0x71);
}
if((fp=fopen(″user_id.chk″,″wb″))==NULL)/?打开记录数据的文件 ″
USER_ID
{ printf(″Write error!/07″);
exit(0);
}
printf(″/n%d/n″,cmosnumsum);
fwrite(&cmosnumsum,2,1,fp);
fclose(fp);
}
在软件主执行程序中加入以下程序段,可以将CMOS中第10H至2DH字节的数据和与记载于
文件“USER_ID.CHK”中的数据进行比较,判断是否符合。
#include ″stdio.h″
main()
{  unsigned int i,cmosnumsum=0;
unsigned int filenum;
FILE ?fp;
for(i=0x10;i<0x2d;i++)/?求得软件运行的机器的CMOS中10H至2DH字节的和?/
{ outportb(0x70,i);
cmosnumsum+=inportb(0x71);
}
if((fp=fopen(″user_id.chk″,″rb″))==NULL)/?打开记录CMOS数据的文件?/
{ printf(″System error!/07″);
exit(0);
}
fread(&filenum,2,1,fp);/?读入记录在文件上的CMOS数据?/
printf(″/n%d/t%d/n″,cmosnumsum,filenum);
if(filenum!=cmosnumsum)/?将当前CMOS中的数据与文件中的数据进行比较?
?是否相同?相同则允许运行?/
 { printf(″Your config was changed , please re-run install.exe !/07″);
 exit(0);
 }
 else
 {printf(″Your system is right ! /07Congratulations !/07″);
 }
 fclose(fp);
}
下面,让我们来看看AV95的自动记录使用次数的功能是如何干得堂而皇之而又不为人知的。
在CMOS的数据结构中,第1BH至2DH字节保留未用。嘿嘿,正好让我们动点手脚。我们可以
将数据随意地写到这里而不用担心会被通知犯规并被扣除“信用点”,至于写些啥,当然是用
来记录你的劳动成果被免费使用的次数,也可以是版权信息、密码等。在CMOS的数据结构中,
第34H至7FH字节也是保留未用的,但这里不能乱写,许多BIOS厂家使用这里留下自己的版权信息
或者密码。
在CMOS中,第2EH和2FH两个字节存放的是第10H至2DH单元中的数据之和,高位在前,低位在后。
在系统自检时,BIOS还要检测该两处的值是否等于10H至2DH字节的数据之和。如果不等,则认为
CMOS出错,停止引导,提示出错及按〈F1〉进行修改。所以,我们在进行CMOS的操作时一定要保证
这两个字节的正确。最稳妥的解决方案是:建立一个2FH-10H+1=20H即32个字节的数组(注意,
不是128字节,因为00H至09H是系统实时钟,读出后再写回会使其走时不?0H至2FH字节的数据依次读入,
修改某些字节后将前30个元素和的高位赋给数组的第30号元素,低位赋给数组的第31号元素,再将数组
写回到CMOS。
下面的程序段可以实现这个操作,将其加入到你的程序中,便可以记录使用的次数。该程序段利用
CMOS中第25H字节记录使用次数,每使用一次使其减1,并使用CMOS中第26H字节记录是否为首次使用。
若26H处为0并且25H为0,则为首次使用,将剩余使用次数29记入25H处,并将26H处置1。若26H处为0并且25H处
为小于30大于0的值,则将25H处减1,显示剩余使用次数;若26H为1且25H为0,则认为使用次数已经用尽,
给出提示,结束运行。

#define NEVER 2/?定义第一次使用的标志量?/
#define OVER 0/?定义可以使用的标志量?/
#define ENABLE 1/?定义使用次数已尽的标志量?/
main()
{
unsigned char data[32];
unsigned int bytesum=0;
unsigned char k=0;
unsigned int i=0;
clrscr();
for(i=0x10;i<=0x2f;i++)
{  outportb(0x70,i);
data[i-0x10]=inportb(0x71);
}
bytesum=0;
for(i=0x10;i<=0x2d;i++)
{ bytesum+=data[i-0x10];
}
printf(″/nThese are CMOS data without changed:/nsum 10h--2dh:%x/n″,bytesum);
for(i=0x10;i<=0x2f;i++)printf(″%x/t%x/t″,data[i-0x10],i);
printf(″Press any key to chang seek 25h ....../n″);
getch();
if((data[0x25-0x10]<30)&&(data[0x25-0x10]>0)&&(data[0x26-0x10]==1))
k=ENABLE;
if((data[0x25-0x10]<=0)&&(data[0x26-0x10]==1))
k=OVER;
if((data[0x25-0x10]==0)&&(data[0x26-0x10]==0))
k=NEVER;
switch(k)
{ case 1:
{  data[0x25-0x10]-=1;
printf(″/nThis is %dth time ...... last %d times !/n/07″,30-data[0x25-0x10],data[0x25-0x10]);
break;
}
case 0:
{  printf(″/nYour times is over ! Please register !/n/07″);
break;
}
case 2:
{  data[0x25-0x10]=29;
data[0x26-0x10]=1;
printf(″/nThis is the first time ...... last 29 times !/n/07″);
break;
}
}
bytesum=0;
for(i=0x10;i<=0x2d;i++)
{ bytesum+=data[i-0x10];
}
data[0x2e-0x10]=bytesum>>8;
data[0x2f-0x10]=bytesum<< 8 >>8;/?利用位运算将和赋给相应的数组元素 /
printf(″/nThese are had changed CMOS data which is in momorey:/nsum
10h--2dh:%x/n″,bytesum);
for(i=0x10;i<=0x2f;i++)printf(″%x/t%x/t″,data[i-0x10],i);
printf(″Press any key to write back to CMOS !/n″);
getch();

for(i=0x10;i<=0x2f;i++)
{  outportb(0x70,i);
outportb(0x71,data[i-0x10]);
}
printf(″/nDATA WRITED BACK TO CMOS !!!/n/07/07/07″);
for(i=0x10;i<=0x2f;i++)
{  outportb(0x70,i);
data[i-0x10]=inportb(0x71);
}
bytesum=0;
for(i=0x10;i<=0x2d;i++)
{  /?此处可以加上你的软件的主要内容了?/
bytesum+=data[i-0x10];
}
printf(″/nThese are had changed CMOS data in CMOS:/nsum 10h--2dh:
%x/n″,bytesum);
for(i=0x10;i<=0x2f;i++)printf(″%x/t%x/t″,data[i-0x10],i);
printf(″Press any key to over ......″);
getch();
}
此程序对于在CMOS中将硬盘参数设置为AUTO的机器无效,因为每次机器重新启动自动检测硬盘时,
就将CMOS数据更新了。

一个子儿都没有?
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部