DELPHI和汇编的高手请进来,如何真正得到硬盘的ID(100分)

  • 主题发起人 主题发起人 angelsoft
  • 开始时间 开始时间
A

angelsoft

Unregistered / Unconfirmed
GUEST, unregistred user!
所谓真正的硬盘ID,就是印在硬盘外壳上的序列号,现已经有人证明,

确实可以编程得到,但是该硬盘ID在WIN9X系统下如何得到是一个问

题,有人使用VXD已经实现,我想问的是如何不用VXD,直接在程序中

实现硬盘序列号的读取,不知有哪位大虾知道。

(注意,是不用VXD的读取,用VXD的读取我已知道了)
 
高手在哪里,大虾在哪里?
 
Nt下当然好办,Win9x下怎么读确实不清楚。
你有vxd的方法,不如帖出来,大家看看。
 
温柔一刀:
好建议!!!
 
用VXD的方法我使用了一个控件,SMALLPORT,如有朋友需要的话可以向我索取
另外转登一个高手的文章,希望能对大虾们有所提示:
如何从Ring 3读取硬盘序列号
作者:丁凯

硬盘的序列号是厂家设定的,且只能用I/O指令读取,所以,这在以前的DOS时代
根本不是什么问题.方法非常简单,如下面的代码所示:
static int WaitIde()
{
int al;

while ((al=inp(0x1F7))>=0x80) ;
return al;
}

static void ReadIDE()
{
int al;
int i;
WORD pw[256];

WaitIde();
outp(0x1F6,0xA0);
al = WaitIde();
if ((al&0x50)!=0x50) return;

outp(0x1F6,0xA0);
outp(0x1F7,0xEC);
al = WaitIde();
if ((al&0x58)!=0x58) return;

for (i=0;i<256;i++) {
pw = inpw(0x1F0);
}
}

至此,关于IDE硬盘的信息已经在 pw 数组中了,需要注意的是该数组是一个 WORD
类型,硬盘的序列号存放于 pw[10] 开始的10个WORD中,使用时需要将每个WORD的
高低字节颠倒一下。

真正有点麻烦的是在Windows 95/98下,I/O指令作为特权指令在应用程序级别,即
Ring 3是不可使用的,所以上面的代码在执行到 WaitIde()时会陷到死循环中,原
因就是 IN 0x1F7 总是返回 0xFF

容易想到的解决办法是写一个VxD,因为VxD运行Ring 0级别上,即最高特权级上,所以
所有的指令都是可用的。当然,这没有任何问题,事实上我已经写了这样的 VxD,效果
是明显的,如果哪位有兴趣,可与我联系。

如果你是一个编程高手,这没有什么难度,所以不必看下去。
如果你连VxD也不会写,请参阅拙作"VxD入门教程"。

当然,如果连象读取硬盘序列号这样小的问题都要写个VxD,确实是一件令人生厌的事,
且不说既要额外装个Win 95 DDK,又要防止VxD出现错误使系统崩溃这种多余的工作
和担心,旦旦是发行程序时带个这么小的东东就让人看着扎眼(读硬盘序列号无非是为了
防止拷贝,这个小东东明显会提示别人应该如何破解)。

所以我推荐的方法是真接从 Ring 3 完成该功能,即在你的EXE文件中处理这件事,这
样一方面减小了编程难度,另一方面有利于实现防止拷贝的目的。

实现的方法出人意料的简单,不过,也还是需要 100 行左右的代码。

唯一的一个技术难点就是利用 CPU 的异常从 Ring 3 直接切换到 Ring 0。如果解决了
这个问题,那么整个程序就非常简单了,值得一提的是,由于该技术将代码切换到
Ring 0 运行,所以,....., 不用我多说了吧?

不象在实模式下,中断向量表位于内存地址的0:0处,每当中断发生时,无论是硬中断还
是软中断,CPU都会从该表中查找中断的入口位置,并执行相应的中断程序。在保护模式
下(包括V86方式),物理内存0:0处不再有中断向量表,甚至"0:0"这种表示方式也发生了
变化,原来的段址不复存在,代之以段选择器,中断向量也用中断描述符表(IDT)取代了,
这意味着当发生中断或异常时(异常只在保护模式下存在,可以把它当作中断看待),CPU
查找的是IDT,然后再根据查到的入口地址执行相应的中断处理程序。

关于这部分内容请参阅80386 (或以上) CPU的技术手册。

从上面可以看出,虽然查找的内容及方法发生了变化,但原理并没有变,如果要修改中
断入口,所需要修改的地方无非是变成了IDT而已。更妙的是,中断处理程序是运行在
CPU最高特权级Ring 0上,这就使得我们从Ring 3进行Ring 0级别的操作成为可能。

具体方法可以归结如下:
首先,取得系统 IDT,这可用 SIDT 指令一步到位,且不受特权级限制;
然后,修改 IDT 中某一中断的入口,使其指向我们自己的处理程序;虽然理论上IDT表
中的所有中断都可以使用,但我建议使用中断 3, 这个中断是给调试器用的,平常没啥
用(修改的方法请参阅IDT的格)。
最后,执行该中断。可以直接执行代码 INT 3,当然,在 Ring 3 上执行该指令必然会导
致CPU异常,于是,我们的处理程序就这样轻易而举地得到了控制权。

一旦得到CPU最高特权级的控制权,中断处理程序就可以进行任何平常在 Ring 3 级别上
不能够进行的操作了,当然也包括本文的主题:读取硬盘序列号。
说得再具体一些,就是将本文前面提到的代码放到中断处理程序中即可全部搞定了。

至于用 C 语言或是汇编语言,那就完全视个人情况了。

我采用的方法是用 C 语言加上内嵌的汇编,完整的程序代码不列在此处了,需要的话请
直接与本人联系(也省得有人未经允许抄俺的程序 :Q)

最后,需要说明的是,这种方法不可以在 Windows NT 下使用。是什么原因我就不多说
了。



一些题外话,实际上我写这篇文章的目的并不完全是为了读取硬盘的序列号(这东东毕竟
没多大用途,有些硬盘,如三星的 32543A 根本就没有序列号),主要的目的是想在从
Ring 3 获取 Ring 0 特权这个问题上做些尝试,希望有兴趣的朋友能够参予进来,公开
你所掌握的技术,大家共同提高编程水平。
还有一句话不能不说:本文写得较为匆忙,如有错误,敬请指正。


本人对上面的文章及代码保留所有权利.需要引用的请告之本人
 
既然你也是看dingkai的文章,那你有没有注意到
他的竹叶上已经有了上面所说的非vxd的源代码下载呢?

源代码为c+asm,把它改成delphi+asm不就可以了吗?
我已经改编成功,花了15分钟和3次死机的代价 :-)
读出的序列号完全正确。
 
To 温柔一刀:
太好了,这篇文章是我的一个朋友告诉我的,我并不知道DingKai的竹叶
地址,请你能否告诉我他的地址,另外将你的改编好的程序寄给我好吗,谢
了,我的EMAIL:yzsljh@elong.com
如此,你就等着拿分吧,呵呵!!!
 
To 温柔一刀:
也请Mail一份给我,Email:pux@soim.net,谢谢!!!
 
http://member.netease.com/~dingkai

翻译你们自己做吧,练练手,很容易的。
 
TO 温柔一刀:
想偷懒都不行,:(,好吧分全给你了,不过如果我翻译的不好的话,
再找你,:)
 
No problem,只要你再提一道“这段代码如何翻译成delphi”之类的问题就可以了

哈哈..开玩笑的。 :-)
 
后退
顶部